https://pyimagesearch.com/2018/02/26/face-detection-with-opencv-and-deep-learning/?utm_source=Drip&utm_medium=Email&utm_campaign=CVandDLCrashCourse&utm_content=email1
Face detection with OpenCV and deep learning
opencv可以使用库附带的经过预训练的深度学习人脸检测器模型,执行快速、准确的人脸检测
The Caffe-based face detector can be found in the face_detector sub-directory of the dnn samples
基于Caffe的人脸检测器可以在dnn样本的face_detector子目录中找到。当将OpenCV的深度神经网络模块与Caffe模型一起使用时,您需要两组文件:
使用使用Caffe训练的模型进行深度学习时,这两个文件都是必需的
基于单镜头检测器(SSD)框架,具有ResNet基础网络。
#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")
# caffe prototxt文件路径
ap.add_argument("-m", "--model", required=True,
help="path to Caffe pre-trained model")
# 过预训练的Caffe模型的路径
ap.add_argument("-c", "--confidence", type=float, default=0.5,
help="minimum probability to filter weak detections")
# 可选参数,默认0.5
args = vars(ap.parse_args())
cv2.dnn
是 OpenCV 中的深度学习模块。readNetFromCaffe()
用于从 Caffe 框架中读取神经网络模型,接收两个参数:一个表示神经网络架构的配置文件(定义了神经网络的层次结构、层参数和连接关系);一个包含经过训练权重的模型文件(包含了训练过的神经网络模型的权重参数)。
根据caffe prototxt和caffe model的路径加载并建立模型net–>加载图像,提取尺寸–>create a blob。(dnn.blobFromImage负责预处理,包括设置blob尺寸和标准化)如下:
# load our serialized model from disk
print("[INFO] loading model...")
net = cv2.dnn.readNetFromCaffe(args["prototxt"], args["model"]) #加载模型并存储为net
# net对象可以用于进行图像分类、对象检测等深度学习任务
# 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] # 提取尺寸,取 shape 的前两个元素,即图像的高度和宽度
blob = cv2.dnn.blobFromImage(cv2.resize(image, (300, 300)), 1.0,
(300, 300), (104.0, 177.0, 123.0)) # create a blob,生成输入神经网络的图像块
#将输入的image调整制定尺寸300,300
# dnn.blobFromImage负责预处理,生成blob作为神经网络的输入,包括设置blob尺寸和标准化,接收调整后的image;1.0是缩放因子,1表示不缩放;300,300是期望尺寸,因为神经网络输入层需要固定尺寸;(104.0, 177.0, 123.0) 是一个可选的均值减法操作,从图像的每个通道中减去对应的均值值,帮助预处理。
#blob 对象现在为:经过调整大小、缩放和预处理的图像数据
apply face detection:
# pass the blob through the network and obtain the detections and
# predictions
print("[INFO] computing object detections...")
net.setInput(blob)#输入blob到神经网络模型,对输入blob进行推断,并获取输出结果
detections = net.forward()#对神经网络进行前向推断,得到推断结果,可能包含物体检测的边界框、分类结果、置信度等信息
为了检测人脸,我们将blob应用net模型。将开启循环检测,并在检测到的人脸周围绘制方框:
# loop over the detections
for i in range(0, detections.shape[2]):#循环次数:检测对象的数量
# detections 是神经网络的输出结果,通常是一个包含多个检测对象的数组或矩阵。
# shape 是一个属性,用于获取数组或矩阵的维度信息。
# detections.shape[2] 表示获取 detections 的第三个维度的大小,也就是检测对象的数量
# 在循环体内部,可以通过 detections[:,:,i] 来访问和处理每个具体的检测对象的相关信息
# 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])
# detections[0, 0, i, 3:7] 是用于访问第 i 个检测对象的边界框信息。
# 0, 0 表示第一个维度和第二个维度的索引,i 表示第三个维度的索引,
# 3:7 表示从第四个元素到第七个元素的切片,对应边界框的坐标信息。
# np.array([w, h, w, h]) 创建了一个包含图像宽度 w 和高度 h 的数组,
# 重复两次以对应边界框的坐标顺序为 (x, y, width, height)
# 该语句:对边界框的坐标进行了缩放操作,以匹配原始图像的尺寸。
# 得到的 box 对象包含了经过缩放的边界框坐标信息
(startX, startY, endX, endY) = box.astype("int")
# 计算边界框坐标,将box边界框中的坐标转换为整数类型
# 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
# 防止文本远离图像,将其下移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)
import argparse
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True,
help="path to input image")
args = vars(ap.parse_args())
ap = argparse.ArgumentParser()
是创建一个参数解析器对象的代码,它是 argparse
模块中的一个类,用于创建命令行参数解析器。
ap
是创建的参数解析器对象,可以用于定义、解析和获取命令行参数。
通过调用该函数,可以创建一个空的参数解析器对象,并将其赋值给变量 ap。参数解析器对象可以用于在命令行中解析和获取参数值,以便根据不同的参数执行相应的操作。
ap.add_argument("-i", "--image", required=True, help="path to input image")
是向参数解析器添加一个名为 -i 或 --image 的命令行参数的代码。
ap.add_argument()
是参数解析器对象的方法,用于向解析器添加命令行参数。
"-i"
是命令行参数的短格式,即单个字符形式的参数名。
"--image"
是命令行参数的长格式,即多个字符形式的参数名。
required=True
表示该参数是必需的,必须在命令行中提供。
help="path to input image"
是该参数的帮助信息,用于在命令行中显示参数的用法和描述。
args = vars(ap.parse_args())
是解析命令行参数并将其存储在字典中的代码。
ap.parse_args()
是参数解析器对象的方法,用于解析命令行参数。
vars()
是 Python 内置函数,用于将对象转换为字典形式。
可以通过 args["image"]
或 args.image
来获取输入图像的路径值。