python + opencv + dlib 实现实时唇色变换 | 虚拟上妆
点击下方“AI算法与图像处理”,一起进步!
重磅干货,第一时间送达
代码:https://github.com/ai-coodinator/lipstick
大家好,今天跟大家分享一个利用python + opencv + dlib 实现一个带滑动条控制的唇色变换案例!
大致内容包括:
1、demo展示
2、思路剖析
3、算法实现
如果内容对你有所帮助的话,这次帮我点个在看分享一下吧
一、demo效果展示
demo已经上传到视频号上了,可以直接点击观看,欢迎关注!
从demo 中可以看到,当我们调整下方的三个RGB 滑动条的时候,可以实现实时的调整嘴唇的颜色。
下面看一下具体的实现思路!
二、思路剖析
具体的思路可以分为下面几个部分:
1、人脸关键点检测
2、嘴唇区域mask提取
3、嘴唇区域上色并与原图融合
1、关键点检测
这里使用的dlib,进行人脸关键点检测(检测到 68 个人脸关键点)
在项目中的 Face_Parts.py 中已实现了对人脸的各个区域的关键点和关键点围成的多边形可视化,后续如果需要对其他部分(非嘴唇区域)进行类似上色,或者变装等,都可以自行拓展使用。
2、嘴唇区域mask提取
通过dlib 检测到的嘴唇区域关键点序列(关键点序号48-61),提取序列并将嘴唇区域关键点连成一个多边形,制作成一个mask,以便后续进行上色处理
3、嘴唇区域上色并与原图融合
这里通过opencv 的滑动条,来进行交互,实现从外部输入 自定义的 rgb 颜色,从而改变唇色,并使用 alpha 融合与原图融合生成最终的效果(PS:这里作者使用高斯模糊处理,让 mask 区域更加的平滑,不会那么尖锐,看起来更加自然)
滑动条的创建和值的获取使用的函数分别是:
cv2.createTrackbar
cv2.getTrackbarPos
三、算法实现
下面是具体的算法实现,这里备注
shape_predictor_68_face_landmarks.dat
可以去 dlib 项目去下载:
https://github.com/davisking/dlib-models
import cv2
import numpy as np
import dlib
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
def empty(a):
pass
cv2.namedWindow('BGR')
cv2.resizeWindow('BGR',640,240)
cv2.createTrackbar('Blue','BGR',0,255,empty)
cv2.createTrackbar('Green','BGR',0,255,empty)
cv2.createTrackbar('Red','BGR',0,255,empty)
def createBox(img,points,scale=5,masked=False,cropped = True):
if masked:
mask = np.zeros_like(img)
mask = cv2.fillPoly(mask,[points],(255,255,255))
img = cv2.bitwise_and(img,mask)
# cv2.imshow('Mask',img)
if cropped:
bbox = cv2.boundingRect(points)
x,y,w,h = bbox
imgCrop = img[y:y+h,x:x+w]
imgCrop = cv2.resize(imgCrop,(0,0),None,scale,scale)
return imgCrop
else:
return mask
while True:
# image
# 1 读入图片并进行人脸关键点检测
img = cv2.imread('1.jpg')
img = cv2.resize(img,(0,0),None,0.5,0.5)
imgOriginal = img.copy()
imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = detector(imgGray)
for face in faces:
x1,y1 = face.left(),face.top()
x2,y2 = face.right(),face.bottom()
# imgOriginal = cv2.rectangle(img, (x1,y1),(x2,y2),(0,255,0),2)
landmarks = predictor(imgGray,face)
myPoints =[]
for n in range(68):
x = landmarks.part(n).x
y = landmarks.part(n).y
myPoints.append([x,y])
# cv2.circle(imgOriginal,(x,y),5,(50,50,255),cv2.FILLED)
# cv2.putText(imgOriginal,str(n),(x,y-10),cv2.FONT_HERSHEY_COMPLEX_SMALL,0.9,(0,0,255),1)
myPoints = np.array(myPoints)
# imgLeftEye = createBox(img,myPoints[36:42],8)
# cv2.imshow('LeftEye',imgLeftEye)
# 2 嘴唇区域mask提取
imgLips = createBox(img,myPoints[48:61],8,masked=True,cropped=False)
imgColorLips = np.zeros_like(imgLips)
# 3 创建滑动条,以及获取滑动条的值,嘴唇区域上色并与原图融合
b = cv2.getTrackbarPos('Blue','BGR')
g = cv2.getTrackbarPos('Green','BGR')
r = cv2.getTrackbarPos('Red','BGR')
imgColorLips[:] = b,g,r
imgColorLips = cv2.bitwise_and(imgLips,imgColorLips)
imgColorLips = cv2.GaussianBlur(imgColorLips,(7,7),10)
#color_image
imgColorLips = cv2.addWeighted(imgOriginal,1,imgColorLips,0.4,0)
#gray_image
# imgOriginalGray = cv2.cvtColor(imgOriginal,cv2.COLOR_BGR2GRAY)
# imgOriginalGray = cv2.cvtColor(imgOriginalGray,cv2.COLOR_GRAY2BGR)
# imgColorLips = cv2.addWeighted(imgOriginalGray,1,imgColorLips,0.4,0)
cv2.imshow('BGR',imgColorLips)
# cv2.imshow('Lips',imgLips)
print(myPoints)
cv2.imshow("Original",imgOriginal)
cv2.waitKey(1)
好的,这样子就实现我们唇色变换的功能,今天的分享就到这里了。喜欢的小伙伴记得三连支持!感谢
怕小伙伴没注意,这里再分享一下代码:
代码:https://github.com/ai-coodinator/lipstick
努力分享优质的计算机视觉相关内容,欢迎关注:
个人微信(如果没有备注不拉群!) 请注明:地区+学校/企业+研究方向+昵称
下载1:何恺明顶会分享
在「AI算法与图像处理」公众号后台回复:何恺明,即可下载。总共有6份PDF,涉及 ResNet、Mask RCNN等经典工作的总结分析
下载2:终身受益的编程指南:Google编程风格指南
在「AI算法与图像处理」公众号后台回复:c++,即可下载。历经十年考验,最权威的编程规范!
下载3 CVPR2021
在「AI算法与图像处理」公众号后台回复:CVPR,即可下载1467篇CVPR 2020论文 和 CVPR 2021 最新论文
点亮 ,告诉大家你也在看