使用 OpenCV 和深度学习进行人脸检测
今天的博文分为三个部分。
在第一部分中,我们将讨论更准确的 OpenCV 人脸检测器的起源以及它们在 OpenCV 库中的位置。
然后我将演示如何使用 OpenCV 和深度学习在图像中执行人脸检测。
最后我将讨论如何使用 OpenCV 和深度学习将人脸检测应用于视频流。
这些“更好”的人脸检测器在 OpenCV 中处于什么位置,它们来自哪里?
早在 2017 年 8 月,OpenCV 3.3 正式发布,带来了高度改进的“深度神经网络”(dnn)模块。 该模块支持多种深度学习框架,包括 Caffe、TensorFlow 和 Torch/PyTorch。 dnn 模块的主要贡献者 Aleksandr Rybnikov 投入了大量工作来使该模块成为可能(我们应该向他表示感谢和掌声)。
然而,大多数 OpenCV 用户不知道的是,Rybnikov 在 OpenCV 的官方版本中包含了一个更准确、基于深度学习的人脸检测器(尽管如果你不知道去哪里找可能会有点困难) )。 可以在 dnn 样本的 face_detector 子目录中找到基于 Caffe 的人脸检测器:
opencv/samples/dnn/face_detector at 4.x · opencv/opencv (github.com)
将 OpenCV 的深度神经网络模块与 Caffe 模型一起使用时,您需要两组文件:
定义模型架构(即层本身)的 .prototxt 文件
包含实际层权重的 .caffemodel 文件 链接:
https://raw.githubusercontent.com/opencv/opencv_3rdparty/dnn_samples_face_detector_20180205_fp16/res10_300x300_ssd_iter_140000_fp16.caffemodel
使用使用 Caffe 训练的模型进行深度学习时,需要这两个文件。 但是,您只能在 GitHub 存储库中找到 prototxt 文件。
权重文件不包含在 OpenCVsamples 目录中,需要更多的挖掘才能找到它们……
使用 OpenCV 和深度学习在图像中进行人脸检测
在第一个示例中,我们将学习如何将 OpenCV 的人脸检测应用于单个输入图像。 在下一节中,我们将学习如何修改此代码并将 OpenCV 的人脸检测应用于视频、视频流和网络摄像头。 打开一个新文件,将其命名为 detect_faces.py ,并插入以下代码:
# import the necessary packages
import numpy as np
import argparse
import cv2
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True,
help="path to input image")
ap.add_argument("-p", "--prototxt", required=True,
help="path to Caffe 'deploy' prototxt file")
ap.add_argument("-m", "--model", required=True,
help="path to Caffe pre-trained model")
ap.add_argument("-c", "--confidence", type=float, default=0.5,
help="minimum probability to filter weak detections")
args = vars(ap.parse_args())
复制代码
导入所需的包并解析命令行参数。 我们有三个必需的参数:
--image :输入图像的路径。
--prototxt :Caffe prototxt 文件的路径。
--model :预训练 Caffe 模型的路径。
可选参数 --confidence 可以覆盖默认阈值 0.5。 从那里让我们加载我们的模型并从我们的图像创建一个 blob:
# load our serialized model from disk
print("[INFO] loading model...")
net = cv2.dnn.readNetFromCaffe(args["prototxt"], args["model"])
# load the input image and construct an input blob for the image
# by resizing to a fixed 300x300 pixels and then normalizing it
image = cv2.imread(args["image"])
(h, w) = image.shape[:2]
blob = cv2.dnn.blobFromImage(cv2.resize(image, (300, 300)), 1.0,
(300, 300), (104.0, 177.0, 123.0))
复制代码
首先,我们使用 --prototxt 和 --model 文件路径加载我们的模型。 我们将模型存储为 net(第 20 行)。
然后我们加载图像,提取尺寸,并创建一个 blob。 dnn.blobFromImage 负责预处理,包括设置 blob 尺寸和规范化。 如果您有兴趣了解有关 dnn.blobFromImage 函数的更多信息,我会在这篇博文中详细介绍。 接下来,我们将应用人脸检测:
# pass the blob through the network and obtain the detections and
# predictions
print("[INFO] computing object detections...")
net.setInput(blob)
detections = net.forward()
复制代码
为了检测人脸,将 blob 通过网络。 然后我们将循环检测并在检测到的人脸周围绘制框:
# loop over the detections
for i in range(0, detections.shape[2]):
# extract the confidence (i.e., probability) associated with the
# prediction
confidence = detections[0, 0, i, 2]
# filter out weak detections by ensuring the `confidence` is
# greater than the minimum confidence
if confidence > args["confidence"]:
# compute the (x, y)-coordinates of the bounding box for the
# object
box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
(startX, startY, endX, endY) = box.astype("int")
# draw the bounding box of the face along with the associated
# probability
text = "{:.2f}%".format(confidence * 100)
y = startY - 10 if startY - 10 > 10 else startY + 10
cv2.rectangle(image, (startX, startY), (endX, endY),
(0, 0, 255), 2)
cv2.putText(image, text, (startX, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 255), 2)
# show the output image
cv2.imshow("Output", image)
cv2.waitKey(0)
复制代码
遍历检测结果。
然后,我们提取置信度并将其与置信度阈值进行比较。 我们执行此检查以过滤掉弱检测。 如果置信度满足最小阈值,我们继续绘制一个矩形以及检测概率。
为此,我们首先计算边界框的 (x, y) 坐标。 然后我们构建包含检测概率的置信文本字符串。 如果我们的文本偏离图像(例如当面部检测发生在图像的最顶部时),我们将其向下移动 10 个像素。 我们的面部矩形和置信文本绘制在图像上。
然后,我们再次循环执行该过程后的其他检测。 如果没有检测到,我们准备在屏幕上显示我们的输出图像)。
打开一个终端并执行以下命令:
python detect_faces.py --image 2.jpg --prototxt deploy.proto.txt --model res10_300x300_ssd_iter_140000_fp16.caffemodel
复制代码
使用 OpenCV 和深度学习在视频和网络摄像头中进行人脸检测
既然我们已经学习了如何将 OpenCV 的人脸检测应用于单个图像,让我们还将人脸检测应用于视频、视频流和网络摄像头。 对我们来说幸运的是,我们在上一节中使用 OpenCV 在单个图像中进行人脸检测的大部分代码都可以在这里重用!
打开一个新文件,将其命名为 detect_faces_video.py ,并插入以下代码:
# import the necessary packages
from imutils.video import VideoStream
import numpy as np
import argparse
import imutils
import time
import cv2
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-p", "--prototxt", required=True,
help="path to Caffe 'deploy' prototxt file")
ap.add_argument("-m", "--model", required=True,
help="path to Caffe pre-trained model")
ap.add_argument("-c", "--confidence", type=float, default=0.5,
help="minimum probability to filter weak detections")
args = vars(ap.parse_args())
复制代码
与上面相比,我们需要导入三个额外的包: VideoStream 、 imutils 和 time 。 如果您的虚拟环境中没有 imutils,您可以通过以下方式安装它:
我们的命令行参数基本相同,只是这次我们没有 --image 路径参数。 我们将改用网络摄像头的视频源。 从那里我们将加载我们的模型并初始化视频流:
# load our serialized model from disk
print("[INFO] loading model...")
net = cv2.dnn.readNetFromCaffe(args["prototxt"], args["model"])
# initialize the video stream and allow the camera sensor to warm up
print("[INFO] starting video stream...")
vs = VideoStream(src=0).start()
time.sleep(2.0)
复制代码
加载模型与上面相同。 我们初始化一个 VideoStream 对象,指定索引为零的相机作为源(通常这将是您笔记本电脑的内置相机或检测到的台式机的第一个相机)。 这里有一些快速说明:
如果您希望使用 Raspberry Pi 摄像头模块,Raspberry Pi + picamera 用户可以将其替换为 vs = VideoStream(usePiCamera=True).start()。 如果要解析视频文件(而不是视频流),请将 VideoStream 类换成 FileVideoStream。
然后我们让相机传感器预热 2 秒。 从那里我们循环帧并使用 OpenCV 计算人脸检测:
# loop over the frames from the video stream
while True:
# grab the frame from the threaded video stream and resize it
# to have a maximum width of 400 pixels
frame = vs.read()
frame = imutils.resize(frame, width=400)
# grab the frame dimensions and convert it to a blob
(h, w) = frame.shape[:2]
blob = cv2.dnn.blobFromImage(cv2.resize(frame, (300, 300)), 1.0,
(300, 300), (104.0, 177.0, 123.0))
# pass the blob through the network and obtain the detections and
# predictions
net.setInput(blob)
detections = net.forward()
复制代码
这个块应该看起来很熟悉上一节中的静态图像版本。 在这个块中,我们从视频流中读取一个帧,创建一个 blob,并将 blob 传递给深度神经网络以获得面部检测。
我们现在可以循环检测,与置信度阈值进行比较,并在屏幕上绘制面部框 + 置信度值:
# loop over the detections
for i in range(0, detections.shape[2]):
# extract the confidence (i.e., probability) associated with the
# prediction
confidence = detections[0, 0, i, 2]
# filter out weak detections by ensuring the `confidence` is
# greater than the minimum confidence
if confidence < args["confidence"]:
continue
# compute the (x, y)-coordinates of the bounding box for the
# object
box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
(startX, startY, endX, endY) = box.astype("int")
# draw the bounding box of the face along with the associated
# probability
text = "{:.2f}%".format(confidence * 100)
y = startY - 10 if startY - 10 > 10 else startY + 10
cv2.rectangle(frame, (startX, startY), (endX, endY),
(0, 0, 255), 2)
cv2.putText(frame, text, (startX, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 255), 2)
复制代码
要详细查看此代码块,请查看我们对静止静态图像执行人脸检测的上一节。 这里的代码几乎相同。 现在我们已经绘制了 OpenCV 人脸检测,让我们在屏幕上显示框架并等待按键:
# show the output frame
cv2.imshow("Frame", frame)
key = cv2.waitKey(1) & 0xFF
# if the `q` key was pressed, break from the loop
if key == ord("q"):
break
# do a bit of cleanup
cv2.destroyAllWindows()
vs.stop()
复制代码
我们在屏幕上显示框架,直到按下“q”键,此时我们会跳出循环并执行清理。
总结
在今天的博客文章中,您发现了关于 OpenCV 库的一个鲜为人知的秘密——OpenCV 提供了开箱即用的更准确的人脸检测器(与 OpenCV 的 Haar 级联相比)。
更准确的 OpenCV 人脸检测器是基于深度学习的,特别是利用单镜头检测器 (SSD) 框架和 ResNet 作为基础网络。 感谢 Aleksandr Rybnikov 和 OpenCV 的 dnn 模块的其他贡献者的辛勤工作,我们可以在自己的应用程序中享受这些更准确的 OpenCV 人脸检测器。
希望您能喜欢今天的博文。完成的权重、文件以及代码链接:
于 OpenCV 库的一个鲜为人知的秘密——OpenCV 提供了开箱即用的更准确的人脸检测器(与 OpenCV 的 Haar 级联相比)。
更准确的 OpenCV 人脸检测器是基于深度学习的,特别是利用单镜头检测器 (SSD) 框架和 ResNet 作为基础网络。 感谢 Aleksandr Rybnikov 和 OpenCV 的 dnn 模块的其他贡献者的辛勤工作,我们可以在自己的应用程序中享受这些更准确的 OpenCV 人脸检测器。
希望您能喜欢今天的博文。完成的权重、文件以及代码链接:https://download.csdn.net/download/hhhhhhhhhhwwwwwwwwww/47449496
评论