WWDC Quick Look 💓 By SwiftGGTeam
Build an Action Classifier with Create ML

Build an Action Classifier with Create ML

元の動画を見る

ハイライト

Create ML は、2020 年にアクション分類テンプレートを追加します。これは、Vision フレームワークの Body Pose Estimation に基づいてビデオ内の骨格キー ポイントを抽出し、これらのキー ポイントを使用して分類モデルをトレーニングします。


主要内容

これまで、Create ML はモーション センサー データを使用してアクティビティ分類モデルをトレーニングできました。問題は、多くのアクションには時計やセンサーの入力がなく、電話、カメラ、またはビデオだけが必要であることです。フィットネス動作、体操トレーニング、ダンス動作はすべてこのカテゴリに分類されます。

アクション分類は、入力をビデオ内の一連の身体姿勢に変換します。 Vision フレームワークはまず各フレームから人間のポーズを抽出し、次に Create ML が一定期間内のポーズ シーケンスを分類モデルにトレーニングします。モデルの出力は、ジャンピング ジャック、ランジ、スクワットなどの事前定義されたアクション ラベルです。

このプロセスは 2 つの段階に分かれています。トレーニングフェーズでは、開発者は「ML アプリの作成」でアクションごとに分類されたビデオを準備し、アクションの長さと拡張を設定してエクスポートします。 .mlmodel。実行フェーズでは、アプリは Vision を使用してカメラ フレームまたはビデオ フレームからポーズを抽出し、60 の連続フレームを組み立ててモデル入力を作成し、アクション ラベルと信頼レベルを取得します。

Session はまた、境界を明確にしました。このモデルは、Vision の人間の姿勢推定によって駆動され、人体の動きに適しています。動物や物体の動きを認識するのには適していません。トレーニング データも、人物、全身、安定した映像、一貫したフレーム レートを中心に準備する必要があります。

詳細

フォルダーまたはアノテーション ファイルを使用してトレーニング データを準備する

(03:45) トレーニング データの基本的な形式はビデオ ファイルのセットです。各ビデオにはアクションが 1 つだけ含まれており、フォルダー名はモデルによって予測されるラベルです。セッションの例では、ジャンピング ジャックやスクワットなど 5 種類のスポーツを収集し、2 つのネガティブ カテゴリも追加します。 other そして none

(05:28) モンタージュ ビデオに複数のアクションが含まれている場合は、CSV または JSON を使用して各アクションの開始時刻と終了時刻をマークします。公式コード スニペットは、JSON 構造を示します。

[
    {
        "file_name": "Montage1.mov",
        "label": "Squats",
        "start_time": 4.5,
        "end_time": 8
    }
]

キーポイント:

  • file_name アクション クリップを含むビデオ ファイルを指します。
  • label は、このビデオに対応するアクション カテゴリであり、モデルによって予測されるラベルになります。
  • start_time そして end_time ビデオ内のアクションの時間範囲をマークします。
  • この方法は、他人がカットした素材やインターネットから入手したミックスカット素材に適しています。

Create ML でアクション ウィンドウを設定する

(07:52) アクション継続時間は、トレーニング中の最も重要なパラメータの 1 つです。複雑な動きには、10 秒かかるダンスの動きなど、より長い時間枠が必要です。短い反復的なフィットネス動作では、2 秒のウィンドウを使用できます。 Create ML は、ビデオのフレーム レートとアクションの継続時間に基づいてフレーム数を計算します。 Session のフィットネス モデルは、予測ウィンドウとして 60 フレームを使用します。

(08:39) 拡張は、既存のビデオを使用してトレーニングのバリエーションを生成します。セッションでは水平反転が実証されました。トレーニング ビデオ内のキャラクターがすべて左を向いている場合、水平反転によってミラー サンプルが生成され、モデルが両方向をカバーできるようになります。

(09:40) トレーニングは 2 つのステップに分かれています。最初のステップは特徴抽出です。ビジョンは各フレームを分析し、身体上の 18 個のランドマーク (キー ポイント) の位置をエンコードします。各キーポイントは、x 座標、y 座標、および信頼度を記録します。 2 番目のステップでは、これらの姿勢特徴を使用して分類モデルをトレーニングします。

Vision を使用してビデオや写真からポーズを抽出する

(14:05) モデルは Vision によって抽出された人間のポーズを受け取り、最初に元のビデオからポーズ抽出が行われます。最小エントリーポイントは VNDetectHumanBodyPoseRequest:

import Vision
let request = VNDetectHumanBodyPoseRequest()

キーポイント:

  • import Vision 人間の姿勢推定のフレームワークを紹介します。
  • VNDetectHumanBodyPoseRequest ボディ ポーズ リクエストを作成して、ビデオ フレームまたは写真内の人間のキー ポイントを検出します。

