やりたいこと
iOS14以降のCoreMLでは、体や指の特徴点座標データを取得できます。この特徴点座標を機械学習用の入力データとし、Python環境にて推論モデルの構築を目指しています。iOSデバイスで取得するリアルタイム動画のSampleBufferに対しては、HandPoseRequestやBodyPoseRequestすることで特徴点座標を取得できるようにはなりました。しかし、今後(ネット動画なども活用できるようにして)機械学習用に大量の訓練データが欲しいとなると、汎用的な動画ファイルを元データに使えるようにしておく必要があります。動画ファイルをクラウドストレージに保存し、必要なファイルを読み出して特徴点座標のリストを返す仕組みの構築を試みました。
特徴点座標取得に関しての以前の投稿はこちら
keypointsMultiArrayから機械学習用データを取得する
Firebase Cloud Storageに保存した動画の取得方法
Firebase Cloud Storageに保存したmp4ファイルを再生するだけなら、こちらの公式サイトにあるように3つのダウンロード方法があります。
Apple プラットフォームで Cloud Storage を使用してファイルをダウンロードする
- メモリ内の NSData にダウンロードする
- デバイス上のファイルを表す NSURL にダウンロードする
- オンラインのファイルを表す NSURL を生成する
SampleBufferはlocalURLに対してならば動画ファイルからでも取得できるものの、remoteURLのファイル(オンラインのファイル)に対して取得しようとするとエラーが起きるようです。ネット上に出回る動画に対して簡単に画像情報を取得させないようにする配慮でしょうか。それとも技術的な問題でしょうか。いずれにせよ、ここが今回一番躓いた点です。今回は2の方法を採用しました。
ローカルファイルの保存場所
mp4ファイルを一時的に保存するローカルURLを以下のように設定します。
let path = "file://" + NSHomeDirectory() + "/tmp/video.mp4"
let localURL = URL(string: path)!
ローカルmp4ファイルのSampleBuffer取得
以下のサイトが大変参考になりました。
iOSで動画ファイルからフレームデータを抽出する実装方法の調査メモ
これによると
・AVAssetReaderを使う
・AVAssetImageGeneratorを使う
・VTDecompressionSessionを使う
の3つの方法があるとのことですが、情報が多いのは最初の方法でサンプルコードの記載もあります。これに従って、ほとんどコピペでmp4ファイルのサンプルバッファーが取得できるようになります。
import AVFoundation
func setupReader(url: URL){ //ローカルファイルURLを指定
let avAsset = AVAsset(url: url)
let avAssetReader = try! AVAssetReader(asset: avAsset)
guard let videoTrack = avAsset.tracks(withMediaType: AVMediaType.video).last else {return}
let readerOutputSettings: [String: Any] = [kCVPixelBufferPixelFormatTypeKey as String : Int(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange)]
let readerOutput = AVAssetReaderTrackOutput(track: videoTrack, outputSettings: readerOutputSettings)
avAssetReader.add(readerOutput)
avAssetReader.startReading()
/*
以下のwhile節でSampleBufferが1フレームずつ取得される。このSampleBufferに対して必要な
処理(今回の目的ではHandPoseRequest)を行えばよい。
*/
while let sampleBuffer = readerOutput.copyNextSampleBuffer() {
//ここでお望みの処理。今回の目的では特徴点座標を取得するメソッドを適用
}
}
これでCloud Storageに保存したmp4ファイルに対して、iOSデバイスでリアルタイムに撮影した動画と同様に手や体の特徴点情報が取得できるようになりました。
補足
外部ストレージに保存したmp4ファイルに対して、特徴点情報の取得ができるようになりましたが、鏡像の情報となっていることがわかりました。mp4ファイルにbackカメラかfrontカメラかの情報が欠落して(あるいは取得できていなくて)、frontカメラで撮影したにも関わらずbackカメラ(普通の撮影)として処理したことが原因と思われます。機械学習用訓練データにする際には、この辺りも注意が必要です。handlerのorientationを変更してmirror画像に対しても特徴点情報取得するという方法もありますが、簡便にはx座標だけ(1-x)としたデータセットを用意しても良さそうです。