Last active
April 23, 2020 04:29
-
-
Save electricbaka/8539cbe83403a8f1ad0a237f61be79ec to your computer and use it in GitHub Desktop.
バーチャル試着アプリ完成前コード(スケール・座標対応)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#================================================== | |
# 準備 | |
#================================================== | |
# import | |
import cv2 | |
import numpy as np | |
from openvino.inference_engine import IENetwork, IEPlugin | |
import math | |
from pngoverlay import PNGOverlay | |
# ターゲットデバイスの指定 | |
plugin = IEPlugin(device='MYRIAD') | |
# モデルの読み込みと入出力データのキー取得(顔検出) | |
net_face = IENetwork(model='intel/face-detection-retail-0005/FP16/face-detection-retail-0005.xml', weights='intel/face-detection-retail-0005/FP16/face-detection-retail-0005.bin') | |
exec_net_face = plugin.load(network=net_face) | |
input_blob_face = next(iter(net_face.inputs)) | |
out_blob_face = next(iter(net_face.outputs)) | |
# モデルの読み込みと入出力データのキー取得(landmarks) | |
net_landmarks = IENetwork(model='intel/landmarks-regression-retail-0009/FP16/landmarks-regression-retail-0009.xml', weights='intel/landmarks-regression-retail-0009/FP16/landmarks-regression-retail-0009.bin') | |
exec_net_landmarks = plugin.load(network=net_landmarks) | |
input_blob_landmarks = next(iter(net_landmarks.inputs)) | |
out_blob_landmarks = next(iter(net_landmarks.outputs)) | |
# カメラ準備 | |
cap = cv2.VideoCapture(0) | |
# PNGOverlayインスタンス生成 | |
item = PNGOverlay('image/6629_trim_small.png') | |
# EyePoint情報(6629_trim_small.png) | |
EPL_x = 137 | |
EPL_y = 237 | |
EPR_x = 381 | |
EPR_y = 237 | |
# EyePoint距離 | |
EP_distance = math.sqrt((EPR_x - EPL_x) ** 2 + (EPR_y - EPL_y) ** 2) | |
# アイテム座標(EyePoint_left基準) | |
item_x_EPL = item.width/2 - EPL_x | |
item_y_EPL = item.height/2 - EPL_y | |
#================================================== | |
# メインループ | |
#================================================== | |
while True: | |
# キー押下で終了 | |
key = cv2.waitKey(1) | |
if key != -1: | |
break | |
# カメラ画像読み込み | |
ret, frame = cap.read() | |
# 入力データフォーマットへ変換 | |
img = cv2.resize(frame, (300, 300)) # HeightとWidth変更 | |
img = img.transpose((2, 0, 1)) # HWC > CHW | |
img = np.expand_dims(img, axis=0) # CHW > BCHW | |
# 推論実行 | |
out = exec_net_face.infer(inputs={input_blob_face: img}) | |
# 出力から必要なデータのみ取り出し | |
out = out[out_blob_face] | |
# 不要な次元を削減 | |
out = np.squeeze(out) | |
# 検出されたすべての顔領域に対して1つずつ処理 | |
for detection in out: | |
# conf値の取得 | |
confidence = float(detection[2]) | |
# バウンディングボックス座標を入力画像のスケールに変換 | |
xmin = int(detection[3] * frame.shape[1]) | |
ymin = int(detection[4] * frame.shape[0]) | |
xmax = int(detection[5] * frame.shape[1]) | |
ymax = int(detection[6] * frame.shape[0]) | |
# conf値が0.5より大きい場合のみLandmarks推論とバウンディングボックス表示 | |
if confidence > 0.5: | |
# 顔検出領域はカメラ範囲内に補正する。特にminは補正しないとエラーになる | |
if xmin < 0: | |
xmin = 0 | |
if ymin < 0: | |
ymin = 0 | |
if xmax > frame.shape[1]: | |
xmax = frame.shape[1] | |
if ymax > frame.shape[0]: | |
ymax = frame.shape[0] | |
#-------------------------------------------------- | |
# ディープラーニングLandmarks推定 | |
#-------------------------------------------------- | |
# 顔領域のみ切り出し | |
img_face = frame[ ymin:ymax, xmin:xmax ] | |
# 入力データフォーマットへ変換 | |
img = cv2.resize(img_face, (48, 48)) # HeightとWidth変更 | |
img = img.transpose((2, 0, 1)) # HWC > CHW | |
img = np.expand_dims(img, axis=0) # CHW > BCHW | |
# 推論実行 | |
out = exec_net_landmarks.infer(inputs={input_blob_landmarks: img}) | |
# 出力から必要なデータのみ取り出し | |
out = out[out_blob_landmarks] | |
# 不要な次元を削減 | |
out = np.squeeze(out) | |
# 目の座標を顔画像のスケールに変換し、オフセット考慮 | |
eye_left_x = int(out[0] * img_face.shape[1]) + xmin | |
eye_left_y = int(out[1] * img_face.shape[0]) + ymin | |
eye_right_x = int(out[2] * img_face.shape[1]) + xmin | |
eye_right_y = int(out[3] * img_face.shape[0]) + ymin | |
#-------------------------------------------------- | |
# アイテムのスケール・座標対応 | |
#-------------------------------------------------- | |
# 目の距離 | |
eye_distance = math.sqrt((eye_right_x - eye_left_x) ** 2 + (eye_right_y - eye_left_y) ** 2) | |
# アイテムのスケール | |
item_scale = eye_distance / EP_distance | |
# アイテム座標(左目基準) | |
item_x_eyeleft = item_x_EPL * item_scale | |
item_y_eyeleft = item_y_EPL * item_scale | |
# アイテム座標 | |
item_x = item_x_eyeleft + eye_left_x | |
item_y = item_y_eyeleft + eye_left_y | |
# アイテム描画 | |
item.resize(item_scale) # スケール | |
item.show(frame, int(item_x), int(item_y)) # 座標 | |
# 画像表示 | |
cv2.imshow('frame', frame) | |
#================================================== | |
# 終了処理 | |
#================================================== | |
cap.release() | |
cv2.destroyAllWindows() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment