人工智能开发实战照片智能搜索功能实现

内容提要

  1. 项目分析
  2. 预备知识
  3. 项目实战

一、项目分析

1、提出问题

随着人民生活水平的提高和手机照相功能的日趋完美,我们不经意中拍摄了很多值得回忆的时刻,一场说走就走的旅行途中也记录下许多令人心动的瞬间,不知不觉之中,我们身边保存了大量的生活相片。

然而,每当你想重温你或者他的系列照片时,或者想分享一张你特别满意的靓照,从众多的照片中一遍遍翻找这些照片的确是一件费时费力的事情。

既然AI无时不在我们身边,能否借助AI的人脸识别技术来帮助我自动整理出我想要的照片,实现照片的智能搜索呢?答案无疑是肯定的。

下面,我们就利用人脸识别技术和OpenCV工具,对相册中的照片进行自动挑选以解决上述问题。

2、解决方法

帮助人们从相册中找出指定人物的系列照片,对于人工操作而言,并不是一件困难的事情,但整理的效率可能不尽人意,毕竟手动翻阅每张照片是个耗时费力的事。

让计算机替代人来完成这个事,难点在于如何从被检照片中识别与目标人脸高度相似的人脸,如果被检照片中有此人,说明该照片就是你想要的那一张,否则,该照片被忽视。

因此,一种可行的方案是:首先训练计算机认识不同式样的同一系列人脸,让它知道其实这些照片上的人物是同为一个人,从而得到目标人脸训练模型。

其次,遍历相册中的每张照片,检测出该照片上所有的人脸,提取人脸特征值,然后用目标人脸训练模型依次对人脸特征值进行预测比对,如果两者之间只要有一次高度匹配,就保留该照片,立即进入下一张照片的搜索,如果均不匹配,则忽视该照片,进行下一张搜索,直至搜索完所有的照片。

最后,得到的所有保留照片就是智能搜索的结果,至此,整个智能搜索照片过程结束。

问题的解决方案如下图所示。

二、预备知识

利用OpenCV来智能搜索相片,有两个重要的环节:

一是人脸区域的检测,这要用到前面提到的人脸检测器;

二是基于人脸区域数据的人脸识别,这要用到人脸识别模型。

下面分别来了解OpenCV中人类检测器和人脸识别模型的使用。

1、人脸检测器

我们可以从网络资源上下载别人训练好的人脸分类器,也可以自己训练。在此我们使用表中默认的级联分类器来检测照片中的人脸。

案例1:检测照片中的所有人脸,并用矩形框出人脸区域。

文件case1.ipynb代码如下:

1	import cv2
2	import numpy as np
3	faceCascade=cv2.CascadeClassifier('data/haarcascade_frontalface_default.xml')
4	img=cv2.imread('data/pic1.JPG')
5	gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
6	faces=faceCascade.detectMultiScale(gray,1.3,5)
7	for (x,y,w,h)in faces:
8	    cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,0),1)
9	cv2.imshow('pic',img)
10	cv2.waitKey(0)
11	cv2.destroyAllWindows()

为方便调用默认的级联人脸分类模型,将文件haarcascade_frontalface_default.xml拷贝到源程序所在位置的data文件夹下,通过代码行3来构建人脸分类器faceCascade。

代码行4读取照片文件pic1.jpg,在代码行5将其转换成灰度图像。

代码行6对灰度图像gray按搜索窗口比例系数为1.3、相邻矩形最小个数为5的扫描方式检测人脸,并返回检测到的人脸矩形框向量数组。

代码行7-8遍历该向量数组,在图像img中人脸的相应位置绘制出一个个的矩形框。

代码行9显示绘制有人脸矩形框的照片。

代码行10一直等待用户的按键响应,按任意键继续,并通过代码行11关闭所有的窗口。

程序的运行效果如下:

由上可以看出,照片中的两个人脸被成功检测出来,人脸的位置及大小数据如下所示:

2、人脸识别算法

目前OpenCV支持:特征脸EigenFace、线性判别分析脸FisherFace与直方图脸LBPHFace三种人脸识别方法。

OpenCV的扩展包opencv-contrib-python提供了相应的函数以方便构建上述三种人脸识别方法的模型,因此在使用人脸识别模型前,要执行以下命令安装OpenCV扩展包。

pip3 install opencv-contrib-python

扩展包提供的模型函数如下表所示:

由于LBPHFace算法不会受到光照、缩放、旋转和平移的影响,且执行性能高,通用性较好,是OpenCV中首选的人脸识别方案。

案例2:识别指定照片中的人是谁。

编写如下代码(case2.ipynb),以识别上图中的照片who.jpg人物是huangshuai还是limu

1	import cv2
2	import os
3	import numpy as np
4	images=[]
5	labels=[]
6	whoPath=''
7	name2num={'huangshuai':1,'limu':2}
8	num2name={1:'huangshuai',2:'limu'}
9	faceCascade=cv2.CascadeClassifier('data/haarcascade_frontalface_default.xml')
10	for root,dirs,filenames in os.walk('data\\case8-2\\'):
11	    for filename in filenames:
12	        if filename!='who.jpg':
13	            filePath=os.path.join(root,filename)
14	            img=cv2.imread(filePath,0)
15	            faces=faceCascade.detectMultiScale(img,1.3,3)
16	            name=filePath.split('\\')[-2]
17	            for (x,y,w,h) in faces:
18	                images.append(img[y:y+h,x:x+w])
19	                labels.append(name2num[name])
20	        else:
21	            whoPath=os.path.join(root,filename)
22	faceRecognizer=cv2.face.LBPHFaceRecognizer_create()
23	faceRecognizer.train(images,np.array(labels))
24	whoimg=cv2.imread(whoPath,0)
25	whoFace=faceCascade.detectMultiScale(whoimg,1.3,3)
26	for(x,y,w,h) in whoFace:
27	    pred_index,conf_score=faceRecognizer.predict(whoimg[y:y+h,x:x+w])
28	    print('待识别照片中的人是:',num2name[pred_index])
29	    print('置信度评分=',conf_score)

代码行4-5分别用列表images、labels保存用于训练人脸识别模型的人脸数据和标签数据。

在代码行7-8定义人物“huangshuai、limu”对应的标签号为“1、2”。

代码行9构建一个人脸分类器faceCascade。

代码行10-21对指定目录data\case8-2\下的文件夹及文件进行遍历,如果文件不是待识别照片who.jpg,则将它们作为训练集。

在代码行15检测出人脸,并在代码行18-19将人脸数据和标签值分别保存到列表images和labels中;若是待识别照片,则在代码行21保存其路径。

代码行22构建一个LBPHFace类型的人脸识别模型,并在代码行23利用人脸数据集images和标签集labels对该模型进行训练。

代码行26-29对照片who.jpg中的人脸进行识别。

在代码行27用训练好的模型对该照片的面部进行预测,返回人物标签值pred_index和置信度评分conf_score,并在代码行28-29分别打印出识别的人物姓名和置信度评分。

程序的运行效果如下所示:

需要指出的是,对人脸识别模型的训练,训练集越多,预测效果越好。

模型一旦训练好后,可以以XML文件的形式将其保存起来,以便下次直接读取调用,以避免每次预测前都要训练一次的麻烦。

三、项目实战

3.1 训练目标人脸识别模型

文件夹persons中有目标人物的几张照片,用照片中的人脸集去训练人脸识别模型,让模型“认识”该人脸,并保存该模型,以便后续利用该模型去“辨认”照片集中的面相。

新建文件task1.ipynb,根据任务目标,按照以下步骤和操作,完成任务一。

任务目标:

提取照片中的人脸数据构成训练集,使用训练集对LBPHFace人脸模型进行训练,将训练好的模型保存起来。

完成步骤:

(1)构建一个人脸检测器

(2)生成目标人脸数据的训练集

(3)训练人脸识别模型

1、构建一个人脸检测器

为方便代码重用,在文件task1.ipynb中定义函数get_face_cascade,以构建一个人脸检测器,代码如下。

1	import cv2
2	import os
3	import numpy as np
4	def get_face_cascade(model_file):
5	    faceCascade=cv2.CascadeClassifier(model_file)
	#利用cv2中已训练好的人脸检测文件model_file来构建一个人脸检测器faceCascade。
6		return faceCascade

2、生成目标人脸数据训练集

根据前面的解决方案,需要获取目标对象的人脸数据和标签值,作为人脸识别模型的训练集。

编写代码如下,得到训练集。

