7
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ちょっとした工夫で効率化!02【PR】パソナテックAdvent Calendar 2020

Day 14

iPhoneのスクリーンタイムをOCRで記録してみた

Last updated at Posted at 2020-12-15

はじめに

スマホ、触りすぎていませんか?

私は隙があればついついスマホでYouTubeやSNSを長々と見てしまいます。YouTubeを始めた芸能人も多く、無限にコンテンツを楽しめてしまいますよね。コロナ渦で自宅にいることが増えたこともあってか、スクリーンタイムを見て唖然としてしまう日も少なくありません...。

そんな中、スクリーンタイムをSNSに投稿して勉強のモチベーションにしている受験生を見て、こういう使い方もあるんだなぁと感心しました。
とはいえ、わざわざ設定画面を開いてスクショを撮り、それをトリミングしてSNSに手動で投稿するのは少々面倒に感じます()

幸いなことに、macからも同じApple IDで登録されてデバイスのスクリーンタイムを見ることができます。また、macにはAutomatorという操作を自動化するアプリケーションがあります。
さらに、Googleが公開しているCloud Vison APIを使えば、画像から文字を抽出することができます。

これらを上手いこと使って自動で「iPhoneのスクリーンタイムをデータとして記録する」までを行ってみました。
日々の生活を記録することで自己管理を効率化できるのではないかと思います!

スクリーンタイムについて

アートボード – 4.png

スクリーンタイムで見れる項目には、

  • App使用時間
  • 通知
  • 持ち上げ/再開回数

があります。
macのスクリーンタイム画面からは、サイドバーからこれらを選択して各項目の利用状況のグラフを見ることができます。注目すべきはシステム環境はウインドウサイズが一定で、スクリーンタイム内の文字やグラフの配置も同じような箇所にあることです。そのため、OCRで読み取りたい箇所だけを決め打ちでトリミングできます。

Automator

文字認識をしたいスクリーンタイムの画像を取得するためにAutomatorを使います。
Automatorの大まかな流れはこのような感じです。

  1. システム環境設定を開く
  2. 操作を記録して、スクリーンタイムを開き、取得したいデバイスを選択する
  3. 「App使用時間」「通知」「持ち上げ/再開回数」それぞれでスクリーンショットを撮影 & OCRしたい箇所をトリミング
  4. トリミングした画像をくっつけてVisonAPIでテキスト取得、スプレッドシートに記録

Automator

Automatorの詳細
#### システムの外観モードを変更 起動したタイミングで外観モードをライトに変更しています。

AppleScript

「アプリケーションを開く」でシステム環境設定を開くと画面が手前にならないことがあり、操作を記録のステップで処理がコケてしまうのでAppleScriptで起動しています。

tell application "System Preferences"
	activate
end tell

操作を記録

Automatorアプリの:red_circle:(記録)ボタンを押して、システム環境設定 > スクリーンタイム > デバイスの選択 > 日付を昨日に変更 までの流れをを記録させています

アートボード – 5 3.png

シェルスクリプトを実行

screencaptureコマンドで画面のスクリーンショットを撮影します。-lオプションで指定したwindow1dの画面を撮影することができます。また、-xは撮影音OFF、-oはスクリーンショットの影をなくすオプションです。
前の手順でクリックした直後に撮影しないように念のためシェルスクリプトの最初でsleep 1sとしています。

sleep 1s
dir="$HOME/lifelog"
filepath=$dir/`date -v -1d +%Y%m%d`_screentime.png
crop="/tmp/cropped_1.png"
screencapture -xo -l$(osascript -e 'tell app "システム環境設定" to id of window 1') $filepath
/usr/local/bin/convert $filepath -crop 828x574+466+152 $filepath  # パスが通っていないので、フルパスで書く
/usr/local/bin/convert $filepath +repage -crop 400x60+20+60 $crop

操作を記録

システム環境設定のサイドバーにある「通知」のクリック操作を記録しています。「通知」をクリックした後は上記と同じ内容のシェルスクリプトを実行します。「持ち上げ/再開」でも同様に行います。

アートボード – 5.png

画像の結合とVisionAPI

