导读
本文给大家分享一个基于OpenCV实现简单人脸面具、眼镜、胡须、鼻子特效的实例,并附实现步骤和源码。
背景介绍
OpenCV传统人脸检测是使用Haar特征的级联分类器实现的。Harr级联是一个基于Haar特征的级联分类器。级联分类器是什么?它是一个把弱分类器串联成强分类器的过程。弱分类器和强分类器分别是什么呢?弱分类器是性能受限的分类器,它们没法正确地区分所有事物。如果你的问题很简单,它的输出结果会在一个可以接受的范围内。强分类器可以正确地对数据进行分类。下图展示了它们是如何组合在一起的。Haar级联的另一个重要部分是Haar特征,这些特征简单地总结了不同的长方形区域的区别,如下图所示:
计算ABCD区域的Haar特征,只需要计算这个区域白色像素和有色像素的区别。在上面四张图表中使用了不同的图案创建Haar 特征,同时其他图案也被使用了。这些图案使用了多重尺度法以确保系统的拉伸是不变的。多重尺度法指把图像缩小再次计算同样的特征。这样可以在给出对象大小有差异的时候候,获得一个可靠的结果。
OpenCV安装目录中提供了多个已经训练好的Haar分类器模型文件,包含:人脸检测、人眼检测、鼻子检测和身体检测等,如下图所示:
比如使用haarcascade_frontalface_alt.xml,我们可以很快实现一个人脸检测功能:
代码语言:javascript复制import sys
import numpy as np
import cv2
#加载xml分类器文件
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_alt.xml')
font = cv2.FONT_HERSHEY_SIMPLEX
def face_detect(img):
strText=""
cv2.imshow('原图', img)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#转为灰度图
#gray = cv2.equalizeHist(gray)#直方图均衡化
#人脸检测
faces = face_cascade.detectMultiScale(gray,1.1,2,0|cv2.CASCADE_SCALE_IMAGE,(30,30))#OpenCV3.x
for (x,y,w,h) in faces: #遍历检测结果
cv2.rectangle(img,(x,y),(x w,y h),(0,255,0),2)#框出人脸区域
#cv2.circle(img,(int(x w/2),int(y h/2)),int(w/2),(0,255,0),3)
face_num = len(faces)
if face_num==0:
print ("There is no face!")
strText="There is no face!"
elif face_num==1:
print ("There is 1 face!")
strText="There is 1 face!"
else:
print ("There are %s faces!"�ce_num)
strText="There are %s faces!"�ce_num
cv2.putText(img, strText, (20,30), font, 1, (0,0,255), 2)
cv2.imshow('结果图',img)
print ('Finished')
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == '__main__':
img = cv2.imread('./pics/5.jpg')
face_detect(img)
实现步骤
【1】准备面具图片并处理成透明背景
【2】人脸检测并确定人脸ROI
【3】将面具图片缩放到人脸ROI大小,并对Alpha通道阈值提取分离面具部分
代码语言:javascript复制Mat faceMask = imread("./mask/mask2.png", -1);
if (faceMask.empty())
{
cerr << "Error loading mask image. Exiting!" << endl;
return -1;
}
Mat alpha, channels[4];
split(faceMask, channels);
alpha = channels[3];
threshold(alpha, alpha, 0, 255, THRESH_BINARY | THRESH_OTSU);
imshow("thresMask", alpha);
cout << alpha.channels() << endl;
vector<Mat>bgrImg;
bgrImg.push_back(channels[0]);
bgrImg.push_back(channels[1]);
bgrImg.push_back(channels[2]);
merge(bgrImg, faceMask);
waitKey();
【4】用Mat的copyTo方法将面具贴到人脸部分
代码语言:javascript复制faceMaskResized.copyTo(faceROI, grayMaskResized)
【5】扩展到眼镜、胡须和鼻子特效:
haarcascade_frontalface_alt.xml---人脸检测
haarcascade_smile.xml---嘴唇检测
haarcascade_mcs_nose.xml---鼻子检测
haarcascade_eye.xml---眼睛检测
实现效果: