顔のランドマーク検出とドロネー分割 Python + OpenCV + dlib

2018-11-17
python%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E7%94%BB%E5%83%8F%E5%87%A6%E7%90%86opencv
    

目次

概要

Python + OpenCV + dlib を用いて顔にドロネー図を描画するサンプルを紹介します。

おまけで、カメラから取得した顔画像に描画するサンプルを追加しました。

環境

Python 3.7.0 OpenCV 3.4

デモ

サンプルソース

import cv2
import dlib
import numpy as np

PREDICTOR_PATH = "/path/to/shape_predictor_68_face_landmarks.dat"
predictor = dlib.shape_predictor(PREDICTOR_PATH)

cascade_path='/path/to/haarcascade_frontalface_default.xml'
cascade = cv2.CascadeClassifier(cascade_path)

def get_landmarks(im):
    rects = cascade.detectMultiScale(im, 1.3,5)
    (x,y,w,h) = rects[0]
    rect = dlib.rectangle(x,y,x+w,y+h)
    return np.matrix([[p.x, p.y] for p in predictor(im, rect).parts()])

def annotate_landmarks(im, landmarks):
    im = im.copy()
    for idx, point in enumerate(landmarks):
        pos = (point[0, 0], point[0, 1])
        cv2.putText(im, str(idx), pos,
            fontFace=cv2.FONT_HERSHEY_SCRIPT_SIMPLEX,
            fontScale=0.4,
            color=(255, 0, 0))
        cv2.circle(im, pos, 2, color=(255, 255, 0))
    return im

def rect_contains(rect, point) :
    if point[0] < rect[0] :
        return False
    elif point[1] < rect[1] :
        return False
    elif point[0] > rect[2] :
        return False
    elif point[1] > rect[3] :
        return False
    return True

def draw_delaunay(img, subdiv, delaunay_color ) :

    triangleList = subdiv.getTriangleList()
    size = img.shape
    r = (0, 0, size[1], size[0])

    for t in triangleList :

        pt1 = (t[0], t[1])
        pt2 = (t[2], t[3])
        pt3 = (t[4], t[5])

        if rect_contains(r, pt1) and rect_contains(r, pt2) and rect_contains(r, pt3) :

            cv2.line(img, pt1, pt2, delaunay_color, 1, 16, 0)
            cv2.line(img, pt2, pt3, delaunay_color, 1, 16, 0)
            cv2.line(img, pt3, pt1, delaunay_color, 1, 16, 0)

if __name__ == "__main__" :
    im = cv2.imread('lenna.png')

    height = im.shape[0]
    width = im.shape[1]

    im = cv2.resize(im, (width, height))

    rect = (0, 0, width, height)

    subdiv = cv2.Subdiv2D(rect)

    points = get_landmarks(im)

    for p in points :
        a = np.array(p).ravel()
        subdiv.insert((a[0], a[1]))

    draw_delaunay(im, subdiv, (255, 255, 255) )

    # im = annotate_landmarks(im, points)

    cv2.imshow('result', im)

    cv2.waitKey(0)
    cv2.destroyAllWindows()

実行結果

リアルタイムでカメラ画像を利用する場合

この場合は、メイン部分をいかに書き換えます。

if __name__ == "__main__" :
    cap = cv2.VideoCapture(0)

    while(True):
        try:
            ret, im = cap.read()

            height = im.shape[0] 
            width = im.shape[1] 
            im = cv2.resize(im, (width, height))

            rect = (0, 0, width, height)

            subdiv = cv2.Subdiv2D(rect)

            points = get_landmarks(im)

            for p in points :
                a = np.array(p).ravel()
                subdiv.insert((a[0], a[1]))

            draw_delaunay( im, subdiv, (255, 255, 255) )

            # im = annotate_landmarks(im, points)

            cv2.imshow('Result',im)
            
        except:
            print('error!')        

        if cv2.waitKey(0) & 0xFF == ord('q'):
            break

    cv2.destroyAllWindows()

説明

ざっくりと、

顔検出 → パーツ検出 → ドロネー分割 → 描画

というフローになっています。

dlib

「dlib」と呼ばれるオープンソースの機械学習ライブラリで顔の輪郭および各器官の検出を行います。

https://tech-blog.s-yoshiki.com/2018/10/702/

Subdiv2D

ドロネー三角形の分割の計算にはOpenCVのSubdiv2Dクラスを利用します。

https://tech-blog.s-yoshiki.com/2018/11/734/

参考

https://tech-blog.s-yoshiki.com/2018/11/734/

https://tech-blog.s-yoshiki.com/2018/10/702/

    

関連記事

AWS Amplify で コンテナベースのデプロイを行い REST API を構築
検証した環境 やってみる 初期準備 パイプラインを確認 終了処理 参考 AWS Amplify で コンテナベースのデプロイを行い REST API を構築した際のメモです。 検証した環境 amplify 5.1.…

