1. aki0141

    Posted

    aki0141
Changes in title
+[Python, OpenCV]動画から検出した円をぴえんに変換する
Changes in tags
Changes in body
Source | HTML | Preview

ぴえんという顔文字をご存じでしょうか。
2019年ぐらいからJKやJCの間で流行りはじめた顔文字で、2020年には上半期のインスタ流行語大賞に選ばれたらしいです。
実際に見てもらった方が早いですね。

002・pien.png

いつからか誰かがこの顔文字と一緒に「ぴえん」という単語を使い始めて、それが定着してこの顔文字自体がぴえんと呼ばれるようになった・・・らしいです。

なんというかカルト的な人気を博したこのぴえん🥺ですが、この顔をした八頭身に追いかけられるようなゲームが出たり、「ぴえんこえてぱおん」というまた新しいよくわからない単語が登場したりしています。

さて、今回はこのぴえんをPythonとOpenCVを使ってカメラの映像に表示したいと思います。
まだどちらも触って1,2ヶ月程度なのでおかしな部分があるかもしれませんが、よろしくお願いします。

開発環境

  • macOS Catalina(使っているのはMacBookPro Mid 2014)
  • Python 3.7.7
  • numpy 1.18.5
  • OpenCV 3.4.2

Anacondaで仮想環境を作成しています。
カメラはeMeetのNovaを使っています。

ソース

pien.py
# -*- coding: utf-8 -*-
import cv2
import numpy as np

#カメラの取得
cap = cv2.VideoCapture(1)

while True:
    ret, frame = cap.read()
    #ハフ変換用にリサイズし、グレーカラーに変更
    frame = cv2.resize(frame, dsize=(640, 480))
    gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
    gray = cv2.GaussianBlur(gray, (33, 33), 1)

    #ハフ変換による円形の抽出
    circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 60, param1=10, param2=85, minRadius=1, maxRadius=80)

    #変換結果がある場合にぴえんの描写を行う
    if circles is not None:
        circles = np.uint16(np.around(circles))
        for i in circles[0,:]:
            #i[0]=x座標 i[1]=y座標 i[2]=半径
            x = i[0]; y = i[1]; r = i[2]
            #cv2.circleは円形 cv2.ellipseは楕円や楕円弧
            #輪郭
            cv2.circle(frame, (x, y), r, (0, 215, 255), -1)
            #眉毛右
            cv2.ellipse(frame, (x+int(r*2/3), y-int(r*2/3)), (int(r/3), int(r/4)), 0, 90, 165, (19, 69, 139), 3)
            #眉毛左
            cv2.ellipse(frame, (x-int(r*2/3), y-int(r*2/3)), (int(r/3), int(r/4)), 0, 15, 90, (19, 69, 139), 3)
            #涙右
            cv2.circle(frame, (x+int(r*2/5), y), int(r*3/10), (255, 255, 255), -1)
            #涙左
            cv2.circle(frame, (x-int(r*2/5), y), int(r*3/10), (255, 255, 255), -1)
            #黒目右
            cv2.circle(frame, (x+int(r*2/5), y-int(r/15)), int(r*3/10), (0, 0, 0), -1)
            #黒目左
            cv2.circle(frame, (x-int(r*2/5), y-int(r/15)), int(r*3/10), (0, 0, 0), -1)
            #白目大右
            cv2.ellipse(frame, ((x+int(r/3), y-int(r/6)), (int(r/3), int(r/4)), 135), (255, 255, 255), -1)
            #白目大左
            cv2.ellipse(frame, ((x-int(r/2), y-int(r/6)), (int(r/3), int(r/4)), 135), (255, 255, 255), -1)
            #白目小右
            cv2.ellipse(frame, ((x+int(r/2), y), (int(r/10), int(r/15)), 135), (255, 255, 255), -1)
            #白目小左
            cv2.ellipse(frame, ((x-int(r/3), y), (int(r/10), int(r/15)), 135), (255, 255, 255), -1)
            #口
            cv2.ellipse(frame, (x, y+r), (int(r/4), int(r/2)), 0, 245, 295, (19, 69, 139), 5)

    #ウィンドウにカメラの映像を表示 この時点でframeにはぴえんが描写されている
    cv2.imshow("frame", frame)

    #qキーを押したら終了する
    if cv2.waitKey(1)&0xff == ord("q"):
        break

cap.release()
cv2.destroyAllWindows()

コードの説明はそのままコメントで残しました。
重要なのは中程のハフ変換による円形の検出部分と、検出した円の座標・半径をもとにぴえんを作成する部分です。
ぴえんは画像を貼り付けているわけではなく、全て円と線で描画しているので、どんな大きさにも対応できるようになっています。
文字列も描写できるので🥺をそのまま使えないかと思ったのですがダメでした。

やってみた結果

仮想環境をconda activateした上でpien.pyを実行すると、カメラからの映像がウィンドウで表示されるかと思います。
そこでカメラを丸いものに向けてみましょう。

001・pien.gif

ぴえんになりました🥺
しっかり大きさが違ってもそれに合わせて変換されていますね。
今回は円を検出指定いるので、円の中に何が入っているかは特に関係ありません。時計でもキャップでもメガネでもぴえんになります。
コードを丸くすればそれもぴえんになります。
ちなみに瞳もぴえんになりました。(🥺ω🥺)みたいな感じです。

OpenCVを使えば円だけでなく例えば人の顔も検出できます。
つまりカメラに移った顔を全て🥺にすることができるということです。
そこら辺はそのうち試してみたいと思います。