使用Python+OpenCV预测年龄与性别

共 9800字,需浏览 20分钟

 ·

2021-03-15 10:23

点击上方小白学视觉”,选择加"星标"或“置顶

重磅干货,第一时间送达

本文转自:深度学习与计算机视觉

现在越来越多的应用程序与年龄和性别的自动分类相关,特别是自从社交平台和社交媒体兴起以后。尽管如此,现有的方法在真实图像上的性能仍然明显不足,特别是与最近人脸识别相关的任务在性能上的巨大飞跃相比。——使用卷积神经网络进行年龄和性别分类。
https://talhassner.github.io/home/publication/2015_CVPR
介绍


龄和性别是人脸的两个重要属性,在社会交往中起着非常基础的作用,使得从单个人脸图像中估计年龄和性别成为智能应用中的一项重要任务,如访问控制、人机交互、执法、营销智能以及视觉监控等。

真实世界用例:


另一个例子可能是AgeBot,它是一个Android应用程序,通过人脸识别从照片中确定你的年龄。它可以猜测你的年龄和性别,同时也可以在一张照片中找到多张脸,并估计每张脸的年龄。
受上述用例的启发,我们将在本文中构建一个简单的年龄和性别检测模型,让我们从我的用例开始:
用例——我们将做一些人脸识别,人脸检测的工作,而且我们将使用CNN(卷积神经网络)从youtube视频中预测年龄和性别,只要视频URL是可以用的,你就不需要下载视频,CNN在视频网址上用于年龄和性别预测。
要求:pip install OpenCV-python numpy pip install pafy pip install youtube_dl(了解更多关于youtube-dl的信息:https://rg3.github.io/youtube-dl/
pafy:pafy库用于检索YouTube内容和元数据(如标题、分级、观看次数、持续时间、分级、作者、缩略图、关键字等)。更多有关pafy,点击网址:https://pypi.org/project/pafy/
让我们检查一个样本:
import pafyurl = 'https://www.youtube.com/watch?v=c07IsbSNqfI&feature=youtu.be'vPafy = pafy.new(url)print vPafy.titleprint vPafy.ratingprint vPafy.viewcountprint vPafy.authorprint vPafy.lengthprint vPafy.description
Testing file uploads with Postman (multipart/form-data)4.8709678649911478Valentin Despa1688➡️➡️➡️ 📢 Check my online course on Postman. Get it for only $10 (limited supply):https://www.udemy.com/postman-the-complete-guide/?couponCode=YOUTUBE10I will show you how to debug an upload script and demonstrate it with a tool that can make requests encoded as "multipart/form-data" so that you can send also a file.After this, we will go even further and write tests and begin automating the process.Here is the Git repository containing the files used for this tutorial:https://github.com/vdespa/postman-testing-file-uploads
要遵循的步骤:
  1. 从YouTube获取视频URL。
  2. 使用Haar级联的人脸检测
  3. CNN的性别识别
  4. CNN的年龄识别
1.从YouTube获取视频网址:
获取Youtube视频URL并尝试使用pafy获取视频的属性,如上所述。
2. 使用Haar级联人脸检测:
这是我们大多数人至少听说过的部分。OpenCV/JavaCV提供了方法来导入Haar级联并使用它们来检测人脸。我不会深入解释这一部分。你们可以参考我之前的文章来了解更多关于使用OpenCV进行人脸检测的信息。
  • 文章地址:https://medium.com/analytics-vidhya/how-to-build-a-face-detection-model-in-python-8dc9cecadfe9
3. CNN的性别识别:
使用OpenCV的fisherfaces实现的性别识别非常流行,大家中的一些人可能也尝试过或阅读过它,但是在这个例子中,我将使用不同的方法来识别性别。2015年,以色列两名研究人员Gil Levi和Tal Hassner引入了一种模型,在这个例子中使用了他们训练的CNN模型。我们将使用OpenCV的dnn包,它代表“深度神经网络”。
在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: 包含训练神经网络(训练模型)的信息。
从这里(https://talhassner.github.io/home/publication/2015_CVPR) 下载.prtoxt和.caffemodel。
从这里(https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_frontalface_default.xml) 下载用于人脸检测的haar级联。
让我们开始实现我们的模型吧。
源代码:
import cv2import numpy as npimport pafy#url of the video to predict Age and genderurl = '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 framecap.set(4, 640) #set height of the frameMODEL_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']def load_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)def video_detector(age_net, gender_net): font = cv2.FONT_HERSHEY_SIMPLEXwhile True: 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)#Get Face face_img = image[y:y+h, h:h+w].copy() blob = cv2.dnn.blobFromImage(face_img, 1, (227, 227), MODEL_MEAN_VALUES, swapRB=False)#Predict Gender gender_net.setInput(blob) gender_preds = gender_net.forward() gender = gender_list[gender_preds[0].argmax()] print("Gender : " + gender)#Predict Age 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) #0xFF is a hexadecimal constant which is 11111111 in binary.if cv2.waitKey(1) & 0xFF == ord('q'): breakif __name__ == "__main__":age_net, gender_net = load_caffe_models()video_detector(age_net, gender_net)
现在让我们一起来理解代码:
步骤1:导入所有必需的库。
import cv2import numpy as npimport pafy
步骤2:获取Youtube视频URL并创建一个对象“play”,该对象包含webm/mp4格式的视频的最佳分辨率。
url = 'https://www.youtube.com/watch?v=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
但在我的例子中,我正在读取一个在线视频URL,为此,我将把“play”对象传递给VideoCapture()。
cap = cv2.VideoCapture(play.url)
步骤4:使用set()设置视频帧的高度和宽度。cap.set(propId, value),这里3是宽度的propertyId,4是高度的propertyId。
cap.set(3, 480) #set width of the framecap.set(4, 640) #set height of the frame
步骤5:创建3个单独的列表,用于存储Model_Mean_值、年龄和性别。
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']
步骤6:我定义了一个函数来加载caffemodel和prototxt的年龄和性别检测器,这些基本上都是预先训练好的CNN模型。
def load_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对象。cap.read()返回布尔值(True / False),如果正确读取框架,则它将为True。
所以你可以通过检查这个返回值来检查视频的结尾。
有时,cap可能尚未初始化捕获。在这种情况下,此代码显示错误。
你可以通过cap.isOpened()方法检查它是否已初始化,如果是真就继续执行,否则,请使用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:现在,我们如何使用级联分类器从图像中检测人脸呢?
OpenCV的CascadedClassifier再次使其变得简单,detectMultiScale()可以准确地检测你需要的内容。
detectMultiScale(image, scaleFactor, minNeighbors)
下面是应该传递给detectMultiScale()的参数。
这是一个检测对象的通用函数,因为我们在人脸级联中调用了此函数,所以它将检测人脸。如果找到一个人脸,则返回一个所述人脸的位置列表,格式为“Rect(x,y,w,h)”,如果没有,则返回“None”。
  • Image:第一个输入是灰度图像。
  • scaleFactor:这个函数补偿当一张脸看起来比另一张脸大时发生的大小错误感知,因为它更靠近相机。
  • minNeighbors:一种使用移动窗口检测对象的检测算法,它通过定义在当前窗口附近找到多少个对象,然后才能声明找到的人脸。
faces = face_cascade.detectMultiScale(gray, 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 4维的blob是从图像创建的。可选地调整图像大小并从中心裁剪图像,减去平均值,按比例因子缩放值,交换蓝色和红色通道
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方法的3元组,也可以是单个值,在这种情况下,从图像的每个通道中减去提供的值。如果要执行平均值减法,请确保按(R,G,B)顺序提供3元组,特别是在使用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:预测性别。
#Predict Gendergender_net.setInput(blob)gender_preds = gender_net.forward()gender = gender_list[gender_preds[0].argmax()]
步骤15:预测年龄。
#Predict Ageage_net.setInput(blob)age_preds = age_net.forward()age = age_list[age_preds[0].argmax()]
步骤16:现在我们必须使用openCV的put text()模块将文本放到输出框架上。
putText()的参数如下:
  • 要写入的文本数据
  • 放置位置坐标(即数据开始的左下角)。
  • 字体类型(请检查cv2.putText()文档以获取支持的字体)
  • 字体比例(指定字体大小)
  • 常规的东西,如颜色,厚度,线型等。为了更好的外观,推荐使用线型=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)
最后我们有:
if cv2.waitKey(1) & 0xFF == ord('q'): break
我们的程序等待用户按下一个键最多1毫秒,然后它获取按下键的值,并将其与0xFF进行比较,为了删除底部8位以上的任何内容,并将结果与字母q的ASCII码进行比较,这意味着用户已决定通过按键盘上的q键退出。
输出:视频URL-1:https://www.youtube.com/watch?v=iH1ZJVqJO3Y
视频URL-2:https://www.youtube.com/watch?v=qLNhVC296YI
很有趣,不是吗?但不太准确。
结论:
正如我们在本文中看到的,在短短几行代码中,我们构建了年龄和性别检测模型,从这里开始,你还可以将情感检测和目标检测合并到同一个模型中,并创建一个功能齐全的应用程序。
参考链接:https://towardsdatascience.com/predict-age-and-gender-using-convolutional-neural-network-and-opencv-fd90390e3ce6
下载1:OpenCV-Contrib扩展模块中文版教程
在「小白学视觉」公众号后台回复:扩展模块中文教程即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。

下载2:Python视觉实战项目52讲
小白学视觉公众号后台回复:Python视觉实战项目即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。

下载3:OpenCV实战项目20讲
小白学视觉公众号后台回复:OpenCV实战项目20讲即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。

交流群


欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~


浏览 37
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报