作者选择了 开放式互联网 / 自由言论基金作为 写给捐赠计划的一部分接受捐款。
介绍
图像构成了每天生成的大量数据,这使得处理这些图像的能力很重要。 处理图像的一种方法是通过 face detection。
A Haar Cascade是用来在图像中找到一个感兴趣的对象的物体检测方法. 该算法是在大量的正面和负面样本上训练的,其中正面样本是包含感兴趣的对象的图像。
在本教程中,您将使用从 OpenCV和 Python的预先训练的 Haar Cascade模型来检测和从图像中提取面孔。
前提条件
一个 本地Python 3开发环境,包括 pip
,用于安装Python包的工具,以及 venv
,用于创建虚拟环境。
步骤 1 – 配置本地环境
在您开始编写代码之前,您首先将创建一个工作区来存储代码并安装一些依赖性。
使用mkdir
命令创建项目目录:
1mkdir face_scrapper
更改到新创建的目录:
1cd face_scrapper
接下来,您将为该项目创建一个虚拟环境. 虚拟环境会隔离不同的项目,以便不同的依赖不会造成任何干扰。
1python3 -m venv face_scrapper
激活隔离环境:
1source face_scrapper/bin/activate
现在你会看到你的提示是前缀与你的虚拟环境的名称:
现在你已经激活了虚拟环境,你会使用nano
或你最喜欢的文本编辑器来创建一个requirements.txt
文件。
1nano requirements.txt
接下来,您需要安装三个依赖程序来完成本教程:
numpy
: numpy是一个 Python 库,增加了对大、多维数组的支持。它还包含了大量数学函数来操作数组。 *opencv-utils
:这是 OpenCV 的扩展库,其中包括辅助函数。 *opencv-python
:这是 Python 使用的核心 OpenCV 模块。
向文件添加以下依赖:
1[label requirements.txt]
2numpy
3opencv-utils
4opencv-python
保存并关闭文件。
通过将requirements.txt
文件传送到Python包管理器pip
来安装依赖性,该-r
标志指定了requirements.txt
文件的位置。
1pip install -r requirements.txt
在此步骤中,您为您的项目设置了虚拟环境,并安装了必要的依赖性,您现在已经准备好开始编写代码,以在下一步中从输入图像中检测面孔。
步骤2 - 写作和运行面部检测器脚本
在本节中,你会写代码,将图像作为输入,并返回两个东西:
- 在输入图像中发现的面孔数量. * 一个新的图像,每个被检测到的面孔周围有一个直角图。
首先,创建一个新的文件来保存您的代码:
1nano app.py
在这个新文件中,先开始写代码,先导入必要的库。你将在这里导入两个模块:‘cv2’和‘sys’。‘cv2’模块将‘OpenCV’库导入程序,而‘sys’则导入常见的Python函数,如‘argv’,您的代码将使用。
1[label app.py]
2import cv2
3import sys
接下来,您将指定输入图像将在运行时作为参数传递到脚本中。 读取第一个参数的 Pythonic 方法是将 sys.argv[1]
函数返回的值分配给一个变量:
1[label app.py]
2...
3imagePath = sys.argv[1]
图像处理的一个常见的做法是首先将输入图像转换为灰度,这是因为检测亮度,而不是颜色,通常会在对象检测中产生更好的结果。
1[label app.py]
2...
3image = cv2.imread(imagePath)
4gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
.imread() 函数将输入图像转换为 OpenCV 对象,然后 OpenCV 的.cvtColor() 函数将输入图像对象转换为灰度对象。
现在您已添加代码来加载图像,您将添加在指定的图像中检测面孔的代码:
1[label app.py]
2...
3faceCascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")
4faces = faceCascade.detectMultiScale(
5 gray,
6 scaleFactor=1.3,
7 minNeighbors=3,
8 minSize=(30, 30)
9)
10
11print("Found {0} Faces!".format(len(faces)))
此代码将创建一个faceCascade
对象,用cv2.CascadeClassifier
方法加载 Haar Cascade 文件,从而允许 Python 和您的代码使用 Haar Cascade。
接下来,该代码将OpenCV的 .detectMultiScale()
方法应用到 faceCascade
对象上. 这将为图像中检测到的所有面孔生成一个 list of rectangles. The list of rectangles is a collection of pixel locations from the image, in the form of `Rect(x,y,w,h)'。
以下是您使用的代码的其他参数的摘要:
gray
: 此选项指定了您先前装入的 OpenCV 灰度图像对象的使用 。- " 尺度因素 " : 这个参数指定了每个图像尺度降低图像大小的速率. 您的模型在训练期间有固定的尺度,因此输入图像可以缩放以被改进检测. 这一过程在达到由 " MaxSize " 和 " minSize " 界定的阈值后停止。
- " 邻居 " : 此参数指定了每个候选矩形需要保留多少个邻居或检测. 较高的数值可能导致较少的假正值,但过高的数值可以消除真正的正值.
- " 缩小 " : 这使得您可以定义以像素测量的最小可能对象大小 。 忽略小于此参数的物体 。 .
在生成直角列表后,面孔随后以len
函数计数,然后在运行脚本后返回检测到的面孔数量作为输出。
接下来,您将使用OpenCV的 .rectangle()
方法来描绘被检测到的面孔的直角:
1[label app.py]
2...
3for (x, y, w, h) in faces:
4 cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)
此代码使用一个 for loop 来迭代从 faceCascade.detectMultiScale
方法返回的像素位置列表,每个被检测到的对象。
图像
告诉代码在原始输入图像上绘制直角。 *(x,y), (x+w, y+h)
是检测对象的四个像素位置。直角
将使用这些位置并绘制在输入图像中检测对象周围的直角。 *(0, 255, 0)
是形状的颜色。
现在你已经添加了代码来绘制矩形,使用OpenCV的.imwrite()
方法将新图像写入本地文件系统为faces_detected.jpg
。
1[label app.py]
2...
3status = cv2.imwrite('faces_detected.jpg', image)
最后,将此代码添加到控制台中,以打印返回.imwrite() 函数的 true
或 false
状态。
1[label app.py]
2...
3print ("Image faces_detected.jpg written to filesystem: ",status)
完成的文件将看起来像这样:
1[label app.py]
2import cv2
3import sys
4
5imagePath = sys.argv[1]
6
7image = cv2.imread(imagePath)
8gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
9
10faceCascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")
11faces = faceCascade.detectMultiScale(
12 gray,
13 scaleFactor=1.3,
14 minNeighbors=3,
15 minSize=(30, 30)
16)
17
18print("[INFO] Found {0} Faces!".format(len(faces)))
19
20for (x, y, w, h) in faces:
21 cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
22
23status = cv2.imwrite('faces_detected.jpg', image)
24print("[INFO] Image faces_detected.jpg written to filesystem: ", status)
一旦您确认所有内容都正确输入,请保存并关闭文件。
注:此代码源自公开可用的 OpenCV 文档。
您的代码已经完成,您已经准备好运行脚本。
步骤3 - 运行脚本
在此步骤中,你将使用一个图像来测试你的脚本. 当你找到一个图像你想用来测试,将其保存到同一个目录作为你的app.py
脚本.本教程将使用以下图像:
如果您想使用相同的图像进行测试,请使用以下命令来下载它:
1curl -O assets/CART-63965/people_with_phones.png
一旦你有一个图像来测试脚本,运行脚本,并提供图像路径作为一个参数:
1python app.py path/to/input_image
一旦脚本完成运行,您将收到这样的输出:
1[secondary_label Output]
2[INFO] Found 4 Faces!
3[INFO] Image faces_detected.jpg written to filesystem: True
真实
输出告诉你,更新的图像已成功写入文件系统. 在本地机器上打开图像,查看新文件的更改:
你应该看到你的脚本在输入图像中检测了四个面孔,并绘制了直角形来标记它们。
步骤4 - 提取面孔并将它们保存到本地(可选)
在之前的步骤中,您编写了代码,使用OpenCV和 Haar Cascade来检测和绘制图像中的面孔周围的直角形. 在本节中,您将修改您的代码,从图像中提取检测到的面孔到自己的文件。
开始使用您的文本编辑器重新打开app.py
文件:
1nano app.py
接下来,在cv2.rectangle
线下添加突出的行:
1[label app.py]
2...
3for (x, y, w, h) in faces:
4 cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
5 roi_color = image[y:y + h, x:x + w]
6 print("[INFO] Object found. Saving locally.")
7 cv2.imwrite(str(w) + str(h) + '_faces.jpg', roi_color)
8...
roi_color
对象从原始输入图像上的面孔
列表中绘制了像素的位置,而x
,y
,h
和w
变量是通过faceCascade.detectMultiScale
方法检测到的每个对象的像素位置。
一旦完成,代码会使用cv2.imwrite
方法将场景保存为新图像,将场景的宽度和高度附加到正在写的图像的名称中,这将使名称在检测到多个面孔的情况下保持独特。
更新后的app.py
脚本将看起来像这样:
1[label app.py]
2import cv2
3import sys
4
5imagePath = sys.argv[1]
6
7image = cv2.imread(imagePath)
8gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
9
10faceCascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")
11faces = faceCascade.detectMultiScale(
12 gray,
13 scaleFactor=1.3,
14 minNeighbors=3,
15 minSize=(30, 30)
16)
17
18print("[INFO] Found {0} Faces.".format(len(faces)))
19
20for (x, y, w, h) in faces:
21 cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
22 roi_color = image[y:y + h, x:x + w]
23 print("[INFO] Object found. Saving locally.")
24 cv2.imwrite(str(w) + str(h) + '_faces.jpg', roi_color)
25
26status = cv2.imwrite('faces_detected.jpg', image)
27print("[INFO] Image faces_detected.jpg written to filesystem: ", status)
要总结一下,更新后的代码使用像素位置将图像中的面孔提取到新的文件中。
现在你已经更新了代码,你已经准备好再次运行脚本:
1python app.py path/to/image
您将看到相似的输出,一旦您的脚本完成处理图像:
1[secondary_label Output]
2[INFO] Found 4 Faces.
3[INFO] Object found. Saving locally.
4[INFO] Object found. Saving locally.
5[INFO] Object found. Saving locally.
6[INFO] Object found. Saving locally.
7[INFO] Image faces_detected.jpg written to file-system: True
根据您的样本图像中有多少个面孔,您可能会看到更多或更少的输出。
在执行脚本后查看工作目录的内容,您将看到输入图像中发现的所有面孔的头像的文件。
您现在将看到从工作目录中收集的输入图像中提取的头像:
在此步骤中,您修改了脚本以从输入图像中提取被检测到的对象并将其保存到本地。
结论
在本教程中,您写了一本使用OpenCV和Python来检测,计数和从输入图像中提取面孔的脚本,您可以通过使用OpenCV库的不同预先训练的Haar Cascade来检测不同对象,或者您可以学习如何训练自己的Haar Cascade。