0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

YOLO v8で笑い男もどきを実現

Posted at

目的

映像に映った人の顔をリアルタイムで笑い男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する
    • 笑い男画像でのマスクができる

image1.png

プログラム

プログラムの説明は考え方の項目を参照

#!/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キー

output4.gif

まとめ

課題はあるが、目標達成!

映像に映った人の顔をリアルタイムで笑い男の画像に差し替えるプログラムを作成する

課題としては以下が挙げられる

  • 人の動きに追従しきれず、顔認識ができないケースがある
    (今回のデモでも一瞬笑い男画像が外れることがあった。ただし、マスクをしているため、顔認識の難易度が上がっている可能性もある)
  • 複数人の顔を笑い男に置き換えることはできない
  1. 笑い男については、以下参照。https://ja.wikipedia.org/wiki/%E7%AC%91%E3%81%84%E7%94%B7_(%E6%94%BB%E6%AE%BB%E6%A9%9F%E5%8B%95%E9%9A%8A

  2. 画像は以下から拝借(http://ledmyway.seesaa.net/article/181382754.html)

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?