(14:10) ビデオ ファイルを処理するときに、このリクエストを VNVideoProcessor:

import Vision
let videoURL = URL(fileURLWithPath: "your-video-file.MOV")
let startTime = CMTime.zero
let endTime = CMTime.indefinite

let request = VNDetectHumanBodyPoseRequest(completionHandler: { request, error in
    let poses = request.results as! [VNRecognizedPointsObservation]
})

let processor = VNVideoProcessor(url: videoURL)
try processor.add(request)
try processor.analyze(with: CMTimeRange(start: startTime, end: endTime))

キーポイント:

  • videoURL 分析するビデオ ファイルを指します。
  • startTime そして endTime 分析範囲を定義します。ここではビデオの最初から最後まで分析されます。
  • 得る [VNRecognizedPointsObservation] から request.results 完了ハンドラー内で。
  • VNVideoProcessor リクエストをビデオ フレームに適用する責任があります。
  • analyze(with:) 指定された時間範囲の分析を実行します。

(14:26) 写真またはカメラ フレームを処理する場合、セッションは VNImageRequestHandler:

import Vision
let request = VNDetectHumanBodyPoseRequest()
// Use either one from image URL, CVPixelBuffer, CMSampleBuffer, CGImage, CIImage, etc. in image request handler, based on the context.
let handler = VNImageRequestHandler(url: URL(fileURLWithPath: "your-image.jpg"))

try handler.perform([request])
let poses = request.results as! [VNRecognizedPointsObservation]

キーポイント:

  • 同じ VNDetectHumanBodyPoseRequest 画像入力に使用できます。
  • への入力 VNImageRequestHandler 画像 URL または CVPixelBufferCMSampleBufferCGImageCIImage
  • perform([request]) 姿勢検出を実行します。
  • その結果も [VNRecognizedPointsObservation]

連続ポーズをモデル入力に結合する

(14:57) Create ML によってエクスポートされたアクション分類モデルは、3 次元のマルチ配列を受け取ります。各フレームの姿勢はまず次のように変換されます。 [1, 3, 18]、60 個のフレームが組み立てられます。 [60, 3, 18]:

import Vision
import CoreML

// Assume pose1, pose2, ..., have been obtained from a video file or camera stream.
let pose1: VNRecognizedPointsObservation
let pose2: VNRecognizedPointsObservation
// ...

// Get a [1, 3, 18] dimension multi-array for each frame
let poseArray1 = try pose1.keypointsMultiArray()
let poseArray2 = try pose2.keypointsMultiArray()
// ...

// Get a [60, 3, 18] dimension prediction window from 60 frames
let modelInput = MLMultiArray(concatenating: [poseArray1, poseArray2], axis: 0, dataType: .float)

キーポイント:

  • keypointsMultiArray() は、Vision が提供する便利な API で、ポーズのフレームをモデルに必要なマルチ配列に変換します。
  • 単一フレーム配列の次元は次のとおりです。 [1, 3, 18]、1 つの時点、3 つの数値チャネル、および 18 の身体キーポイントに対応します。
  • MLMultiArray(concatenating:axis:dataType:) 複数のポーズのフレームをタイムラインに沿ってつなぎ合わせます。
  • トレーニング時のウィンドウ サイズは 60 であり、実行時には 60 フレームのウィンドウを準備する必要があります。

アプリ内でウィンドウと予測を維持する

(16:27) Xcode デモでは、ポーズ抽出、ウィンドウ キャッシュ、予測がカプセル化されています。 Predictor:

import Foundation
import CoreML
import Vision

@available(iOS 14.0, *)
class Predictor {
    /// Fitness classifier model.
    let fitnessClassifier = FitnessClassifier()

    /// Vision body pose request.
    let humanBodyPoseRequest = VNDetectHumanBodyPoseRequest()

    /// A rotation window to save the last 60 poses from past 2 seconds.
    var posesWindow: [VNRecognizedPointsObservation?] = []
    init() {
        posesWindow.reserveCapacity(predictionWindowSize)
    }

    /// Extracts poses from a frame.
    func processFrame(_ samplebuffer: CMSampleBuffer) throws -> [VNRecognizedPointsObservation] {
        // Perform Vision body pose request
        let framePoses = extractPoses(from: samplebuffer)

        // Select the most promiment person.
        let pose = try selectMostProminentPerson(from: framePoses)

        // Add the pose to window
        posesWindow.append(pose)

        return framePoses
    }

    // Make a prediction when window is full, periodically
    var isReadyToMakePrediction: Bool {
        posesWindow.count == predictionWindowSize
    }

