1. 前言
前段时间自制了个人脸表情识别软件,许多步骤用到了OpenCV中的函数和功能,其中就包括人脸图像检测与定位。作为人脸表情识别的第一步需要在输入图像中找到人脸确切的位置,而OpenCV中的haar分类器可以简单方便地解决这一预处理问题。接下来详细介绍图片中人脸的检测和标记实现过程。
2. OpenCV haar分类器
Haar-like特征最早是由Papageorgiou等人用于物体检测的数字图像特征,而Viola和Jones在此基础上,使用3种类型4种形式的特征。
Haar特征分为三类:边缘特征、线性特征、中心特征和对角线特征,组合成特征模板。特征模板内有白色和黑色两种矩形,并定义该模板的特征值为白色矩形像素和减去黑色矩形像素和。Haar特征值反映了图像的灰度变化情况。例如:脸部的一些特征能由矩形特征简单的描述,如:眼睛要比脸颊颜色要深,鼻梁两侧比鼻梁颜色要深,嘴巴比周围颜色要深等。但矩形特征只对一些简单的图形结构,如边缘、线段较敏感,所以只能描述特定走向(水平、垂直、对角)的结构。
这类矩形特征模板由两个或多个全等的黑白矩形相邻组合而成,而矩形特征值是白色矩形的灰度值的和减去黑色矩形的灰度值的和,矩形特征对一些简单的图形结构,如线段、边缘比较敏感。如果把这样的矩形放在一个非人脸区域,那么计算出的特征值应该和人脸特征值不一样,所以这些矩形就是为了把人脸特征量化,以区分人脸和非人脸。
以Haar特征分类器为基础的对象检测技术是一种非常有效的对象检测技术,但其实并不新颖,不过因为技术成熟好用这里依然采用这一方法。它是基于机器学习的,使用大量的正负样本训练得到分类器。其实就是基于对人脸特征的描述,分类器根据训练的样品数据进行训练,完成后即可感知读取到的图片上的特征,进而对图片进行人脸识别。
OpenCV已在GitHub训练结果网址上分享了其训练好的结果数据,分类器普适性较好可满足一般人脸检测的需要,调用的代码如下:
python import cv2 face_cascade = cv2.CascadeClassifier(r'./haarcascade_frontalface_default.xml')
通过以上代码可以得到一个训练好的人脸检测分类器,其中的xml文件可在GitHub训练结果网址上下载得到,下一步就是检测图片中的人脸,在OpenCV中调用的代码如下:
python # 检测脸部 faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30), flags=cv2.CASCADE_SCALE_IMAGE) print('Detected ', len(faces), " face") # 在图片中显示检测到的人脸数 label = 'Result: Detected ' + str(len(faces)) +" faces !" cv2.putText(img, label, (10, 20), cv2.FONT_HERSHEY_SCRIPT_COMPLEX, 0.8, (0, 0, 0), 1) # 显示图片 cv2.imshow('img', img) cv2.waitKey(0) cv2.destroyAllWindows()
通过以上代码可以得到检测出的人脸数据,其中faces中包含了检测到的所有人脸区域的起始点位置及区域大小,可以通过遍历该变量获得每张人脸的检测具体数据并据此标记人脸位置。上面代码运行的几个如下图所示:
以上代码中用到了putText函数,如下代码中各参数依次是:图片,添加的文字,左上角坐标,字体,字体大小,颜色,字体粗细。
python cv2.putText(img, label, (10, 20), cv2.FONT_HERSHEY_SCRIPT_COMPLEX, 0.8, (0, 0, 0), 1)
3. 人脸标记
上一节中可知分类器的detectMultiScale方法可以得到检测出的人脸区域,这一节就可以据此对人脸进行标记,在此之前先读入一张图片并调整为灰度图,代码如下:
python import cv2 face_cascade = cv2.CascadeClassifier('haarcascade_files/haarcascade_frontalface_default.xml') eye_cascade = cv2.CascadeClassifier('haarcascade_files/haarcascade_eye.xml') img = cv2.imread('west.jpeg')# 读取图像 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转为灰度图 # 检测脸部 faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30), flags=cv2.CASCADE_SCALE_IMAGE) print('Detected ', len(faces), " face")
接下来对脸部区域进行标记,利用OpenCV中的rectangle、circle函数可以在图像中添加自定义的矩形、圆形标记,对检测结果区域进行标记的代码如下:
python # 标记位置 for (x, y, w, h) in faces: img = cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 1) # cv2.circle(img, (int((x + x + w) / 2), int((y + y + h) / 2)), int(w / 2), (0, 255, 0), 1) roi_gray = gray[y: y + h, x: x + w] roi_color = img[y: y + h, x: x + w] eyes = eye_cascade.detectMultiScale(roi_gray) for (ex, ey, ew, eh) in eyes: cv2.rectangle(roi_color, (ex, ey), (ex + ew, ey + eh), (0, 255, 0), 1)
以上代码同时检测和标记了眼睛的位置,同样的使用的是OpenCV中得到的分类器,可以得到眼睛的位置并用长方形的颜色框标出来。代码通过遍历检测到的人脸数据,对每个人脸进行标记,并在每个人脸上检测眼睛的位置标识出来。通过如下代码显示图片:
python label = 'Result: Detected ' + str(len(faces)) +" faces !" cv2.putText(img, label, (10, 20), cv2.FONT_HERSHEY_SCRIPT_COMPLEX, 0.8, (0, 0, 0), 1) cv2.imshow('img', img) cv2.waitKey(0) cv2.destroyAllWindows()
运行结果如下图所示:
4. 完整代码
要使用博文中的代码需先安装OpenCV库,可直接下载或通过在终端输入如下代码安装:
python pip install opencv-python
为方便大家使用参考,在此贴出全部的完整代码(需自行准备图片):
python # encoding:utf-8 import cv2 import numpy as np # 运行之前,检查cascade文件路径是否在相应的目录下 face_cascade = cv2.CascadeClassifier('haarcascade_files/haarcascade_frontalface_default.xml') eye_cascade = cv2.CascadeClassifier('haarcascade_files/haarcascade_eye.xml') # 读取图像 img = cv2.imread('lovers.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转为灰度图 # 检测脸部 faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30), flags=cv2.CASCADE_SCALE_IMAGE) print('Detected ', len(faces), " face") # 标记位置 for (x, y, w, h) in faces: img = cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 1) # cv2.circle(img, (int((x + x + w) / 2), int((y + y + h) / 2)), int(w / 2), (0, 255, 0), 1) roi_gray = gray[y: y + h, x: x + w] roi_color = img[y: y + h, x: x + w] eyes = eye_cascade.detectMultiScale(roi_gray) for (ex, ey, ew, eh) in eyes: cv2.rectangle(roi_color, (ex, ey), (ex + ew, ey + eh), (0, 255, 0), 1) label = 'Result: Detected ' + str(len(faces)) +" faces !" cv2.putText(img, label, (10, 20), cv2.FONT_HERSHEY_SCRIPT_COMPLEX, 0.8, (0, 0, 0), 1) cv2.imshow('img', img) cv2.waitKey(0) cv2.destroyAllWindows()
【下载链接】
若您想获得博文中涉及的实现完整全部程序文件(包括图片,py, xml文件等),这里已打包上传至博主的CSDN下载资源中,下载后运行test.py文件即可运行。文件下载链接如下: