Bigdra.Log

備忘録

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 で異なる画…

f:id:bigdra50:20210731142609p:plain

流れ

初期化

顔検出用のクラスを初期化します。

テクスチャ読み込み

入れ替えたい顔が写っている2枚のテクスチャから、 OpenCVでの処理で使う行列Matを生成します。

画像の連結

元のサンプルは1枚の画像内の顔を入れ替えるものだったので、 ここで2枚のテクスチャを連結しました。
連結するテクスチャは同じサイズである必要があるので、 まずはImgproc.resizeでサイズを揃えます。
次に、 Core.vconcatで第1引数のリスト内の画像を連結し、 結果を第2引数へ格納します。

f:id:bigdra50:20210731144923p:plain

顔の位置を検出

ここから顔入れ替えまでは元のサンプル通りです。

DlibのFaceLandmarkDetector または、 HaarCascadeを使って顔の位置を検出します。

顔の形状を検出

前のステップでは顔の位置の矩形が取得できました。 ここでは顔の入れ替えのために顔の形状を検出します。
f:id:bigdra50:20210731150043p:plain

正面を向いていない顔を除外

検出した結果の中から、 正面をむいていないものを除外します。
どの程度まで許容するかを_frontalFaceRateLowerLimitで設定できます。

顔入れ替え

DlibFaceSwapperクラスを使って顔の入れ替えを実行します。
f:id:bigdra50:20210731150636p:plain

連結した部分を再分割

最後に、 連結していた1枚の画像を2枚に再分割してテクスチャへ変換して完了です。
Matクラスのコンストラクタに切り抜きたい領域をRect型で指定することでその領域のみのMatを生成できるため、 上半分と下半分の領域を指定すると分割できます。