Pythonでソケット通信を実装しメッセージの送受信を行う
ソース server.py client.py 動かしてみる 参考 Pythonでソケット通信を実現する方法です。 ソース server.py サーバ側のソースです。 client.py…

CentOS8 に Python + OpenCV をインストール
インストール テスト CentOS8 で標準で提供されているパッケージで Python + OpenCV 環境を構築する方法です。 検証した環境は CentOS8.3 (Docker) です。 インストール まず opencv…

Python poetryでパッケージ開発 PyPIで公開 Pytestでテスト CIをGitHub Actionsで回す
Poetry でパッケージ開発 pytest でユニットテストを実施しカバレッジを算出する パッケージをビルドし PyPI で公開する 検証環境にデプロイする 本番環境にデプロイする GitHub Actions で CI を回す codecovの設定 GitHub…

Selenium + Python でYahooのログインや検索・メールの操作を自動化する。
環境 Selenium環境の構築 Seleniumのインストール 検証 Yahoo検索する Yahooにログイン/ログアウトする Yahooメールの操作〜ゴミ箱を空にする サンプルソース 参考 Selenium + PythonでYahoo…

macOSにOpenCV4をインストール
パッケージの情報 インストール 試す with Python3 macOS (MacBook Pro 2018 13 inchi)にhomebrewを用いてOpenCVをインストールする方法。 パッケージの情報 まず、brew search と brew info…

エンジニアなMacBookのセットアップ 開発環境の構築
ブラウザ関連 Homebrewのインストール ターミナル環境系 Hyper エディタ VSCode typora CLIツール Git 言語系 Python node.js MacBookPro…

OpenCV.jsを動かしてみる + デモ
環境 OpenCV.jsのセットアップ サンプルソース グレースケール 2値化 Cannyエッジ 輪郭抽出 ガウシアン デモ OpenCV.jsを試してみました。 環境 OpenCV.js v4.1.0 OpenCV.jsのセットアップ OpenCVをWasm…

JavaScriptで画像のヒストグラムの正規化
サンプルソース 画像のヒストグラムを正規化するコードの紹介 サンプルソース

画像のヒストグラムを表示する Chart.js JavaScript canvas
ヒストグラム算出のサンプルコード インストール ヒストグラム表示クラス ヒストグラム算出 デモ 出力結果 参考 画像のヒストグラムをJavaScriptで算出してグラフとして表示してみます。 ヒストグラム算出のサンプルコード ヒストグラムの表示にChart.js…

最新の投稿

Node.js で作成した REST API を Docker化
Node.jsでREST APIを作成 コンテナ化 コンテナ化定義 コンテナ化作業 参考 Node.js で作成した REST API を Docker化した際のメモです。 Node.jsでREST APIを作成 まずはNode.js…

JavaScriptで優先度付きキューを実装する
優先度付きキューについて ソース 参考 JavaScriptで優先度付きキュー (プライオリティキュー) を実装する 優先度付きキューについて 具体的には次のような機能があります。 キューに対して要素を優先度付きで追加 (push…

AWS Amplify で コンテナベースのデプロイを行い REST API を構築
検証した環境 やってみる 初期準備 パイプラインを確認 終了処理 参考 AWS Amplify で コンテナベースのデプロイを行い REST API を構築した際のメモです。 検証した環境 amplify 5.1.…

Pythonでソケット通信を実装しメッセージの送受信を行う
ソース server.py client.py 動かしてみる 参考 Pythonでソケット通信を実現する方法です。 ソース server.py サーバ側のソースです。 client.py…

next_permutationをJSで実装する
ソース 使い方 参考 C++で提供されている順列を生成する next_permutation のJS実装です。 ソース 順列が存在する場合はtrueを返し、そうでなければfalse…

応用情報技術者試験の合格体験記
受験時のステータス 受験結果 対策 スケジュール 午前問題 午後問題 参考書等 令和…

[JS]ラジアンから度数に度数からラジアンに変換する
コード 度数からラジアンへ ラジアンから度数へ サンプル ラジアンから度数に度数からラジアンに変換する際のスニペット。 コード 度数からラジアンへ ラジアンから度数へ サンプル

CentOS8 に Python + OpenCV をインストール
インストール テスト CentOS8 で標準で提供されているパッケージで Python + OpenCV 環境を構築する方法です。 検証した環境は CentOS8.3 (Docker) です。 インストール まず opencv…

[Perl] CentOS8 に plenv をインストール
インストール Step1 事前準備 Step2 PATHを通す (README通りにインストール) Step2 PATHを通す ($HOME以外にplenvをインストール) Step3 Perlインストール Step4 cpanmインストール CentOS…

JS/TSのclassでclass名を取得する
コード JS/TSのconstructorを利用して自分自身のクラス名を取得する際のメモ。 コード このコードの結果は次のようになります。

Tags

Dates

s-yoshiki
s-yoshiki
githubtwitterqiita
Web作ってますが、インタラクティブなプログラミングも好きです。
JavaScript / Vue / node.js / PHP / AWS / OpenCV
© 2021   404 motivation not found