1	def get_faces_trains(file_path,model_file):
2	    images=[]
3	    labels=[]
4	    faceCascade=get_face_cascade(model_file)
5	    for file in os.listdir(file_path):
6	        filePath=os.path.join(file_path,file)
7	        img=cv2.imread(filePath,0)
8	        faces=faceCascade.detectMultiScale(img,1.3,3)
9	        x,y,w,h=faces[0]
10	        images.append(img[y:y+h,x:x+w])
11	        labels.append(1)
12		return images,labels
13	images,labels=get_faces_trains('data/persons/','data/haarcascade_frontalface_default.xml')

代码行2-3定义的变量分别保存人脸数据和人脸标签。

代码行5-11遍历文件目录file_path下所有的目标人物照片文件,在代码行7读入灰度图。

在代码行8利用人脸分类器对灰度图检测人脸,然后在代码行10-11分别保存人脸数据和标签值,因为已知训练照片属于同一个人,所以标签值相同。

代码行13利用定义好的函数get_faces_trains来获取data/persons目录下目标人脸的训练数据。

3、训练人脸识别模型

有了步骤2的训练数据,就可以对LBPHFace模型进行训练,代码如下:

1	faceRecognizer=cv2.face.LBPHFaceRecognizer_create()
2	faceRecognizer.train(images,np.array(labels))
3	faceRecognizer.save('data/models/my_LBPHfaceRec.xml')

因为标签集labels是列表类型,需要转换成向量类型,然后在代码行2对人脸识别模型进行训练,并在代码行3将训练好的模型保存起来,以备后续随时调用。

至此,我们就得到了一个可用于搜索照片的人脸识别模型。

3.2 找到与某个用户最相似的n个用户

任务一已经按照指定的人物照片训练好了人脸识别模型,那么下一步我们就可以利用该模型,去照片集中帮我们找到想要的照片。

根据任务目标,按照以下步骤和操作,完成任务二。

任务目标:

搜索照片集中与目标人脸高度相似的照片,并显示搜索结果。

完成步骤:

(1)加载训练好的模型

(2)搜索照片集中要找的照片

1、加载训练好的模型

初始化人脸识别方法,读取训练好的模型文件,将其作为预测照片的人脸识别器。代码如下:

1	faceRecognizer1=cv2.face.LBPHFaceRecognizer_create()
2	faceRecognizer1.read('data/models/my_LBPHfaceRec.xml')

2、搜索照片集中要找的照片

有了人脸识别器faceRecognizer1,就定义如下方法search_photos,用它去寻找与目标人脸相似的照片,代码如下:

1	def search_photos(file_path,model_file):
2	    faceCascade=get_face_cascade(model_file)
3	    i=0
4	    for file in os.listdir(file_path):
5	        filePath=os.path.join(file_path,file)
6	        pred_img=cv2.imread(filePath)
7	        gray=cv2.cvtColor(pred_img,cv2.COLOR_BGR2GRAY)
8	        faces=faceCascade.detectMultiScale(gray,1.3,3)
9	        x,y,w,h=faces[0]
10	        pred_index,conf_score=faceRecognizer1.predict(gray[y:y+h,x:x+w])
11	        if conf_score<50:
12	            i+=1
13	            cv2.putText(pred_img,str(i),(x+int(w/2),y+int(h/2)),
		    cv2.FONT_HERSHEY_SIMPLEX,1,(0,0,255),3) 
14	            cv2.imshow('foundImage',pred_img)
15	            cv2.waitKey(0)
16	        	cv2.destroyAllWindows()
17	search_photos('data/photos/','data/haarcascade_frontalface_default.xml')

代码行4-16是遍历目录file_path下的照片集,代码行7将读取的彩色图转换成灰度图。

代码行10用人脸识别器faceRecognizer1去预测当前人脸数据应归属于那一类、置信度如何。

其中代码行11-16是判断如果置信度分数<50,则说明当前照片与目标人脸高度相似,通过代码行13在人脸中间部位写上序号i,然后通过代码行14显示该图像。

代码行17是调用定义的函数search_photos,完成照片的搜索任务。

上述代码的运行效果如下图所示:

可以看出,找出的6张照片上的人物与原目标人脸是一个人,说明本次智能搜索是有效的。

当然,在实际应用过程中,不排除漏搜和多搜的情况,这时候就要考虑通过调参、甚至更改人脸检测器和识别模型来改善搜索效果。

更多精彩内容请持续关注本站!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值