/usr/local/bin/convert /tmp/cropped_1.png /tmp/cropped_2.png /tmp/cropped_3.png -append /tmp/combined.png
python record_screentime.py  # Vision APIとシートに記録

スクリーンショットとトリミング

macでは、screencaptureコマンドでCLIからスクリーンショットを撮影できます。
トリミングにはImageMagickのconvertコマンドを使用しています。-cropオプションの値には、(width)x(height)+(left)+(top)を指定しています。
また、一度cropした画像にさらにcropしようとするとconvert: geometry does not contain imageというエラーが出てしまいましたが、-cropの前に+repageをつけることで解消できました。

# ウインドウを指定してスクリーンショットを撮影
screencapture -xo -l$(osascript -e 'tell app "システム環境設定" to id of window 1') screentime.png
# crop
convert screentime.png -crop 828x574+466+152 screentime.png
# OCRしたい箇所でさらにcrop
convert screentime.png +repage -crop 400x60+20+60 screentime_cropped.png

上記コマンドでOCRで文字認識したい箇所でcropすると、

  • App使用時間

cropped_1.png

  • 通知
    cropped_2.png

  • 持ち上げ/再開回数
    cropped_3.png

のようになります。これらを結合した画像をVisino APIに投げます。画像の結合は、以下のコマンドで行いました。+appendで縦方向、-appendで横方向に結合できます。

convert /tmp/cropped_1.png /tmp/cropped_2.png /tmp/cropped_3.png -append /tmp/combined.png

結合した画像

combined.png

これで準備完了です。

Vision APIとシートに記録

いよいよ準備した画像を使って、文字認識を行ってデータとして保存します。
以下の記事などを参考にさせていただきました。:bow:

import gspread
import json
from datetime import datetime, timedelta
from oauth2client.service_account import ServiceAccountCredentials 
import os
import io
import re
from google.cloud import vision

credential_path = '【サービスアカウントキーのパス】'

os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = credential_path
file_path = "/tmp/combined.png"
with io.open(file_path, "rb") as image_file:
    content = image_file.read()
image = vision.Image(content=content)

client = vision.ImageAnnotatorClient()
response = client.text_detection(image=image)
data = response.text_annotations[0].description.split()  # [0]でfull textを取得

scope = ['https://spreadsheets.google.com/feeds','https://www.googleapis.com/auth/drive']
credentials = ServiceAccountCredentials.from_json_keyfile_name(credential_path, scope)
gc = gspread.authorize(credentials)
SPREADSHEET_KEY = '【スプレッドシートのキー】'
worksheet = gc.open_by_key(SPREADSHEET_KEY).sheet1

yesterday = datetime.today() - timedelta(days=1)
date = datetime.strftime(yesterday, '%Y/%m/%d')

d = re.findall("\d+", data[0])  # 'xx時間yy分` -> ['xx','yy']
d = list(map(int, d))
if len(d) == 2:  # xx時間yy分の場合
    data[0] = d[0]* 60 + d[1]
elif len(d) == 1:  # yy分の場合
    data[0] = d[0]

data = list(map(int, data))
data.insert(0, date)
worksheet.append_row(data, value_input_option="USER_ENTERED")

実行すると...
スクリーンショット 2020-12-15 20.44.23.png

スクリーンタイムのデータがシートに反映されました!
あとはAutomatorのアプリを起動すれば今までの処理を自動で行ってくれます。(本当はcronで設定したかったけど、画面操作があるためできませんでした。。)

ちなみに、VisionAPIを使った文字認識の結果はこうなりました。緑がParagraph、黄色が文字を表しています。きれいに認識できていますね。
スクリーンショット 2020-12-15 20.47.28.png

おわりに

自動化ソフトや画像認識のツールを使って、スクリーンタイムをログに残してみました。せっかくならスクショだけはでなくて数字で記録に残せるといいですよね。
VisionAPIは1ヶ月1000リクエストまで無料なので毎日スクリーンタイムを記録して問題なさそうです。

今のところスクリーンタイムを記録する術は英語でググっても見つからなかったので、この記事が誰かの参考になれば幸いです。

(Appleさん、スクリーンタイムもヘルスケアから読み取れるようにしてください)

7
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?