アプリで拡張顔を使用する方法を学びます。
前提条件
- Xcode バージョン 13.0 以降
- Cocoapods 1.4.0 以降(Cocoapods を使用する場合)
- iOS 12.0 以降を搭載した ARKit 互換 Apple デバイス(iOS 12.0 以降のデプロイ ターゲットが必要)
サンプルアプリをビルドして実行する
詳しい手順については、クイックスタートをご覧ください。
- GitHub から ARCore SDK for iOS のクローンを作成するかダウンロードして、サンプルアプリコードを取得します。
- ターミナル ウィンドウを開き、Xcode プロジェクトが存在するフォルダから
pod install
を実行します。 - Xcode バージョン 10.3 以降でサンプルアプリを開き、USB 経由でデバイスを開発マシンに接続します。ビルドエラーを回避するには、
.xcodeproj
ファイルではなく、.xcworkspace
ファイルからビルドするようにしてください。 - Cmd+R キーを押すか、Run をクリックします。拡張顔は、シミュレーターではなく実機を使用して操作できます。
- [OK] をタップして、カメラにサンプルアプリへのアクセスを許可します。アプリの前面カメラが開き、すぐにカメラフィードで顔が追跡されます。キツネの耳の画像を額の両側に配置し、キツネの鼻を自分の鼻の上に置きます。
アプリに拡張された顔を実装する方法の概要
*.scn
ファイルを Xcode にインポートする
アプリで検出された顔にテクスチャや 3D モデルなどの独自のアセットを追加するには、*.scn
アセットを Xcode にドラッグします。
拡張顔セッションを初期化する
アプリから Augmented Faces API を使用するには、拡張顔セッションを初期化します。このセッションはカメラ画像を 60 fps で取り込み、非同期的に顔の更新をデリゲート メソッドに返します。初期化時に、キャプチャ デバイスの画角を渡すだけで、デリゲートを設定します。
// Session takes a float for field of view
let faceSession = try? GARAugmentedFaceSession(fieldOfView: cameraFieldOfView)
faceSession?.delegate = self
カメラ画像をセッションに渡す
セッションが初期化され、適切に構成されたら、アプリからセッションへのカメラ画像の送信を開始できます。サンプルアプリは、前面カメラからの動画フレームを使用して AVCaptureSession
を作成して、カメラ画像を取得します。
次のコードサンプルは、AVFoundation
のキャプチャ出力デリゲート メソッドの実装を示しています。このメソッドでは、画像、タイムスタンプ、認識回転が顔セッションに渡されます。
func captureOutput(_ output: AVCaptureOutput,
didOutput sampleBuffer: CMSampleBuffer,
from connection: AVCaptureConnection) {
faceSession.update(with: imageBuffer,
timestamp: frameTime,
recognitionRotation: rotationDegrees)
}
画像の処理が完了すると、Augmented Faces API は GARAugmentedFaceFrame
を返すデリゲート コールバックを送信します。顔にエフェクトを適用できる拡張顔オブジェクトが含まれています。また、画像バッファと update メソッドに渡したタイムスタンプも含まれます。これは、顔効果を画像と同期させる場合に便利です。このオブジェクトにはディスプレイ変換と投影行列も用意されているため、検出された顔に接しているように見える顔効果を簡単にレンダリングできるように、3D 世界と 2D ビューを設定できます。
var face: GARAugmentedFace? { get }
var capturedImage: CVPixelBuffer { get }
var timestamp: TimeInterval { get }
顔メッシュの向き
iOS のフェース メッシュの向きに注意してください。
面に 2D テクスチャを適用する
サンプルアプリには、拡張顔を SCNGeometry
オブジェクトに変換するためのクラスが用意されています。このジオメトリを使用すると、SceneKit ノードに簡単にアタッチして、拡張顔の中心変換に配置できます。
let faceNode = SCNNode()
// Gets the most recent frame's face
let face = faceSession.currentFrame?.face
// This is instantiated once, not with every frame
let faceGeometryConverter = FaceMeshGeometryConverter()
// Converts Augmented Face to SCNGeometry object
let faceMesh = faceGeometryConverter.geometryFromFace(face)
// Assigns geometry to node and sets the pose
faceNode.geometry = faceMesh
faceNode.simdTransform = face.centerTransform
2D 面テクスチャは UIImage
として読み込まれ、フェースメッシュのジオメトリにアタッチされているマテリアルに設定されます。
faceTextureMaterial = SCNMaterial()
faceTextureMaterial.diffuse.contents = UIImage(named:@"face.png")
faceMesh?.firstMaterial = faceTextureMaterial
3D オブジェクトを面に取り付ける
デリゲートのコールバックから受け取った GARAugmentedFace
は、3 つの異なるリージョン(変換)を提供します。これを顔にアタッチするために使用できます。この変換により、ワールド空間で鼻、額の左側、額の右側を取得できます。ここでは、球体を鼻に取り付けるために鼻変換を使用します。
// Create node and add to scene
let node = SCNNode(geometry: SCNSphere(radius: .02))
sceneView.rootNode.addChild(node)
// Every frame updates the node's position
node.simdWorldTransform = session.currentFrame.face.transform(for: .nose)
独自のアセットを Xcode にインポートする
アプリで検出された顔にテクスチャや 3D モデルなどのアセットを追加するには、まず、アセットを Xcode にインポートします。
*.dae
(3D モデル)ファイルをエクスポートします。*.dae
ファイルを Xcode プロジェクトにドラッグします。- Xcode で Editor > Convert to SceneKit scene file format (.scn) に移動して、ファイルを
.scn
形式に変換します。