2020/06/04
「AI CORE XスターターキットとOpenVINO™ですぐに始めるディープラーニング推論」シリーズの9回目記事です。
このシリーズは、「ディープラーニングとは何か」から始まり、「各種ツールの使い方」「プログラミング基礎」「プログラミング応用・実践」までをステップバイステップでじっくり学び、自分で理解してオリジナルのAIアプリケーションが作れるようになることを目指しています。
第9回目はバーチャル試着アプリで必要となる補助ツールを作成します。
ここでは、メガネ画像や帽子画像のことを「アイテム画像」という名称で呼ぶことにします。
検出した目の位置に対して、どの位置にアイテム画像を表示するかをどうやって決めるかについて考えます。
例えば、左右の目の中心座標にアイテム画像の中心を合わせて表示することが考えられます。しかし、この場合はアイテム画像の中心が目の中心になっている前提です。
メガネ画像の場合は元々画像の中心が目の中心に近い場合が多いですが、帽子画像の場合は編集する必要があります。また、メガネ画像の場合であっても、ほんの少しだけ位置をずらした方が似合うことが多いです。
特に帽子の場合などは、中心を目に合わせるために余分な領域が増えて画像サイズが大きくなり、描画処理に影響が出そうです。
そこで考え方を逆にして、アイテム画像の原点に対してどの位置に2つの目ががあると良いかの座標を決めることにします。以後、アイテム画像に対して左目と右目がどこにあるべきかを示す座標のことを「EyePoint」と呼ぶことにします。
EyePointはアイテム画像外にあっても問題ないため、画像を編集する必要がありません。
事前に画像毎のEyePointが分かっていれば、目を検出したときに計算でアイテム画像を表示する位置や大きさ、角度が決められそうですね!
アイテム画像に対し、どこをEyePointにすると良さそうなのかは感覚的な内容ですので人が決める必要があります。
という訳で今回は、背景とアイテム画像を表示して、EyePointにすべき座標をマウスクリックすると、座標が表示されるような簡単なツールを作りたいと思います。
まず真っ白な背景を作成したいと思います。
ndarrayを使うと実際の画像ファイルを用意しなくても、簡単に画像生成することが可能です。
まずは黒画を生成してみます。np.zeros
を使って第一引数にはタプルでHeight, Width, Color Channelの順に、第二引数にはnp.uint8
を指定します。Color Channelはカラーなので3
とし、HeightとWidthに任意のサイズを割り当てます。今回は 300
と500
にしました。標準的な表記の500 x 300(Width x Height)とは順番が逆なのでご注意ください。
import cv2import numpy as np# 黒画の生成img = np # HWCcv2cv2cv2
実行すると黒画が表示されたかと思います。
今回はnp.zeros
を使って全ての画素を(0, 0, 0)にしました。
逆に白にしたい場合は(255, 255, 255)ですが、np.255
のような関数はありませんので、NumPyの計算を活用してみたいと思います。
ndarrayに対する四則演算は全ての要素に反映されます。
例えば 10 を足すとどうなるか確認してみましょう
import numpy as npa = np + 10print(a)
こちらのように全ての要素に10が足されています。
この性質を利用して先程の白画を黒画にしましょう
import cv2import numpy as np# 白画の生成img = np + 255 # HWCcv2cv2cv2
これで 500 x 300 の白画を作ることができました
次にマウスがクリックされたときの座標情報を得たいと思います。
下記のコードを実行してみてください。ウィンドウ内をクリックするとその位置に赤丸が描かれ、ターミナル画面にはクリックした位置の座標が表示されます。
import cv2import numpy as np# コールバック関数if event == cv2.EVENT_LBUTTONDOWN:print(x, y)cv2# コールバック関数の登録cv2cv2# 白画生成img = np + 255# メインループwhile True:cv2key = cv2if key != -1:break# 終了処理cv2
マウス情報はOpenCVを使うことで簡単に得ることが可能です。
ボタンクリックやカーソル移動などマウスに何かしらアクションが起きたら、呼び出す関数を作ることができます。このような関数のことを「コールバック関数」と呼びます。
実際にプログラムで使用するには「コールバック関数」と「コールバック関数の登録」の2つが必要です。それではコードの詳細について見てゆきましょう
今回はcallback_mouse
という名前で関数を作成しました。コールバック関数の場合は得られる引数が決まっていますので、5つの引数を割り当てるようにします。ポイントは最初の3つの引数event, x , y
です。x, y
はマウスのカーソル座標位置で、event
には以下のような情報が入っています。
※その他の詳細はこちらを参照して下さい
ちなみに先程「クリック」と書きましたが、実際にはボタンが「ダウン」かつ「アップ」されたときのアクションのことを指すので厳密には異なります。今回の対象としているアクションは左ボタンの「ダウン」だけです。
この関数の処理をまとめると、引数event
がcv2.EVENT_LBUTTONDOWN
つまり左ボタンダウンのときに、x, y
の値を利用してprint
とcv.circle
で座標値表示と赤丸描画を行っています。
コールバック関数が存在しているだけでは何も起きません。
OpenCVでは複数のウィンドウを扱うことができますので、どのウィンドウにおけるマウスイベントなのかと、どの関数をコールバックとするのか設定が必要です。cv2.namedWindow
にてウィンドウにimage
という名前をつけて、cv2.setMouseCallback
にてimage
ウィンドウに対してcallback_mouse
という関数を設定してます。
白画生成は先程のコードの通りです。
今回はカメラ映像はありませんが、マウス操作を待つ必要があるためWhile True:
を使ってカメラ映像のときのように無限ループにしています。
それではOpenCVのときに学んだPNGOverlayクラスを活用して、アイテム画像も表示して補助ツールを完成させましょう。
アイテム画像はこちらを使いました。背景が透明になっている「ダウンロード用画像(無料)」ボタンからダウンロードします。
ただ、この画像のままだと少しサイズが大きいので、トリミングして縮小しました。
下の画像を右クリックして保存してください。
image
フォルダに6629_trim_small.png
という名前で保存しています。
では以下のコードを実行してみて下さい。
import cv2import numpy as npfrom pngoverlay import PNGOverlay# コールバック関数if event == cv2.EVENT_LBUTTONDOWN:print(x, y)cv2# コールバック関数の登録cv2cv2# 透過PNG画像のインスタンス生成item =# 白画生成img = np + 255# 透過PNGを描画item# メインループwhile True:cv2key = cv2if key != -1:break# 終了処理cv2
マウスをクリックすると赤丸が描画され、その座標が端末に表示されます。左右の目の位置にそれぞれ赤丸を描くことで、EyePoint座標が得られるというツールです。
先程のコードからの変更は3点です
ポイントは白画生成時のHeightとWidthとPNG画像描画時の座標です。
今までは500x300の白画像を生成していましたが、今回はアイテム画像のサイズに合わせています。item.height
とitem.width
を使うことによりPNGOverlayでの画像サイズが得られます。widthはそのままで、heightは帽子画像でも使えるように+300
しています。
PNGOverlayは指定座標に対し、画像の中心が来るように描画します。ですので、白画の原点に画像の左上が来るようにitem.width/2
, item.height/2
としています。
※image/6629_trim_small.png
のサイズは500x112ですが、PNGOverlayで読み込んだ変数item
のサイズはprintなどで確認すると512x512となっています。この理由はPNGOverlayクラス側の都合で、処理しやすいように、対角線の長さを一辺とする正方形にしているためです。
これでEyePointを簡易的に得られるツールができました。
機能としては先程のツールで事足りていますが、少し使いづらい点もあります。
ツールはもっと改善可能です。アイテムの拡大・縮小、顔画像を表示してそこにアイテムをドラッグする など、色々とツールに機能を入れることはできます。ぜひ色々と挑戦してみてください。
参考にもう少しUIを改善したツールのソースコードをこちらに展開します。自分で挑戦してみたい方はまず、ソースコードを見ずにやってみた方が良いかもしれません。
virtual_fitting_eyepoint_tool.py
使い方
次回はいよいよ、バーチャル試着アプリの作成を行います。
以上、「応用プログラミングで補助ツール作成」でした。