今のところdlibにはあって、OpenCVには無い顔器官検出。
とりあえず、無理やり色付けしたけど、もっとスマートな方法があるはず。
というか、リファレンスをしっかり読み込んでいないだけだと思いますが。。。
動画は以下。
顔を出すのは恥ずかしいので顔検出を用いて隠しております。
youtu.be
ソースコードは以下。
動作させるには、pyファイルと同じディレクトリに顔器官の学習済みデータを
配置する必要があります。
→shape_predictor_68_face_landmarks.dat(http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
face_landmark_detector.py.
Usage:
face_landmark_detector.py [<video source>] [<resize rate>] [<privacy mask>]
'''
import sys
import dlib
import cv2
import time
import copy
try:
fn = sys.argv[1]
if fn.isdigit() == True:
fn = int(fn)
except:
fn = 0
try:
resize_rate = sys.argv[2]
resize_rate = int(resize_rate)
except:
resize_rate = 1
try:
privacy_mask = sys.argv[3]
privacy_mask = int(privacy_mask)
except:
privacy_mask = 0
predictor_path = "./shape_predictor_68_face_landmarks.dat"
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(predictor_path)
video_input = cv2.VideoCapture(fn)
while(video_input.isOpened() == True):
ret, frame = video_input.read()
temp_frame = copy.deepcopy(frame)
# 処理負荷軽減のための対象フレーム縮小(引数指定時)
height, width = frame.shape[:2]
temp_frame = cv2.resize(frame, (int(width/resize_rate), int(height/resize_rate)))
# 顔検出
start = time.time()
dets = detector(temp_frame, 1)
elapsed_time = time.time() - start
print ("detector processing time:{0}".format(elapsed_time)) + "[sec]"
for k, d in enumerate(dets):
print("Detection {}: Left: {} Top: {} Right: {} Bottom: {}".format(
k, d.left(), d.top(), d.right(), d.bottom()))
# 顔器官検出
start = time.time()
shape = predictor(temp_frame, d)
elapsed_time = time.time() - start
print ("predictor processing time:{0}".format(elapsed_time)) + "[sec]"
# 描画
rect_offset = 20
if privacy_mask == 1:
cv2.rectangle(frame, (int(d.left() * resize_rate) - rect_offset, int(d.top() * resize_rate) - rect_offset), \
(int(d.right() * resize_rate) + rect_offset, int(d.bottom() * resize_rate) + rect_offset), (255, 255, 255), -1)
for shape_point_count in range(shape.num_parts):
shape_point = shape.part(shape_point_count)
if shape_point_count < 17: # [0-16]:輪郭
cv2.circle(frame, (int(shape_point.x * resize_rate), int(shape_point.y * resize_rate)), 2, (0, 0, 255), -1)
elif shape_point_count < 22: # [17-21]眉(右)
cv2.circle(frame, (int(shape_point.x * resize_rate), int(shape_point.y * resize_rate)), 2, (0, 255, 0), -1)
elif shape_point_count < 27: # [22-26]眉(左)
cv2.circle(frame, (int(shape_point.x * resize_rate), int(shape_point.y * resize_rate)), 2, (255, 0, 0), -1)
elif shape_point_count < 31: # [27-30]鼻背
cv2.circle(frame, (int(shape_point.x * resize_rate), int(shape_point.y * resize_rate)), 2, (0, 255, 255), -1)
elif shape_point_count < 36: # [31-35]鼻翼、鼻尖
cv2.circle(frame, (int(shape_point.x * resize_rate), int(shape_point.y * resize_rate)), 2, (255, 255, 0), -1)
elif shape_point_count < 42: # [36-4142目47)
cv2.circle(frame, (int(shape_point.x * resize_rate), int(shape_point.y * resize_rate)), 2, (255, 0, 255), -1)
elif shape_point_count < 48: # [42-47]目(左)
cv2.circle(frame, (int(shape_point.x * resize_rate), int(shape_point.y * resize_rate)), 2, (0, 0, 128), -1)
elif shape_point_count < 55: # [48-54]上唇(上側輪郭)
cv2.circle(frame, (int(shape_point.x * resize_rate), int(shape_point.y * resize_rate)), 2, (0, 128, 0), -1)
elif shape_point_count < 60: # [54-59]下唇(下側輪郭)
cv2.circle(frame, (int(shape_point.x * resize_rate), int(shape_point.y * resize_rate)), 2, (128, 0, 0), -1)
elif shape_point_count < 65: # [60-64]上唇(下側輪郭)
cv2.circle(frame, (int(shape_point.x * resize_rate), int(shape_point.y * resize_rate)), 2, (0, 128, 255), -1)
elif shape_point_count < 68: # [65-67]下唇(上側輪郭)
cv2.circle(frame, (int(shape_point.x * resize_rate), int(shape_point.y * resize_rate)), 2, (128, 255, 0), -1)
cv2.imshow('face landmark detector', frame)
c = cv2.waitKey(50) & 0xFF
if c==27: # ESC
break
video_input.release()
cv2.destroyAllWindows()
以上。