OpenCV for Unityで異なる画像上の顔を入れ替える
はじめに
OpenCV for UnityとDlib FaceLandmark Detectorは有料ですが、 FaceSwapperExampleは無料で公開されています。
FaceSwapperExampleに顔入れ替えのサンプルはありましたが、 1枚の画像内に写っている顔同士を入れ替えるというものでした。
この記事では、 そのサンプルを基に異なる画像内の顔同士を入れ替える例を紹介します。
検証環境
- Windows10 Home
- Unity2020.3.14f1
- OpenCV for Unity v2.4.4
- Dlib FaceLandmark Detector v1.3.2
- FaceSwapperExample v1.1.0
ソースコード
OpenCV for UnityとDlib FaceLandmark Detector で異なる画…
流れ
初期化
顔検出用のクラスを初期化します。
テクスチャ読み込み
入れ替えたい顔が写っている2枚のテクスチャから、 OpenCVでの処理で使う行列Mat
を生成します。
画像の連結
元のサンプルは1枚の画像内の顔を入れ替えるものだったので、 ここで2枚のテクスチャを連結しました。
連結するテクスチャは同じサイズである必要があるので、 まずはImgproc.resize
でサイズを揃えます。
次に、 Core.vconcat
で第1引数のリスト内の画像を連結し、 結果を第2引数へ格納します。
顔の位置を検出
ここから顔入れ替えまでは元のサンプル通りです。
DlibのFaceLandmarkDetector
または、 HaarCascade
を使って顔の位置を検出します。
顔の形状を検出
前のステップでは顔の位置の矩形が取得できました。 ここでは顔の入れ替えのために顔の形状を検出します。
正面を向いていない顔を除外
検出した結果の中から、 正面をむいていないものを除外します。
どの程度まで許容するかを_frontalFaceRateLowerLimit
で設定できます。
顔入れ替え
DlibFaceSwapper
クラスを使って顔の入れ替えを実行します。
連結した部分を再分割
最後に、 連結していた1枚の画像を2枚に再分割してテクスチャへ変換して完了です。
Mat
クラスのコンストラクタに切り抜きたい領域をRect
型で指定することでその領域のみのMat
を生成できるため、 上半分と下半分の領域を指定すると分割できます。