BETA

リングフィットアドベンチャーのデータをiPhoneのヘルスケアに追加する

投稿日:2020-06-18
最終更新:2020-06-18

任天堂のフィットネスゲーム「リングフィットアドベンチャー」の運動ログをiPhoneのヘルスケアアプリに追加するためのアプリを作成しました。Githubからソースコードを取得することができます。

RingFitConnect
https://github.com/watanabetoshinori/RingFitConnect

アプリの構成

リングフィットアドベンチャーには運動ログを外部に連携するためのAPIやアプリはまだ提供されていません。そのためカメラで撮影したゲーム画面から文字列を認識して運動ログを取得しています。

ゲーム画面の撮影と文字列認識にはiOSのVisionフレームワークを使用しています。文字列認識はiOS13からサポートされた機能であり、日本語には未対応ですが今回の用途では問題ありません。認識された文字列をもとにHealthKitのワークアウトを作成して登録します。登録されたワークアウトがヘルスケアアプリに表示されます。

対象画面

リングフィットアドベンチャーで運動ログが表示されるのは以下の2画面です。

  • フィットネス終了時に表示される「本日の運動結果」
  • マイメニューから確認できる「運動ログ」

表示される運動ログは同じですが、両画面では表記に違いがあります。

上が「本日の運動結果」、下が「運動ログ」の文字列です。「本日の運動結果」では大きさの異なるフォントが組み合わせて使用されており、文字列認識では"19153 Cal"のようなありえない値として認識される事がありました。「運動ログ」は画像を正確に撮影できていれば誤認識は発生しづらく、さらに活動時間に文字列(分/秒/min/sec)が含まれないという利点があります。

アプリの用途を考えると、フィットネス終了時にいつも表示される「本日の運動結果」を対象とした方がわかりやすいのですが、認識精度の問題があるため今回は「運動ログ」画面のみを対象としています。

ゲーム画面の撮影

対象の画面を撮影します。撮影にはVisionフレームワークが提供するVNDocumentCameraViewControllerクラスを使用しました。
このクラスはカメラの起動と撮影、そして撮影した画像の補正機能まで備わっており、ゲーム画面の撮影もこのViewControllerで実現できます。

文字列認識

撮影した画像から文字列を認識します。Visionフレームワークを使用した文字列認識は以下のようにシンプルなコードで実装できます。

let request = VNRecognizeTextRequest { (request, error) in  
    let observations = request.results as? [VNRecognizedTextObservation] ?? []  

    // 文字列の矩形(くけい)  
    // observation.boundingBox  

    // 認識された文字列  
    // observation.topCandidates(1)[0].string  

}  

let handler = VNImageRequestHandler(cgImage: image, options: [:])  
try? handler.perform([request])  

Visionの認識結果から必要な情報を取り出し、日付ごとの運動ログとしてグルーピングします。今回のアプリではサイズの固定されているスクリーンショットではなく、利用者がカメラで撮影した画像を使用するため、固定の座標値をもとにした値の判別を行うことは困難です。

対象である「運動ログ」画面を見ると以下の構成が繰り返されていることが分かります。

  • 日付
    • 活動時間
    • 消費カロリー
    • 走行距離

それぞれの値について、日付は「MM/dd」、活動時間は「hh:mm:ss」、消費カロリーは「00.00 kcal」、走行距離は「00.00 km」のように特徴が見つかります。"00.00"と"kcal"が個別の文字列として認識されていると判定がかなり面倒になりますが、幸いにもVisonの文字認識では"00.00 kcal"として期待通りに認識してくれているため、正規表現を使用して文字列がどの値に該当するかを判別します。

値を判別できたら、日付ごとにグルーピングを行います。文字列の矩形からY軸の値を取得し、画面上部に出現する順に並べます。活動時間、消費カロリー、走行距離は出現順序が入れ替わる可能性はありますが、Y軸上で直近にある日付に紐づければOKです。

ワークアウト作成

日付ごとにグルーピングされた運動ログが準備できたので、HealthKitのワークアウトとして登録します。HKWorkoutを作成し、HKHealthStoreに保存します。

let workout = HKWorkout(activityType: .fitnessGaming,  
                               start: start,  
                                  end: end,  
                                  duration: durationInterval,  
                                  totalEnergyBurned: calorieQuantity,  
                                  totalDistance: distanceQuantity,  
                                  metadata: nil)  

HKHealthStore().save(workout) { (success, error) in  
    // 保存完了  
}  

activityTypeにはfitnessGamingというピッタリな値があったのでそれを指定しています。また「運動ログ」画面からはフィットネスの開始時間と終了時間が取得できないため、0:00を開始時刻としています。

ワークアウトを追加すると、アプリに登録内容が表示されます。この画面ではアプリからヘルスケアに登録した全件が表示されます。

ヘルスケアアプリにも登録した内容が反映されています。他のヘルスデータと同様に、グラフから運動量の推移や継続期間などをチェックすることができます。

  • 運動ログの詳細画面にはフィットネスごとの実行回数も表示されています。フィットネスはゲームの進行状況によって変わるため、今回のように値だけを正規表現で判別する方法では対応できません。Visionの日本語対応を待つか、TesseractなどのOCRライブラリやオンラインの文字列認識サービスを利用する必要があります。
技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

⭐オススメ技術ブログ⭐

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう