2.3K Views
August 27, 24
スライド概要
iOSDC2024のトーク資料になります。
iOS・wacthOS アプリエンジニアです。 App : apps.apple.com/jp/app/mycam-pro/id1540711931
動かして学ぶDockKit入門 iOSDC Japan 2024 day0 - Track C 19:20 ~ Naoya Maeda
DockKitについて話します
自己紹介 • 前田 直哉 • 株式会社タイミー / iOS エンジニア • タイミーを使っていただいているワーカー様の「働く前」・「働 いた後」の体験が向上する機能の開発
• 技術発信 • Zenn、noteでiOS / watchOSに関する技術記事を発信 • 個人開発アプリ • カメラアプリを3つリリース中
アジェンダ • DockKitについて • 実装 • まとめ
本トークで話さないこと • AVFoundationのAVCapture APIについて • Core ML, Visionについて
DockKitについて
DockKit • DockKit対応デバイスをコン トロール • 2023年の9月にリリース • iOS 17から使用可能 引用元:[Belkin公式サイト]Auto-Tracking Stand Pro with DockKit https://www.belkin.com/jp/p/auto-tracking-stand-pro-with-dockkit/MMA008qc05BK.html
DockKit対応デバイスについて
Auto-Tracking Stand Pro with DockKit (Belkin) • 2024年3月に発売 • 世界で初めてDockKitに対応 したデバイス • 人の顔と体を自動でトラッキ ング • iOS 18で追加された一部の APIは非対応 引用元:[Belkin公式サイト]Auto-Tracking Stand Pro with DockKit https://www.belkin.com/jp/p/auto-tracking-stand-pro-with-dockkit/MMA008qc05BK.html
Insta360 Flow Pro (Insta360) • 2024年7月に発売 • 人の顔と体を自動でトラッ キング • DockKit全てのAPIに対応 • ホイール / ボタン 引用元:[Insta360公式サイト]insta360- ow-pro fl fl https://www.insta360.com/jp/product/insta360- ow-pro
似たようなデバイスってたくさん あるんじゃないの?
DockKit対応デバイスの強み
DockKit対応デバイスの強み • 専用アプリは不要 • ビデオ撮影機能を搭載しているアプリはDockKitアクセサリに対 応
DockKit対応デバイスの強み • 専用アプリは不要 • ビデオ撮影機能を搭載しているアプリはDockKitアクセサリに対 応 • 他のフレームワークとの相性が良好 • Vision, Core ML, AVFoundation…
実装
顔・体のトラッキング
実装は不要!
AVCapture APIとDockKitが連携している • AVCapture APIを使用してビデオ撮影機能を実装すればOK
AVCapture APIとDockKitが連携している • AVCapture APIを使用してビデオ撮影機能を実装すればOK
AVCapture APIとDockKitが連携している • AVCapture APIを使用してビデオ撮影機能を実装すればOK
デモ
カスタムコントロール
DockAccessory iOS 17 • DockKit対応デバイスを表すクラス • 主要な役割 • ハードウェア情報を提供 • 動きをカスタマイズするためのメソッドやプロパティを提供
被写体の表示位置変更 • デフォルトは中央寄せで表示 • 組み込みモードは4種類 • 左寄せ / 右寄せ / 中央寄せ / 自動 • 座標とサイズを指定して表示領域を指定することも可能 iOS 17
• func setFramingMode(̲ mode: DockAccessory.FramingMode) • enum FramingMode (automatic, center, left, right) switch framingType { case .auto: try await dockAccessory.setFramingMode(.automatic) case .left: try await dockAccessory.setFramingMode(.left) case .center: try await dockAccessory.setFramingMode(.center) case .right: try await dockAccessory.setFramingMode(.right) }
• func setRegionOfInterest(̲ region: CGRect) let roi = CGRect(x: 0.0, y: 50.0, width: 1.0, height: 0.46) do { if let dockAccessory { try await dockAccessory.setRegionOfInterest(roi) } } catch { print(error.localizedDescription) }
デモ
カスタムトラッキング • 顔・体以外をトラッキング • Vision、Core MLとの連携 • Observationを利用 iOS 17
Observation • 検出した物体の情報 • DockKitに渡すことでトラッ キング対象を決定
Observation • 検出した物体の情報 • DockKitに渡すことでトラッ キング対象を決定
Observation • 独自に生成したObservation をDockKitに渡すことでトラ ッキング対象をカスタマイズ • Vision, Core ML
• VNImageRequestHandler • 画像解析リクエストを処理 let handler = VNImageRequestHandler(cmSampleBuffer: sampleBuffer, orientation: .up, options: [:]) try handler.perform([handPoseRequest]) guard let observation = handPoseRequest.results?.first as? VNHumanHandPoseObservation else { return } let indexFingerTip = try observation.recognizedPoints(.indexFinger)[.indexMCP] if let indexFingerTip { let rect = CGRect(x: indexFingerTip.x, y: indexFingerTip.y, width: 0.4, height: 0.4) let dockAccessoryObservation = DockAccessory.Observation(identifier: 1, type: .object, rect: rect) do { let cameraInfo = DockAccessory.CameraInformation(captureDevice: .builtInWideAngleCamera, cameraPosition: .front, orientation: .corrected, cameraIntrinsics: nil, referenceDimensions: nil) try await dockAccessory.track([dockAccessoryObservation], cameraInformation: cameraInfo) } catch { print(error.localizedDescription) } }
• DockAccessory.Observation • 被写体の情報 let handler = VNImageRequestHandler(cmSampleBuffer: sampleBuffer, orientation: .up, options: [:]) try handler.perform([handPoseRequest]) guard let observation = handPoseRequest.results?.first as? VNHumanHandPoseObservation else { return } let indexFingerTip = try observation.recognizedPoints(.indexFinger)[.indexMCP] if let indexFingerTip { let rect = CGRect(x: indexFingerTip.x, y: indexFingerTip.y, width: 0.4, height: 0.4) let dockAccessoryObservation = DockAccessory.Observation(identifier: 1, type: .object, rect: rect) do { let cameraInfo = DockAccessory.CameraInformation(captureDevice: .builtInWideAngleCamera, cameraPosition: .front, orientation: .corrected, cameraIntrinsics: nil, referenceDimensions: nil) try await dockAccessory.track([dockAccessoryObservation], cameraInformation: cameraInfo) } catch { print(error.localizedDescription) } }
• DockAccessory.CameraInformation • 使用しているカメラデバイスの情報 let handler = VNImageRequestHandler(cmSampleBuffer: sampleBuffer, orientation: .up, options: [:]) try handler.perform([handPoseRequest]) guard let observation = handPoseRequest.results?.first as? VNHumanHandPoseObservation else { return } let indexFingerTip = try observation.recognizedPoints(.indexFinger)[.indexMCP] if let indexFingerTip { let rect = CGRect(x: indexFingerTip.x, y: indexFingerTip.y, width: 0.4, height: 0.4) let dockAccessoryObservation = DockAccessory.Observation(identifier: 1, type: .object, rect: rect) do { let cameraInfo = DockAccessory.CameraInformation(captureDevice: .builtInWideAngleCamera, cameraPosition: .front, orientation: .corrected, cameraIntrinsics: nil, referenceDimensions: nil) try await dockAccessory.track([dockAccessoryObservation], cameraInformation: cameraInfo) } catch { print(error.localizedDescription) } }
• func track(̲ data: [DockAccessory.Observation], cameraInformation: DockAccessory.CameraInformation • 被写体の追跡処理 let handler = VNImageRequestHandler(cmSampleBuffer: sampleBuffer, orientation: .up, options: [:]) try handler.perform([handPoseRequest]) guard let observation = handPoseRequest.results?.first as? VNHumanHandPoseObservation else { return } let indexFingerTip = try observation.recognizedPoints(.indexFinger)[.indexMCP] if let indexFingerTip { let rect = CGRect(x: indexFingerTip.x, y: indexFingerTip.y, width: 0.4, height: 0.4) let dockAccessoryObservation = DockAccessory.Observation(identifier: 1, type: .object, rect: rect) do { let cameraInfo = DockAccessory.CameraInformation(captureDevice: .builtInWideAngleCamera, cameraPosition: .front, orientation: .corrected, cameraIntrinsics: nil, referenceDimensions: nil) try await dockAccessory.track([dockAccessoryObservation], cameraInformation: cameraInfo) } catch { print(error.localizedDescription) } }
デモ
iOS 18 ボタンコントロール • ジンバルに搭載されているボ タン、ホイールの回転イベン トを取得可能 • 2024/8/22時点では Insta360 Flow Proのみ対応 引用元:[Insta360公式サイト]insta360- ow-pro fl fl https://www.insta360.com/jp/product/insta360- ow-pro
デモ
被写体の識別 • ビデオフレーム内の被写体を識別 • 被写体の特徴を取得 • 顕著性ランク • カメラ目線スコア • 発話確信スコア iOS 18
デモ
まとめ • ビデオキャプチャ機能を実装すれば自動トラッキングを使用可能 • 豊富なカスタムコントロール • 他のフレームワークとの相性も良い • iOS 18からはよりインテリジェンスな被写体識別が可能
ご静聴ありがとうございました