第一章 python-opencv-图片导入和显示
第二章 python-opencv图像简单处理
第三章 python-opencv图像mask掩膜处理
第四章 python-opencv图像马赛克
第五章 python-opencv人脸马赛克
第六章 python-opencv人脸检测
上一章中说明了如何检测人脸,那么,这一张将说明检测到人脸之后如何在人脸区域张贴另一张图像。
本文将代码进行了详细的标注说明。
import cv2
if __name__ == '__main__':
# 加载图片
img = cv2.imread('./tong.jpg')
# 将图片转化为灰度
gray = cv2.cvtColor(img, code = cv2.COLOR_BGRA2GRAY)
# 加载人脸检测器
face_detector = cv2.CascadeClassifier('./haarcascade_frontalface_alt.xml')
# 人脸检测
faces = face_detector.detectMultiScale(gray)
# 加载要张贴的图片
heart = cv2.imread('./heart.jpg')
# 提取图片中的图案
for x,y,w,h in faces:
heart1 = cv2.resize(heart, (w, h))
for i in range(w):
for j in range(h):
if not (heart1[i,j] > 200).all():
img[i+y,j+x] = heart1[i,j]
cv2.imshow('picture', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
gray = cv2.cvtColor(img, code = cv2.COLOR_BGRA2GRAY)
为什么要转化为灰度图?
因为转化为灰度图后图片只有一通道,这样在人脸检测的时候可以减少计算参数,加快检测速度,当然也可以不转换。
其中参数img为要转化的图片,cv2.COLOR_BGRA2GRAY则代表将图片转化为灰度图。
人脸检测模型可以直接从opencv官方网站中下载(下载地址),下载后是一个xml文件,通过加载xml文件即可进行检测。
模型加载用到的函数为cv2.CascadeClassifier(),其中括号中直接填入你下载好的检测模型的路径。
face_detector = cv2.CascadeClassifier('./haarcascade_frontalface_alt.xml')
模型加载后便开始人脸检测,人脸检测用到的是detectMultiScale函数。
detectMultiScale函数可以检测出图片中所有的人脸,并将人脸用vector保存各个人脸的坐标、大小(用矩形表示)
detectMultiScale函数的定义为:
detectMultiScale(self, image, scaleFactor=None, minNeighbors=None, flags=None, minSize=None, maxSize=None)
各参数含义为:
image--待检测图片,一般为灰度图像加快检测速度;
objects--被检测物体的矩形框向量组;
scaleFactor--表示在前后两次相继的扫描中,搜索窗口的比例系数。默认为1.1即每次搜索窗口依次扩大10%;
minNeighbors--表示构成检测目标的相邻矩形的最小个数(默认为3个)。
如果组成检测目标的小矩形的个数和小于 min_neighbors - 1 都会被排除。
如果min_neighbors 为 0, 则函数不做任何操作就返回所有的被检候选矩形框,
这种设定值一般用在用户自定义对检测结果的组合程序上;
flags--要么使用默认值,要么使用CV_HAAR_DO_CANNY_PRUNING,如果设置为
CV_HAAR_DO_CANNY_PRUNING,那么函数将会使用Canny边缘检测来排除边缘过多或过少的区域,
因此这些区域通常不会是人脸所在区域;
minSize和maxSize用来限制得到的目标区域的范围。
检测代码:
faces = face_detector.detectMultiScale(img,
scaleFactor=1.05, #缩放每次检测范围,默认1.1
minNeighbors=3)
原始的图片是这样的
for x,y,w,h in faces: # 遍历所有检测到的人脸区域
heart1 = cv2.resize(heart, (w, h)) # 将要张贴的图像尺寸变为人脸区域大小
for i in range(w):
for j in range(h):
if not (heart1[i,j] > 200).all():
img[i+y,j+x] = heart1[i,j]
其中:
if not (heart1[i,j] > 200).all():
img[i+y,j+x] = heart1[i,j]
这里heart1[i,j] > 200为白色区域,heart1[i,j] < 200为红色区域,所以,这行代码是将红色区域的部分提取出来,然后将人脸部分对应的位置替换为要张贴的图像对应的部分。