    /// Make a model prediction on a window.
    func makePrediction() throws -> PredictionOutput {
        // Prepare model input: convert each pose to a multi-array, and concatenate multi-arrays.
        let poseMultiArrays: [MLMultiArray] = try posesWindow.map { person in
            guard let person = person else {
                // Pad 0s when no person detected.
                return zeroPaddedMultiArray()
            }
            return try person.keypointsMultiArray()
        }

        let modelInput = MLMultiArray(concatenating: poseMultiArrays, axis: 0, dataType: .float)

        // Perform prediction
        let predictions = try fitnessClassifier.prediction(poses: modelInput)

        // Reset poses window
        posesWindow.removeFirst(predictionInterval)

        return (
            label: predictions.label,
            confidence: predictions.labelProbabilities[predictions.label]!
        )
    }
}

キーポイント:

  • FitnessClassifier() Create ML からエクスポートされた Core ML モデルです。
  • humanBodyPoseRequest は一度だけ初期化されるため、フレームごとに繰り返し作成されることを避けるためにセッションを推奨します。
  • posesWindow トレーニング中の 2 秒のウィンドウに対応する、ポーズの最新の 60 フレームを保存します。
  • processFrame(_:) ~からポーズを抽出します CMSampleBuffer そして最も顕著なものを選択します。
  • アクション分類子は 1 人の入力のみを受け入れます。複数人の画面では、独自の選択ロジックを実装する必要があります。
  • 人物が検出されない場合の例では、 zeroPaddedMultiArray() ゼロを埋め込みます。
  • fitnessClassifier.prediction(poses:) 各カテゴリの予測されたラベルと信頼度を返します。
  • removeFirst(predictionInterval) 継続的な予測を容易にするために、ウィンドウを前方にスライドさせます。

トレーニングおよび使用時の制限

(22:00) モデルには反復と多様性が必要です。セッションでは、各動きについて約 50 本のビデオを用意し、さまざまな人々のスタイル、能力、スピードをカバーすることを推奨しています。ユーザーが横または後ろから動く場合、トレーニング データにはこれらの角度も含める必要があります。

(23:35) アクションの継続時間はアクションの長さと一致する必要があり、さまざまなアクションの継続時間は可能な限り近づける必要があります。ビデオ フレーム レートは実際のウィンドウの長さに影響するため、トレーニング ビデオとテスト ビデオの平均フレーム レートは一貫している必要があります。

(24:21) 実行時に選択されるのは 1 人だけです。 Vision が複数の人物を検出した場合、アプリはフレーム内に 1 人だけを残すようにユーザーに通知したり、ポーズのキーポイント座標に基づいてサイズや位置によって人物を選択したりすることができます。

(24:52) 繰り返される動きをカウントしたい場合は、トレーニング ビデオごとに 1 つの動きを 1 回だけ含めることをお勧めします。予測には、カウンターを更新するための信頼できるトリガー ポイントまたは平滑化ロジックも必要です。

重要ポイント

  • 画面に触れずにホームフィットネスタイマーを作成: モデルがジャンピングジャック、ランジ、またはスクワットを認識すると、自動的にタイマーが開始され、元の状態に戻ります。 other 動作を停止した後の状態。セッションのデモでは、継続的な予測を使用してチャレンジのタイミングを制御します。これは、携帯電話を置いた後のトレーニングに適しています。
  • アクション品質スコアリング ツールを作成します: 予測結果の信頼値を使用してアクション品質をスコアリングします。セッションでは、アクションの品質を評価するために信頼度を使用し、トレーニング ビデオのアクション例と比較できることを明確に述べています。
  • 繰り返しカウンターを作成する: トレーニング ビデオを「ビデオには 1 つのアクションのみが含まれる」ように編成し、予測ウィンドウと平滑化ロジックを使用して実行時にカウントを更新します。このプログラムは、スクワット、ランジ、ジャンピング ジャックなどの反復動作に適しています。
  • 学習データのチェックリストを作成: ユーザーがビデオをインポートする前に、人物が 1 人だけであるか、全身がフレーム内に収まっているか、レンズが安定しているか、衣服が動作を妨げていないかを確認します。セッションでは、これらをモデルのパフォーマンスに影響を与える主要な条件としてリストします。
  • ミックスカットビデオ注釈ガジェットを作成: ユーザーがマークできるようにします file_namelabelstart_time そして end_time 長いビデオを作成し、ML トレーニングの作成用に JSON または CSV にエクスポートします。これにより、最初に各アクションを個別のビデオにカットすることなく、既存の映像を再利用できます。

関連セッション

コメント

GitHub Issues · utterances