5
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

OpenCVで透明人間

Posted at

先日,透明人間になって写真や動画を撮影できるAndroidアプリ「Invisible Camera」をリリースしました.OpenCV for Unityで作りました.せっかくなのでOpenCVで透明人間になる方法をメモとして残します.

なお,下記ソースコードは以下のようにusing staticでクラス名を省略しています.

using static OpenCVForUnity.Imgproc;
using static OpenCVForUnity.Core;

HSV画像に変換

GaussianBlur(webcamMat, blurred, new Size(7, 7), 0);
cvtColor(blurred, hsv, COLOR_RGBA2RGB);
cvtColor(hsv, hsv, COLOR_RGB2HSV);

webcamMatはカメラ映像をMatに変換したものです.OpenCV for Unityでは,WebCamTextureToMatHelperというクラスのGetMat()メソッドを使うとカメラ映像をRGBAのMatとして取得できます.別にRGBでも構いません.

後述のinRangeメソッドが使えるように,入力画像をHSVに変換します.ノイズ除去はお好みで.
COLOR_RGBA2RGBはないのでRGBを経由しています.

肌と髪の後ろにある背景を抽出する

//肌領域が255,それ以外が0のマスクを作成
//Hが0~180で循環しているので,両端とも取り出す
inRange(hsv, SKIN_LOWER1, SKIN_UPPER1, skinMask1);
inRange(hsv, SKIN_LOWER2, SKIN_UPPER2, skinMask2);

//髪(黒)領域が255,それ以外が0のマスクを作成
bitwise_or(skinMask1, skinMask2, skinMask1);
inRange(hsv, HAIR_LOWER, HAIR_UPPER, hairMask);

//肌と髪の領域が255のマスクを作成
bitwise_or(skinMask1, hairMask, skinAndHairMask);

//肌と髪の領域と同じ位置の背景を切り出す
bitwise_and(bg, bg, bgOnSkinAndHair, skinAndHairMask);

bgは背景(Background)のRGBA画像です.

inRangeメソッドで指定した範囲内の画素を255(白),範囲外の画素を0(黒)としたマスクを作成します.範囲は以下のように設定しました.

Scalar SKIN_LOWER1 = new Scalar(  0,  30,  88); //H(0~180)の左側  
Scalar SKIN_UPPER1 = new Scalar( 25, 173, 255);             
Scalar SKIN_LOWER2 = new Scalar(160,  30,  88); //H(0~180)の右側
Scalar SKIN_UPPER2 = new Scalar(180, 173, 255);            
Scalar HAIR_LOWER  = new Scalar(  0,   0,   0);                   
Scalar HAIR_UPPER  = new Scalar(255, 150,  90);              

bitwise_orは,ざっくり言うと2つのマスクの0でない領域を足し合わせます.

bitwise_andは,本来は2つの画像の両方で0でない領域だけを抽出するメソッドです.上記コードでは同じ画像のandを取っているのでそれだけだとbgがbgOnSkinAndHairにコピーされるだけですが,第4引数にマスク画像を指定することでマスク画像で0でない領域のみ抽出することができます.これはbitwise_orでも同じです.

skinAndHairMaskとbgOnSkinAndHairはそれぞれ以下のような画像になります(毎回撮り直しているので少しずれてますが気にしないでください).

Screen Shot 2018-12-27 at 4.56.15.png Screen Shot 2018-12-27 at 5.22.55.png

カメラ映像から肌と髪以外の領域を抽出する

bitwise_not(skinAndHairMask, skinAndHairMask);
bitwise_and(webcamMat, webcamMat, withoutSkinAndHair, skinAndHairMask);

skinAndHairMaskを反転してからカメラ映像に適用することで,髪と肌以外の領域を抽出します.反転後のskinAndHairMaskとwithoutSkinAndHairは以下のようになります.

uTZ16fzhmZnyA1V1545856493_1545856500.png Screen Shot 2018-12-27 at 5.26.35.png

肌と神の領域を背景で置換

bitwise_or(withoutSkinAndHair, bgOnSkinAndHair, invisible);

withoutSkinAndHairの0領域にbgOnSkinAndHairの0でない領域がはめ込まれるイメージです.invisibleは以下のようになります.

Screen Shot 2018-12-27 at 5.29.26.png
5
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?