- 本文是个人使用OpenCV-Python的应用案例,由于水平有限,难免出现错漏,敬请批评改正。
- 更多精彩内容,可点击进入
OpenCV-Python小应用专栏或我的个人主页查看
- 熟悉Python
- Python 3.6.13 (面向对象的高级语言)
- OpenCV 3.4.10(python第三方库)
pip3 install opencv-python==3.4.10.37
- Numpy 1.19.2
pip3 install numpy==1.19.2
- OpenCV 提供了已经训练好的 Haar 级联分类器用于人脸定位。Haar 级联分类器的实现,经过了以下漫长的历史:
- 开始,有学者提出了使用Haar特征用于人脸检测,但是此时Haar特征的运算量超级大,这个方案并不实用。
- 接下来,有学者提出了简化 Haar 特征的方法,让使用 Haar 特征检测人脸的运算变得简单易行,同时提出了使用级联分类器提高分类效率。
- 后来,又有学者提出用于改进 Haar 的类 Haar 方案,为人脸定义了更多特征,进一步提高了人脸检测的效率。
- 现在,随着深度学习的发展,人脸识别基本都是有深度学习去实现,很少用 Haar级联分类器 了,但是,Haar 仍值得我们去了解和学习。
- 下面用一个简单的例子来叙述上述方案。假设有两幅 4×4 大小的图像,如下图所示。针对这两幅图像,我们可以通过简单的计算来判断它们在左右关系这个维度是否具有相关性。
- 用两幅图像左侧像素值之和减去右侧像素值之和:
- 针对左图,sum(左侧像素) - sum(右侧像素) = (128+96) - (108+76) = 40
- 针对右图,sum(左侧像素) - sum(右侧像素) = (47+88) - (27+68) = 40
- 这两幅图像中,“左侧像素值之和”减去“右侧像素值之和”都是 40。所以,可以认为在“左侧像素值之和”减去“右侧像素值之和”这个角度,这两幅图像具有一定的相关性。
- 从多角度考虑图像的特征。Papageorgiou等人提出了如下图所示的 Haar 特征,这些特征包含垂直特征、水平特征和对角特征。
- Haar 特征反映的是图像的灰度变化,它将像素划分为模块后求差值。Haar 特征用黑白两种矩形框组合成特征模板,在特征模板内,用白色矩形像素块的像素和减去黑色矩形像素块的像素和来表示该模板的特征。
- 经过上述处理后,人脸部的一些特征就可以使用矩形框的差值简
单地表示了。比如,眼睛的颜色比脸颊的颜色要深,鼻梁两侧的颜色比鼻梁的颜色深,唇部的颜色比唇部周围的颜色深。- 关于 Harr 特征中的矩形框,有如下 3 个变量。
- 矩形位置:矩形框要逐像素地划过(遍历)整个图像获取每个位置的差值。
- 矩形大小:矩形的大小可以根据需要做任意调整。
- 矩形类型:包含垂直、水平、对角等不同类型。
- 上述 3 个变量保证了能够细致全面地获取图像的特征信息。但是,变量的个数越多,特征的数量也会越多。
- 例如,仅一个 24×24 大小的检测窗口内的特征数量就接近 20 万个。由于计算量过大,该方案并不实用。
- 后来,Viola 和 Jones 两位学者在论文 Rapid Object Detection Using A Boosted Cascade Of Simple Features 和 Robust Real-time Face Detection 中提出了使用积分图像快速计算 Haar 特征的方法。他们提出通过构造“积分图(Integral Image)”,让 Haar 特征能够通过查表法和有限次简单运算快速获取,极大地减少了运算量。同时,在这两篇文章中,他们提出了通过构造级联分类器让不符合条件的背景图像(负样本)被快速地抛弃,从而能够将算力运用在可能包含人脸的对象上。
- 为了进一步提高效率,Lienhart 和 Maydt 两位学者,在论文 An Extended Set Of Haar-Like Features For Rapid Object Detection 中提出对 Haar 特征库进行扩展。他们将 Haar 特征进一步划分为如图 23-4 所示的 4 类:
- Lienhart 和 Maydt 两位学者认为在实际使用中,对角特征(见上图 底部)和线特征中的(e)图和(g)图是相近的,因此通常情况下无须重复计算。
- 同时,该论文还给出了计算 Haar 特征数的方法、快速计算方法,以及级联分类器的构造方法等内容。(有兴趣的,可自行了解)
- OpenCV 在上述研究的基础上,实现了将 Haar 级联分类器用于人脸部特征的定位。我们可以直接调用 OpenCV 自带的 Haar 级联特征分类器来实现人脸定位。
import cv2
# 读取待检测的图像
image = cv2.imread('faces.jpg')
# 获取 XML 文件,加载人脸检测器
faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
# 色彩转换,转换为灰度图像
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
# 调用函数 detectMultiScale
faces = faceCascade.detectMultiScale(gray,scaleFactor = 1.15,minNeighbors = 5,minSize = (5,5))
print(faces)
# 打印输出的测试结果
print("发现{0}个人脸!".format(len(faces)))
# 逐个标注人脸
for (x,y,w,h) in faces:
cv2.rectangle(image,(x,y),(x+w,y+w),(0,255,0),2) #矩形标注
# 显示结果
cv2.imshow("face_reconize",image)
# 保存检测结果
cv2.imwrite("res.jpg",image)
cv2.waitKey(0)
- 不熟悉OpenCV-Python实时视频或摄像头操作的,可查阅OpenCV-Python快速入门(一):基本操作或OpenCV-Python快速入门专栏。
import cv2
import numpy as np
def face_reconize(image):
# 获取 XML 文件,加载人脸检测器
faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
# 色彩转换,转换为灰度图像
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
# 调用函数 detectMultiScale
faces = faceCascade.detectMultiScale(gray,scaleFactor = 1.15,minNeighbors = 5,minSize = (5,5))
# 逐个标注人脸
for (x,y,w,h) in faces:
cv2.rectangle(image,(x,y),(x+w,y+w),(0,255,0),2) #矩形标注
return image
if __name__ == "__main__":
cap = cv2.VideoCapture(0)
while(cap.isOpened()):
ret, frame = cap.read()
image_res = face_reconize(frame)
cv2.imshow('face_reconize_res',image_res)
c = cv2.waitKey(1)
if c==27: #ESC 键
break
cap.release()
cv2.destroyAllWindows()
获取链接 提取码:rlsb
[1] https://opencv.org/
[2] 李立宗. OpenCV轻松入门:面向Python. 北京: 电子工业出版社,2019
- 更多精彩内容,可点击进入
OpenCV-Python小应用专栏或我的个人主页查看