作者|Nagesh Singh Chauhan
编译|Flin
来源|towardsdatascience
越来越多的应用程序与年龄和性别的自动分类相关,特别是自从社交平台和社交媒体兴起以来。尽管如此,现有的方法在真实图像上的性能仍然明显不足,特别是与最近报道的与人脸识别相关的任务在性能上的巨大飞跃相比。——使用卷积神经网络进行年龄和性别分类(https://talhassner.github.io/home/publication/2015_CVPR)
介绍
年龄和性别是人脸的两个重要属性,在社会交往中起着非常基础的作用,使得从单个人脸图像中估计年龄和性别成为智能应用中的一项重要任务,如访问控制、人机交互、执法、营销智能以及视觉监控等。
真实世界用例:
最近我遇到了Quividi,它是一个人工智能软件应用程序,用于根据在线人脸分析检测经过的用户的年龄和性别,并根据目标受众自动开始播放广告。
另一个例子可能是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 pafy
url = 'https://www.youtube.com/watch?v=c07IsbSNqfI&feature=youtu.be'
vPafy = pafy.new(url)
print vPafy.title
print vPafy.rating
print vPafy.viewcount
print vPafy.author
print vPafy.length
print vPafy.description
Testing file uploads with Postman (multipart/form-data)
4.87096786499
11478
Valentin Despa
1688
➡️➡️➡️ 📢 Check my online course on Postman. Get it for only $10 (limited supply):
https://www.udemy.com/postman-the-complete-guide/?couponCode=YOUTUBE10
I 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
要遵循的步骤:
- 从YouTube获取视频URL。
- 使用Haar级联的人脸检测
- CNN的性别识别
- CNN的年龄识别
1.从YouTube获取视频网址:
获取Youtube视频URL并尝试使用pafy获取视频的属性,如上所述。
2. 使用Haar级联人脸检测:
这是我们大多数人至少听说过的一部分。OpenCV/JavaCV提供了直接的方法来导入Haar级联并使用它们来检测人脸。我不会深入解释这一部分。你们可以参考我之前的文章来了解更多关于使用OpenCV进行人脸检测的信息。
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在该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 cv2
import numpy as np
import pafy
#url of 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']
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_SIMPLEX
while 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'):
break
if __name__ == "__main__":
age_net, gender_net = load_caffe_models()
video_detector(age_net, gender_net)
现在让我们一起来理解代码:
步骤1:导入所有必需的库。
import cv2
import numpy as np
import 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")
第三步:通常,我们必须用相机捕捉现场的视频流。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 frame
cap.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']
第六步:我定义了一个函数来加载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()。它执行:
平均减法
缩放比例
和可选的通道交换
所以blobFromImage4维的blob是从图像创建的。可选地调整图像大小并从中心裁剪图像,减去平均值,按比例因子缩放值,交换蓝色和红色通道
blob = cv2.dnn.blobFromImage(image, scalefactor=1.0, size, mean, swapRB=True)
-
image:这是输入图像,我们要先对其进行预处理,然后再通过我们的深度神经网络进行分类。
-
scale factor: 在我们执行平均值减法之后,我们可以选择按某个因子缩放图像。这个值默认为1.0(即没有缩放),但我们也可以提供另一个值。还要注意的是,比例因子应该是1/σ,因为我们实际上是将输入通道(在平均值减去之后)乘以比例因子。
-
size: 这里我们提供卷积神经网络所期望的空间大小。对于大多数目前最先进的神经网络来说,这可能是224×224、227×227或299×299。
-
mean:这些是我们的平均减法值。它们可以是RGB方法的3元组,也可以是单个值,在这种情况下,从图像的每个通道中减去提供的值。如果要执行平均值减法,请确保按(R,G,B)顺序提供3元组,特别是在使用swapRB=True的默认行为时。
-
swapRB:OpenCV假设图像是BGR通道顺序的;但是,平均值假设我们使用的是RGB顺序。为了解决这个差异,我们可以通过将这个值设置为True来交换图像中的R和B通道。默认情况下,OpenCV为我们执行此通道交换。
blob = cv2.dnn.blobFromImage(face_img, 1, (227, 227), MODEL_MEAN_VALUES, swapRB=False)
第14步:预测性别。
#Predict Gender
gender_net.setInput(blob)
gender_preds = gender_net.forward()
gender = gender_list[gender_preds[0].argmax()]
第15步:预测年龄。
#Predict Age
age_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
进行比较,0xFF
删除底部8位以上的任何内容,并将结果与字母q的ASCII码进行比较,这意味着用户已决定通过按键盘上的q键退出。
输出:视频URL-1:https://www.youtube.com/watch?v=iH1ZJVqJO3Y
视频URL-2:https://www.youtube.com/watch?v=qLNhVC296YI
很有趣,不是吗?但不太准确。
结论:
正如我们在本文中看到的,在短短几行代码中,我们构建了年龄和性别检测模型,从这里开始,你还可以将情感检测和目标检测合并到同一个模型中,并创建一个功能齐全的应用程序。
欢迎关注磐创AI博客站:
http://panchuang.net/
sklearn机器学习中文官方文档:
http://sklearn123.com/
欢迎关注磐创博客资源汇总站:
http://docs.panchuang.net/
原创文章,作者:磐石,如若转载,请注明出处:https://panchuang.net/2020/10/19/%e4%bd%bf%e7%94%a8%e5%8d%b7%e7%a7%af%e7%a5%9e%e7%bb%8f%e7%bd%91%e7%bb%9c%e5%92%8copencv%e9%a2%84%e6%b5%8b%e5%b9%b4%e9%be%84%e5%92%8c%e6%80%a7%e5%88%ab/