使用paddlehub face_landmark_localization进行面部图像精确处理

人脸关键点检测是人脸识别和分析领域中的关键一步,它是诸如自动人脸识别、表情分析、三维人脸重建及三维动画等其它人脸相关问题的前提和突破口。
paddlehub提供了face_landmark_localization模型,可以快速的提供人脸部68个关键点(人脸轮廓17个点,左右眉毛各5个点,左右眼睛各6个点,鼻子9个点,嘴巴20个点)。
我计划试验在这68个点的基础上,为目标图像进行一个唐代妆容的美化。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200501212047172.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tlbnNoaW41MTYxNjM=,size_16,color_FFFFFF,t_70)

设计思路

利用识别出的关键点进行面部区域划定,然后使用opencv的方式进行填充和图像融合。

代码

import paddlehub as hub
import cv2
import numpy as np
from matplotlib import pyplot as plt
import os
import random
%matplotlib inline

#展示图片效果
def img_show_bgr(image,size=8):
#cv2.cvtColor,plt.imshow,plt.axis
#节省空间,不填代码了
#返回两点中点坐标
def mid_point(p1,p2):
    point=(np.array(p1)+np.array(p2))/2
    point=point.astype(int)
    return (point[0],point[1])
 #返回两点距离
def dis_point(p1,p2):
    x_dis=p1[0]-p2[0]
    x_dis**=2
    y_dis=p1[1]-p2[1]
    y_dis**=2
    return (x_dis+y_dis)**0.5
#肤色判定RGB
def skin_rgbrange(R,G,B):
    skin = 0
                
    if (abs(R - G) > 15) and (R > G) and (R > B):
        if (R > 95) and (G > 40) and (B > 20) and (max(R,G,B) - min(R,G,B) > 15):               
            skin = 1    
        elif (R > 220) and (G > 210) and (B > 170):
            skin = 1

    return skin

关于肤色判定部分,更好的是使用通道识别,这里为了简便,直接使用了RGB

face_landmark = hub.Module(name="face_landmark_localization")
img_path = "./work/face_test01.jpg"
results = face_landmark.keypoint_detection(images=[cv2.imread(img_path)],visualization=True,output_dir="./work/output_face_landmark")

使用paddlehub face_landmark_localization进行面部图像精确处理_第1张图片
使用paddlehub face_landmark_localization进行面部图像精确处理_第2张图片
识别出的效果如图,点位的索引图要放在手边,是区域划分的关键

#前额区域 鹅黄
forehead_area=[]
forehead_area.append((points[18-1][0],y_eyebrow_min))
forehead_area.append((points[27-1][0],y_eyebrow_min))
forehead_area.append((points[18-1][0],points[28-1][1]-ot_face_height*1.2))
forehead_area.append((points[27-1][0],points[28-1][1]-ot_face_height*1.2))
forehead_hull=cv2.convexHull(np.array(forehead_area,np.int32).reshape((-1,1,2)))

#core_forehead眉心坐标
core_forehead=mid_point((points[18-1][0],y_eyebrow_min),(points[27-1][0],y_eyebrow_min))
dismax=dis_point(core_forehead,(points[18-1][0],y_eyebrow_min))
#面靥
#左5~49,右55~13 有偏移
#左38x,49y,右45x,55y
#l_face_ye=mid_point(points[5-1],points[49-1])
#r_face_ye=mid_point(points[55-1],points[13-1])    
#print(l_face_ye,":",r_face_ye)
l_face_ye=(points[38-1][0],points[49-1][1])
r_face_ye=(points[46-1][0],points[55-1][1])

cv2.circle(image,l_face_ye, 10, (106,106,255), -1)
cv2.circle(image,r_face_ye, 10, (106,106,255), -1)

cv2.circle(image_flag,l_face_ye, 10, (106,106,255), -1)
cv2.circle(image_flag,r_face_ye, 10, (106,106,255), -1)

#斜红
#left 1,37中点,3,right 46,17中点15
l_face=[]
l_face.append(mid_point(points[1-1],points[37-1]))
l_face.append((mid_point(points[18-1],points[1-1])[0],points[3-1][1]))
l_face.append((mid_point(points[2-1],points[37-1])[0],points[2-1][1]))
l_face_hull=cv2.convexHull(np.array(l_face,np.int32).reshape((-1,1,2)))
cv2.drawContours(image,[l_face_hull], -1, (64,64,255), -1)
cv2.drawContours(image_flag,[l_face_hull], -1, (64,64,255), -1)
r_face=[]
r_face.append(mid_point(points[17-1],points[46-1]))
r_face.append((mid_point(points[27-1],points[17-1])[0],points[15-1][1]))
r_face.append((mid_point(points[16-1],points[46-1])[0],points[16-1][1]))
r_face_hull=cv2.convexHull(np.array(r_face,np.int32).reshape((-1,1,2)))
cv2.drawContours(image,[r_face_hull], -1, (0,0,255), -1)
cv2.drawContours(image_flag,[r_face_hull], -1, (0,0,255), -1)
#花钿
img_path_flow="./work/flower1.jpg"                
image_flow=cv2.imdecode(np.fromfile(img_path_flow, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
flow_size_y=int(ot_face_height*0.4)
flow_size_x=int((flow_size_y/image_flow.shape[0])*image_flow.shape[1])

flow_zero_x=int(core_forehead[0]-flow_size_x/2)
flow_zero_y=int(core_forehead[1]-flow_size_y)

image_flow=cv2.resize(image_flow,(flow_size_y,flow_size_x))

ycrcb = cv2.cvtColor(image_flow, cv2.COLOR_BGR2YCrCb) 
(y, cr, br) = cv2.split(image_flow) 
_, cr = cv2.threshold(cr, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) 

for i in range(0,cr.shape[0]):
    for j in range(0,cr.shape[1]):
        if cr[i][j]==0:
            image[flow_zero_y+i][flow_zero_x+j]=image_flow[i][j]
            image_flag[flow_zero_y+i][flow_zero_x+j]=image_flow[i][j]
img_show_bgr(image_flag)           

这里没有采用图片叠加的方式。用了直接绘图和像素替换的方法。直接绘图调用cv2的相应函数,如果要做渐变和融合后效果会更好,像素替换先做了图片模式的转换,希望能够最大限度保留素材图片丰富的变化,而不是一个纯色的。最后效果如图:
使用paddlehub face_landmark_localization进行面部图像精确处理_第3张图片

思考和总结

1.需要继续改进的地方还很多,因为面部的关键点在脸部动态中发挥的作用更大,点头摇头什么的,精确定位还需要考虑比例、肤色、光照等
2.采用图片叠加的方法会破坏原图的一些色调。像素替换只针对局部,对整体破坏会小。

你可能感兴趣的:(使用paddlehub face_landmark_localization进行面部图像精确处理)