目前,随着社交平台以及社交媒体的兴起,年龄与性别自动分类开始与越来越多的应用相关联。然而,尤其是与近来在人脸识别任务中取得的快速进展相比,使用现有方法识别真实图像的结果并不尽如人意。
比如……
其实,年龄与性别作为面部的两个关键属性,在社交互动中发挥着根本作用。因此,对人脸图像进行年龄性别评估在一些智能应用,如访问权限、人机交互、执法、营销情报和视觉监控等领域具有重要意义。
实际应用
1. 一款名为Quividi的人工智能应用软件,可通过在线面部分析推测用户年龄与性别,并根据分析结果为目标受众自动播放广告。
2. 安卓应用程序AgeBot,可对用户照片进行面部识别从而推测其年纪。该应用不但支持单人年龄和性别推测,同时还能识别多人照片中的不同人脸并推测相应年龄。
受上述用例启发,本篇文章将详细介绍构建一个简单的年龄性别检测模型的相关步骤。那么就从用例开始介绍吧:
用例
人脸识别、人脸检测、以及使用CNN(卷积神经网络)对youtube视频里人物进行年龄与性别预测,视频无需下载,仅需保存网址链接(URL)。在此,使用CNN来预测视频URLs中的人物年龄性别,这一过程将十分有趣。
准备工作
Pip install OpenCV-python
numpy
pip install pafy
pip install youtube_dl(以了解youtube_dl更多相关信息)
pafy
Pafy库用于检索YouTube内容和元数据(包括标题、分级、点击率、持时长、评分、作者、缩略图、关键词等)。要了解更多有关pafy的信息,我们来看看一个样本:
importpafy
url='https://www.youtube.com/watch?v=c07IsbSNqfI&feature=youtu.be'
vPafy= pafy.new(url)
printvPafy.title
printvPafy.rating
printvPafy.viewcount
printvPafy.author
printvPafy.length
printvPafy.description
输出
请在Postman上下载测试文件 (multipart/form-data)
4.87096786499
11478
瓦伦汀·德斯帕(Valentin Despa)
1688
以下是包含本教程所用文件的Git仓库:
https://github.com/vdespa/postman-testing-file-uploads
演示步骤
1. 从YouTube获取视频网址
获取Youtube视频网址,并如上所述用pafy获取视频的属性。
2. 使用Haar cascades检测人脸
大多数人至少对这一部分内容有所耳闻。OpenCV / JavaCV提供了导入Haar-cascades并将其用来检测面部的直接方法。
3. 使用CNN识别性别
使用OpenCV的fisherfaces来识别性别十分流行,有人可能已经尝试此方法或阅读过相关文章。但本文将采取另一种识别性别的方法。这一方法最早在2015年由两位以色列研究人员Gil Levi和Tal Hassner首次使用。本文所用CNN模型便是由这二人所创建。同时,还会用到OpenCV的dnn程序包,dnn代表“深度神经网络”(DeepNatural Networks)。
在dnn程序包中,OpenCV提供了一个名为Net的类,用于填充神经网络。此外,这些软件包支持从众所周知的深度学习框架(如caffe,tensorflow和torch)导入神经网络模型。上文提到的研究员已经发布了他们的CNN caffe模型。因此,在此可以使用CaffeImporter将该模型导入到应用程序中。
4. 使用CNN识别年龄
与性别识别几乎一致,只是将相应的prototxt文件和caffe模型文件改为“deploy_agenet.prototxt”和“age_net.caffemodel”。此外,CNN的输出层(概率层)由8个年龄组的8个值组成(“0-2”,“4-6”,“8-13”,“15-20”,“25-32” “,”38-43“,”48-53“和”60-“)
一个caffe模型包含2个文件:
(1).prototxt - 包含CNN定义文件,定义了神经网络中的不同层以及各层的输入、输出和功能。
(2) .caffemodel - 包含经过训练的神经网络(训练模型)信息。
下载.prtotxt和.caffemodel:https://talhassner.github.io/home/publication/2015_CVPR
下载用于人脸检测的haar cascade:https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_frontalface_default.xml
接下来开始编写模型。
源代码
importcv2
importnumpy as np
importpafy
#urlof the video to predict Age and gender
url= 'https://www.youtube.com/watch?v=c07IsbSNqfI&feature=youtu.be'
vPafy= pafy.new(url)
play= vPafy.getbest(preftype="mp4")
cap= cv2.VideoCapture(play.url)
cap.set(3,480) #set width of the frame
cap.set(4,640) #set height of the frame
MODEL_MEAN_VALUES= (78.4263377603, 87.7689143744, 114.895847746)
age_list= ['(0, 2)', '(4, 6)', '(8, 12)', '(15, 20)', '(25, 32)', '(38, 43)', '(48,53)', '(60, 100)']
gender_list= ['Male', 'Female']
defload_caffe_models():
age_net =cv2.dnn.readNetFromCaffe('deploy_age.prototxt', 'age_net.caffemodel')
gender_net= cv2.dnn.readNetFromCaffe('deploy_gender.prototxt', 'gender_net.caffemodel')
return(age_net,gender_net)
defvideo_detector(age_net, gender_net):
font = cv2.FONT_HERSHEY_SIMPLEX
whileTrue:
ret, image = cap.read()
face_cascade =cv2.CascadeClassifier('haarcascade_frontalface_alt.xml')
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray,1.1, 5)
if(len(faces)>0):
print("Found {}faces".format(str(len(faces))))
for(x, y, w, h )in faces:
cv2.rectangle(image, (x, y), (x+w, y+h),(255, 255, 0), 2)
#GetFace
face_img = image[y:y+h, h:h+w].copy()
blob = cv2.dnn.blobFromImage(face_img, 1,(227, 227), MODEL_MEAN_VALUES, swapRB=False)
#PredictGender
gender_net.setInput(blob)
gender_preds = gender_net.forward()
gender =gender_list[gender_preds[0].argmax()]
print("Gender : " + gender)
#PredictAge
age_net.setInput(blob)
age_preds = age_net.forward()
age = age_list[age_preds[0].argmax()]
print("Age Range: " + age)
overlay_text= "%s %s" % (gender, age)
cv2.putText(image, overlay_text, (x, y),font, 1, (255, 255, 255), 2, cv2.LINE_AA)
cv2.imshow('frame',image)
#0xFFis a hexadecimal constant which is 11111111 in binary.
ifcv2.waitKey(1) & 0xFF == ord('q'):
break
if__name__ == "__main__":
age_net,gender_net = load_caffe_models()
video_detector(age_net,gender_net)
下面分析一下源代码:
第1步: 导入全部所需库
importcv2
importnumpy as np
importpafy
第2步:获取Youtube视频URL,并创建对象‘play’包含webm/mp4格式下视频最佳分辨率。
url='https://www.youtube.com/watchv=c07IsbSNqfI&feature=youtu.be'
vPafy= pafy.new(url)
play= vPafy.getbest(preftype="mp4")
第3步:通常情况下必须用摄相机捕捉直播。OpenCV为此提供了一个非常简单的接口。从摄相机捕获到的视频可以转换为灰度视频来显示。操作起来也很容易。
捕获视频需要先创建视频捕获对象。参数可以是设备索引或视频文件名称。设备索引通过数字指定连接的摄像头。通常会连接一台摄像机(如本文所示)。因此,只用输入0(或-1)。也可以通过输入1来选择第二个摄像机,依此类推。如此一来,便可以逐帧捕获。
cap= cv2.VideoCapture(0) #if you are using webcam
但本文所示案例使用的是在线视频网址,因此要在VideoCapture()函数中输入对象'play'。
cap= cv2.VideoCapture(play.url)
第4步:使用set()设置视频的帧高和帧宽。cap.set(propId,value),代码中的3代表帧宽,4代表帧高。
cap.set(3,480) #set width of the frame
cap.set(4,640) #set height of the frame
第5步:创建3个单独列表分别存储Model_Mean_Values,Age和Gender数据。
MODEL_MEAN_VALUES=(78.4263377603,87.7689143744,114.895847746)
age_list= ['(0,2)','(4,6)','(8,12)','(15,20)','(25,32)',''(38,43)' ,'(48,53)','(60,100)']
gender_list= ['男','女']
第6步:定义一个函数来加载年龄和性别检测器的caffe 模型和prototxt文件,它们都是基础的CNN预先训练模型,将进行检测工作。
defload_caffe_models():
age_net =cv2.dnn.readNetFromCaffe('deploy_age.prototxt', 'age_net.caffemodel')
gender_net= cv2.dnn.readNetFromCaffe('deploy_gender.prototxt', 'gender_net.caffemodel')
return(age_net,gender_net)
第7步:执行面部检测,年龄检测和性别检测。为此,要在主函数内创建一个video_detector(age_net,gender_net)函数,并将age_net和gender_net作为传递参数。
if__name__==“__ main__”:
age_net,gender_net = load_caffe_models()
video_detector(age_net,gender_net)
第8步:读取第3步时从VideoCapture()创建的捕获对象。
cap.read()会返回运算(True / False)。如果读取到当前帧,则显示True。
#因此可以通过确认返回值来检查视频结尾。
#有时,cap函数可能尚未开启捕获,因此代码会显示错误。
#使用cap.isOpened()来检查是否已开启。如果结果为True则已开,否则用cap.open()打开。
ret,image = cap.read()
第9步:根据OpenCV人脸检测器要求,将图像转换为灰度图。
gray= cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
第10步:加载预先建立的人脸检测模型。
face_cascade=
cv2.CascadeClassifier('haarcascade_frontalface_alt.xml')
第11步:接下来,如何使用CascadeClassifier从图像中检测人脸?
OpenCV的级联分类器操作十分简单,借助detectMultiScale()函数便可准确检测所需内容。
detectMultiScale(image,scaleFactor,minNeighbors)
以下是detectMultiScale()函数参数。
作为一个检测对象的常用函数,在此它能够结合CascadeClassifier中的人脸,如检测到人脸,将以“Rect(x,y,w,h)”的形式返回上述人脸列表,如果没有,则返回“None”。
· Image:首先输入人脸灰度图。
· scaleFactor:缩放图像以减少由于对象与摄像头距离不一而导致人脸尺寸不同带来的检测误差。
· minNeighbors:使用移动窗口来检测对象的算法,用来定义当前识别人脸附近还能识别到的人脸个数。
faces =face_cascade.detectMultiScale(灰色,1.1,5)
第12步:循环遍历人脸列表并在视频人脸上绘制矩形。此步骤主要是识别并分割人脸,确认尺寸并在人脸处绘制矩形。
for(x, y, w, h )in faces:
cv2.rectangle(image, (x, y), (x+w, y+h),(255, 255, 0), 2)
#Get Face
face_img = image[y:y+h, h:h+w].copy(
第13步:OpenCV提供了帮助深度学习分类中图像预处理的函数:blobFromImage(). 运行方式为:
· 均值消减
· 缩放
· 并选择性频道交换
blobFromImage可根据图像创建四维数组。可选择从中心调整大小和裁剪图像,减去平均值,通过scalfactor缩放值,交换蓝色和红色通道。
blob= cv2.dnn.blobFromImage(image,scalefactor = 1.0,size,mean,swapRB = True)
1. image:指通过深度神经网络进行分类之前想要预处理的输入图像。
2.scale factor:在减去均值之后,可以选择按比例缩放图像。该值默认为1.0(即没有缩放),但也可以设置其他值。此处还要注意,缩放比例应该是1 /σ,实际上输入通道(均值消减之后)将会乘以比例因子。
3.size:指使用卷积神经网络适用的图像尺寸。当前大多数先进神经网所用尺寸为224×224、227×227或299×299。
4. mean:指均值消减。既可以减去RGB均值三元组,也可以从图像的各个通道中减去所提供的单个平均值。进行均值消减时,要注意确保三元组顺序(依次是R,G,B),尤其是在执行swapRB = True默认行为时。
5. swapRB:OpenCV假定图像处于BGR信道顺序;但是,平均值假设使用RGB顺序。要解决这种差异,可以通过将此值设置为True来交换图像中的R和B通道。默认情况下,OpenCV执行此频道交换。
blob =cv2.dnn.blobFromImage(face_img,1,(227,227),MODEL_MEAN_VALUES,swapRB = False)
第14步:预测性别
#PredictGender
gender_net.setInput(blob)
gender_preds= gender_net.forward()
gender= gender_list[gender_preds[0].argmax()]
第15步:预测年龄
#PredictAge
age_net.setInput(blob)
age_preds= age_net.forward()
age= age_list[age_preds[0].argmax()]
第16步:使用openCV的putText()函数在输出框架上放置文本。
cv2.putText()的参数包括:
· 要写入的文本数据
· 数据放置的位置坐标(即数据开始的左下角)。
· 字体类型(确认cv2.putText()文件夹所支持字体)
· 字体比例(指定字体大小)
· 如颜色,粗细,线型等字体常规设置。为了美观,推荐使用lineType = cv2.LINE_AA。
overlay_text= "%s %s" % (gender, age)
cv2.putText(image,overlay_text, (x, y), font, 1, (255, 255, 255), 2, cv2.LINE_AA)
第17步:最终输出
cv2.imshow('frame',image)
最后一行:
ifcv2.waitKey(1) & 0xFF == ord('q'):
break
此程序仅需用户等待1毫秒。用户按下键盘按键后,程序会结合0xFF进行AND运算,删除底部所有8位以上的内容,并将其结果与ASCII代码进行比较,其中字母q代表用户可按下键盘中的q键(quit)来退出。
输出:
Video URL-1: https://www.youtube.com/watch?v=iH1ZJVqJO3Y
Video URL-2:https://www.youtube.com/watch?v=qLNhVC296YI
是不是很有趣呢?尽管结果并不那么精确。
本文暂时没有评论,来添加一个吧(●'◡'●)