利用open-cv对黄晓明、AB、刘亦菲图片进行人脸识别
手动反爬虫: 原博地址
知识梳理不易,请尊重劳动成果,文章仅发布在CSDN网站上,在其他网站看到该博文均属于未经作者授权的恶意爬取信息
如若转载,请标明出处,谢谢!
1. 简单的小示例
直接对一张图片中的人脸进行标记,目的就是找到所有的人脸,如下
基本流程:
- 读取照片
- 创建级联分类器
- 进行人脸检测
- 截图人脸位置
- 展示图片
代码如下:(haarcascade_frontalface_alt.xml文件已将上传至资源)
import cv2
import matplotlib.pyplot as plt
import os
import numpy as np
# 简单测试
img = cv2.imread('face.jpg')
#采用级联分类器
detector = cv2.CascadeClassifier('haarcascade_frontalface_alt.xml')
#进行人脸检测
rects = detector.detectMultiScale(img,scaleFactor = 1.1,minNeighbors = 3,minSize = (20,20),flags =cv2.CASCADE_SCALE_IMAGE)
#返回的就是人脸的位置
# print(rects)
for x,y,w,h in rects:
#截取人脸,并且都转化为200*200的固定大小
cv2.rectangle(img, (x,y),(x+w,y+h), (0,255,0), (2))
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(img)
plt.axis('off')
plt.show()
2 项目所需材料及业务逻辑
(1)所需材料
创建两个文件夹分别为train和test,其中train文件夹中放置三个子文件夹,命名为angelababy、xiaoming和xiaoxiannv,文件夹内部分别存放杨颖、黄晓明和刘亦菲三人的照片多张(图片可以直接在百度图片中进行查找,然后保存本地)
test文件夹中放置三人的照片,其中单人的照片各一张,两人合照的照片若干张,这些test中的照片一般是train文件中没有的
(2)业务逻辑
整个项目的流程、业务逻辑,可以按照五个函数进行
face_detect(face_path,predict_face_path)
人脸检测,并截取人脸并保存到本地loc_face(file,predict_face_sub_path)
该函数为人脸检测下的进程子函数,定位人脸
get_label(predict_face_path)
制作标签函数,给图像贴标签,方便模型的人脸标记train_model()
模型训练face_test()
人脸识别验证
其中face_path
为图片的路径地址,predict_face_path
为定位人脸后截取照片所保存的文件夹,predict_face_sub_path
是上截取照片所保存的文件夹的子文件夹,里面分别对应angelababy、xiaoming和xiaoxiannv文件夹中截取的人脸图片。
3 人脸检测并截取图片保存在本地
(1)图片地址获取与截取图片保存文件夹创建
进行人脸检测的前提是获取人脸图片的信息,那么首先就是要获取各个文件夹中的图片路径,方便程序的读取。在读取图片的过程中涉及到路径的处理,刚好可以把要保存图片的文件夹及子文件夹创建好。
代码如下:(主要是涉及到了人脸具体路径的定位,和要存放图片地址文件夹的创建,其中loc_face
就是来实现人脸检测)
先注释掉最后的loc_face
函数,调用写好的face_detect('train','predict_faces')
函数,就会读取train
文件夹下的图片信息,然后在predict_faces
文件夹分别创建三个明星的空文件夹,用于存放待截取的照片。由于涉及到路径的问题,所以在写函数的过程中建议多使用print()
看一下是不是出错,再进行下一步。输出结果如下
(2)人脸检测及截取图片保存
最初的小示例已经完成了一张图片识别的基本流程,这里将过程封装到loc_face
函数中即可,最后保存到刚刚创建的文件夹,注意这里的路径是各个明星的文件夹,也就是最初传入predict_face_path
下的子文件夹,代码如下
这里要详细介绍两点,第一个是级联分类器中的参数
detector.detectMultiScale(image,scaleFactor = 1.1,minNeighbors = 3,minSize = (20,20),flags =cv2.CASCADE_SCALE_IMAGE)
- image:输入图像
- scaleFactor=1.1:这个是每次缩小图像的比例,默认是1.1
- minNeighbors=3:匹配成功所需要的周围矩形框的数目,每一个特征匹配到的区域都是一个矩形框,只有多个矩形框同时存在的时候,才认为是匹配成功,比如人脸,这个默认值是3。
- minSize:匹配人脸的最小范围
- flags=0:可以取如下这些值:
CASCADE_DO_CANNY_PRUNING=1, 利用canny边缘检测来排除一些边缘很少或者很多的图像区域
CASCADE_SCALE_IMAGE=2, 正常比例检测
CASCADE_FIND_BIGGEST_OBJECT=4, 只检测最大的物体
CASCADE_DO_ROUGH_SEARCH=8 初略的检测
第二个就是关于图片的切片问题,这里使用的是image[y:y+h,x:x+w]
,为什么要这么切而不是image[x:x+w,y:y+h]
这样切呢?举个小例子如下
通过结果可以发现,虽然两种方式切取的元素个数是一样的,但是形状前者是3行4列,后者是4行3列。可能不是很明晰,那么直接来个灵魂画图帮助理解一下,假设获取的人脸信息是起点在x=1,y=2处,宽为3,高为4,那么最终人脸形成的区域就如下,图像信息占据4行3列,因此再截取人脸的时候采用的是image[y:y+h,x:x+w]
,这一点还是通过画图好理解一点
执行以上的两个函数,输出结果为
angelababy文件夹下(可以看到存在不是人脸的图片,再进行模型创建之前需要手动删除)
xiaoming文件夹下(全部定位到人脸了)
xiaoxiannv文件夹下(也有一个没有定位到)
手动删除没有识别出来的照片,然后接着进入下一步
4 制作标签
既然已经获得了人脸截图,那么在要训练模型之前就需要给每张脸贴一张标签,方便只有模型训练完成后进行标签人脸的识别,因此这里就创建一个label.txt文件分别存放人脸截取图片的地址和对应标签信息。主要是要注意文件路径处理还有为了方便区分图片地址和标签,在写入文件时记得加一个标识符,方便之后模型训练时候取标签,代码如下
调用函数后,输出结果如下:
5 训练模型
这一步就是分别读取标签文件中的图片地址和图片标签,然后进行模型的训练,一般是要创建两个容器来分别保存对应的数据,需要注意,从文本中读取的数值(仍是字符串)需要转化成整型,由于之前使用的是灰度图片进行图片人像截取的,所以这里训练时候imread()
读取图片的flags=0
,也要是灰度读入(不然最后预测的都是0),最后安装一下opencv的扩展包,保存训练好的模型就可以了
运行结果为:(打开文件后内容如下)
6 模型测试
终于到了最后一步,可以检验模型的可靠程度。首先进行识别前要设置标签对应的标记名称方便程序识别标签后进行打标记;其次就是加载我们训练好的模型;然后读取test文件夹中的图片信息,进行模型预测;最后根据预测的结果进行标记,从而实现人脸识别。代码如下
运行结果如下:
第一张:黄晓明被识别为刘亦菲
第二张:精准识别
第三张:精准识别
第四张:精准识别
第五张:误杀全部
第六张:精准识别
第七张:误杀部分
总结
最后发现图片识别中单张图片都可以正确的识别出来,但是当两张面孔同时出现的时候,误杀率就有点大了,主要是因为黄晓明被认作了刘亦菲(哎哎,最初看神雕侠侣的时候就被姑姑和过儿配的一脸),最后测试发现这两张脸还是挺相似的。
不过识别率不是很精准的原因可能在于训练集的样本只用了不到60张的照片,样本量较少,所以模型的预测能力有点低,不过大致梳理一下整个流程也方便了解人脸识别的原理
最后博客所需要的文件及整个项目的全部代码已经上传至我的资源,有需要的可以自行下载