目的
映像に映った人の顔をリアルタイムで笑い男
1の画像に差し替えるプログラムを作成する
(この記事 が面白そうだったので、それをYOLOでやったみた記事です)
環境
HW
- PC:Lenovo ThinkBook 13s Gen 3
- カメラ:PC内蔵のインカメラ
SW
- Python:v3.11.5
- Anaconda:conda v23.7.4
- 物体検出モデル:YOLO v8
作業メモ
環境整備
参考サイト
https://qiita.com/marumen/items/481ffac7cc0c54948652
Anaconda の導入
以前、光学迷彩もどきプログラム にて導入したため、そちらを参照
YOLO v8 の導入
同上
YOLOで顔認識できるようにする
参考サイト
https://github.com/akanametov/yolo-face
参考サイトに顔認識できるモデルが公開されていたので、そちらを使えるようにセットアップする
顔認識モデルのダウンロード
-
Installation
に書かれている内容をそのまま実施
# clone repo
$ git clone https://github.com/akanametov/yolov8-face
# pip install required packages
$ pip install ultralytics # これは依然やったので省略
# go to code folder
$ cd yolov8-face
- 顔認識用のモデルをダウンロード
参考サイト からyolov8n-face.pt
をダウンロード
顔認識をお試し
※ Jupyter Notebook上で確認
$ from ultralytics import YOLO
$ model = YOLO("yolov8n-face.pt")
WARNING ⚠️ yolov8n-face.pt appears to require 'omegaconf', which is not in ultralytics requirements.
AutoInstall will run now for 'omegaconf' but this feature will be removed in the future.
Recommend fixes are to train a new model using the latest 'ultralytics' package or to run a command with an official YOLOv8 model, i.e. 'yolo predict model=yolov8n.pt'
requirements: Ultralytics requirement ['omegaconf'] not found, attempting AutoUpdate...
requirements: ❌ Command 'pip install --no-cache "omegaconf" ' returned non-zero exit status 101.
→ omegaconf
というパッケージが足りない模様。将来的には削除されると書かれているが、とりあえずの対策としてインストールする
- 不足パッケージをインストール
$ pip install omegaconf
Collecting omegaconf
・・・
Successfully installed antlr4-python3-runtime-4.9.3 omegaconf-2.3.0
Note: you may need to restart the kernel to use updated packages.
- 顔認識を試す
# from ultralytics import YOLO
# model = YOLO("yolov8n-face.pt")
# results = model(0 , show=True)
→ webカメラの映像に対して、顔認識できる事を確認
笑い男もどきプログラムを作成
参考サイト
http://ledmyway.seesaa.net/article/181382754.html
考え方
- (1) マスク用の画像1を作成
- 顔認識できた範囲に笑い男画像2をリサイズし(黒色の部分)、それ以外の背景(白色の部分)をWebカメラ画像のサイズになるように補完
- (2) (1)の画像でWebカメラ画像をマスクする(
cv2.bitwise_and
) - (3) マスク用の画像2を作成
- 顔認識できた範囲に笑い男画像をリサイズする
- (4) (2)と(3)から黒の部分を消すように
cv2.bitwise_or
する- 笑い男画像でのマスクができる
プログラム
プログラムの説明は考え方の項目を参照
#!/usr/bin/env python
# coding: utf-8
from ultralytics import YOLO
import cv2
import numpy as np
model = YOLO("yolov8n-face.pt")
cap = cv2.VideoCapture(0)
org_img_mask = cv2.imread("image\warai.png")
while True:
ret, img_main = cap.read()
results = model(img_main)
for r in results:
boxes_xyxy = r.boxes.numpy().xyxy
# print(boxes_xyxy)
# print(boxes_xyxy[0][0])
# print(boxes_xyxy[0][1])
# print(boxes_xyxy[0][2])
# print(boxes_xyxy[0][3])
# 顔認識できた場合に以下の処理を実施
if r.boxes.numpy().cls.size > 0 and r.boxes.numpy().cls[0] == 0:
# 笑い男画像を顔のサイズにリサイズ
# intにしないとエラーになるので、小数点以下が切り捨てになる
dsize_x = int(boxes_xyxy[0][2] - boxes_xyxy[0][0])
dsize_y = int(boxes_xyxy[0][3] - boxes_xyxy[0][1])
resize_img_mask = cv2.resize(org_img_mask, (dsize_x, dsize_y))
# mask画像作成
h, w = r.boxes.numpy().orig_shape[:2]
th, th_resize_img_mask = cv2.threshold(resize_img_mask, 1, 255, cv2.THRESH_BINARY)
th_resize_img_mask = cv2.bitwise_not(th_resize_img_mask)
# pythonの除算はfloat型で返却らしいので、intへ型変換
top = int(boxes_xyxy[0][1])
bottom = (h - dsize_y) - top
left = int(boxes_xyxy[0][0])
right = (w - dsize_x) - left
# webカメラ画像のサイズが合うように、mask画像を補完
# img_main_mask("考え方"の(1)の画像)、img_mask("考え方"の(3)の画像)
img_main_mask = cv2.copyMakeBorder(th_resize_img_mask, top, bottom, left, right, cv2.BORDER_CONSTANT, value=(255,255,255))
img_mask = cv2.copyMakeBorder(resize_img_mask, top, bottom, left, right, cv2.BORDER_CONSTANT, (0,0,0))
# 笑い男画像でのmaskを実行("考え方"の(2)の画像)
img_main_masked = cv2.bitwise_and(img_main, img_main_mask)
# お試しに顔認識している範囲を見える化
cv2.rectangle(img_main_masked, (int(boxes_xyxy[0][0]), int(boxes_xyxy[0][1])), (int(boxes_xyxy[0][2]), int(boxes_xyxy[0][3])), (255, 255, 0))
# "考え方"の(4)の画像
img_last = cv2.bitwise_or(img_main_masked, img_mask)
# 顔認識できない場合はWebカメラの画像をそのまま映す
else:
img_last = img_main.copy()
cv2.imshow("img_last",img_last)
# 処理を終了する場合は、Escキーで抜ける
if cv2.waitKey(1) == 27:
break
cv2.destroyAllWindows()
cap.release()
デモ
実際に動作させたときのデモ動画が以下になる
- プログラムを起動して、Webカメラ画像で顔認識できればその範囲が笑い男画像になる
- プログラム終了は
Esc
キー
まとめ
課題はあるが、目標達成!
映像に映った人の顔をリアルタイムで
笑い男
の画像に差し替えるプログラムを作成する
課題としては以下が挙げられる
- 人の動きに追従しきれず、顔認識ができないケースがある
(今回のデモでも一瞬笑い男画像が外れることがあった。ただし、マスクをしているため、顔認識の難易度が上がっている可能性もある) - 複数人の顔を笑い男に置き換えることはできない