detector = dlib.get_frontal_face_detector()
功能:人脸检测画框
参数:无
返回值:默认的人脸检测器
faces = detector(img_gray, 0)
功能:对图像画人脸框
参数:img_gray:输入的图片
返回值:人脸检测矩形框4点坐标。坐标为[(x1, y1) (x2, y2)]。可以通过函数的left,right,top,bottom方法分别获取对应的x1, x2, y1, y2值。(cv里的矩阵和C++的那种一样,左上角是(0,0)点,水平为x方向,竖直为y方向,类似笛卡尔系(区别是y轴正方向不同),所以top的y坐标 < bottom的y坐标。matplotlib是相反的。)
后面那个参数代表将原始图像是否进行放大,1表示放大1倍再检查,提高小人脸的检测效果。
左图是参数为0的检测情况,右图是参数为1的检测情况。
上述例子参考自链接:http://blog.sina.com.cn/s/blog_49b3ba190102yvl9.html
注意dlib只能对灰度图进行检测:
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
注意更改当前文件运行目录 为 程序执行文件路径 的方法:
https://www.jb51.net/article/138980.htm
下面进行代码实战:
原图地址
代码实战1:人脸检测
import numpy
import dlib
import cv2
import sys
import os# 修改执行目录为该.py文件所在目录
#dirname, filename = os.path.split(os.path.abspath(sys.argv[0]))
dirname, filename = os.path.split(sys.argv[0])
# print(dirname,filename)
# path = os.getcwd()
os.chdir(dirname)
print(os.getcwd())# 人脸检测
detector = dlib.get_frontal_face_detector()# 人脸关键点标注。
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat'
)
img = cv2.imread('sdtw2.jpg')gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#这样也可以灰度图但是不建议用:im2 = cv2.imread('tfboys.jpg',flags = 0)faces = detector(gray,0)# 第二个参数越大,代表讲原图放大多少倍在进行检测,提高小人脸的检测效果。for face in faces:#左上角(x1,y1),右下角(x2,y2)x1, y1, x2, y2 = face.left(), face.top(), face.right(), face.bottom()print(x1,y1,x2,y2)cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.imshow("image", img)
cv2.waitKey(0)
运行结果:
代码实战2:人脸关键点标注
import numpy
import dlib
import cv2
import sys
import os#dirname, filename = os.path.split(os.path.abspath(sys.argv[0]))
dirname, filename = os.path.split(sys.argv[0])
# print(dirname,filename)
# path = os.getcwd()
os.chdir(dirname)
print(os.getcwd())# 人脸检测
detector = dlib.get_frontal_face_detector()# 人脸关键点标注。
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat'
)
img = cv2.imread('sdtw2.jpg')gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#这样也可以灰度图但是不建议用:im2 = cv2.imread('tfboys.jpg',flags = 0)dets = detector(gray,0)# 第二个参数越大,代表讲原图放大多少倍在进行检测,提高小人脸的检测效果。for d in dets:# 使用predictor进行人脸关键点检测 shape为返回的结果shape = predictor(gray, d)for index, pt in enumerate(shape.parts()):print('Part {}: {}'.format(index, pt))pt_pos = (pt.x, pt.y)cv2.circle(img, pt_pos, 1, (255, 0, 0), 2) #利用cv2.putText标注序号font = cv2.FONT_HERSHEY_SIMPLEXcv2.putText(img, str(index+1),pt_pos,font, 0.3, (0, 0, 255), 1, cv2.LINE_AA)
cv2.imshow("image", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
实验结果:
人脸关键点:
附标号:
代码实战3:佩戴口罩
我们取2,8,14,28作为口罩关键点,即下图3,9,15,29,放入points_key中
对于待测图片的每一个人脸框,按照对应points_key来检测边界,将口罩图片进行缩放,填入对应区域。
注意对下载后的口罩要进行背景去除,这里可以用一些在线处理网站,或者ps等等。(本项目使用已去除背景的口罩已上传到github)
注意实现的时候,有个问题就是透明度的问题,不然会出现下面这个问题:
为了方便讲解,我们将口罩区域分成口罩图像区域,和口罩真实区域。
在代码实现的时候,刚开始只是想着分摊像素值,比如对口罩图像区域,让他80%保留原图像素值,20%来自口罩图像,这样进行merge。但是效果并不是期待的那样。
发现其实口罩部分还是要口罩占主体,所以换成了20%保留原图像素值,80%来自口罩图像,如下图。
剩下的就是透明度的问题了,这里我采用的是二值化方法,把像素值较小的背景部分隐去,像素值较大的是口罩真实区域,采用口罩图80%和人脸图20%进行merge。
阈值设置为80,表现良好。
此项目代码对应代码和实验所用到的图像均放到了github:https://github.com/xuanweiace/put_a_mask_on_the_face/
欢迎下载和star。
项目中是用二值化的方法来实验背景透明的功能,cv2中也自带了一个功能可以实现透明化处理,感兴趣的同学可以搜一下:
透明度覆盖:
img_mix = cv2.addWeighted(img1, 1, img2,1, 0) #合并,其中参数1表示透明度,第一个1表示img1不透明,第二个1表示img1不透明,如果改成0.5表示合并的时候已多少透明度覆盖。
相关拓展链接:
识别戴口罩的人脸的四种方法:https://blog.csdn.net/qq_23670601/article/details/104344917