使用OpenCV进行人脸识别--(5)进行人脸识别--图片

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_41204464/article/details/100832457

准备工作

1)测试集的一张图片

疑惑

1)我们的六个命令行参数解析  

  • image  :输入图像的路径。我们将尝试识别此图像中的面部。
  • detector :OpenCV深度学习人脸探测器的路径。我们将使用此模型来 检测图像中面部ROI的位置。
  • - embedding-model  :OpenCV深度学习面嵌入模型的路径。我们将使用此模型从面部ROI中提取128-D面部嵌入 - 我们将数据提供给识别器。
  • - recognizer  :识别器模型的路径。我们在步骤#2中训练了我们的SVM识别器 。这实际上 决定了一张脸是
  • le  :标签编码器的路径。这包含我们的脸部标签,如 'adrian'   或 'trisha'  。
  • confidence  :过滤弱脸检测的可选阈值。

一定要研究这些命令行参数 - 了解两个深度学习模型和SVM模型之间的区别非常重要。

2)现在我们已经处理了导入和命令行参数,让我们将三个模型从磁盘加载到内存中:

25

26

27

28

29

30

31

32

33

34

35

36

37

38

# load our serialized face detector from disk

print("[INFO] loading face detector...")

protoPath = os.path.sep.join([args["detector"], "deploy.prototxt"])

modelPath = os.path.sep.join([args["detector"],

"res10_300x300_ssd_iter_140000.caffemodel"])

detector = cv2.dnn.readNetFromCaffe(protoPath, modelPath)

 

# load our serialized face embedding model from disk

print("[INFO] loading face recognizer...")

embedder = cv2.dnn.readNetFromTorch(args["embedding_model"])

 

# load the actual face recognition model along with the label encoder

recognizer = pickle.loads(open(args["recognizer"], "rb").read())

le = pickle.loads(open(args["le"], "rb").read())

我们在这个块中加载了三个模型。存在冗余的风险,我想明确提醒你模型之间的差异:

  1. 探测器  :预先训练的Caffe DL模型,用于探测人脸在图像中的位置第27-30行)。
  2. embedder  :预训练的 Torch DL模型,用于计算我们的128-D面嵌入第34行)。
  3. 识别器  :我们的线性SVM人脸识别模型(第37行)。我们在第2步训练了这个模型 。

1和2都是  预先训练的,这意味着它们是由OpenCV按原样提供给你的。它们被埋在GitHub上的OpenCV项目中,但为了方便起见,我将它们包含在今天帖子的  “下载”部分中。我还按照我们将它们用于识别OpenCV面部的顺序对模型进行编号。

我们还加载了标签编码器,其中包含我们模型可识别的人员的姓名(第38行)。

 

3)现在让我们加载我们的图像并  检测面部:

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

# load the image, resize it to have a width of 600 pixels (while

# maintaining the aspect ratio), and then grab the image dimensions

image = cv2.imread(args["image"])

image = imutils.resize(image, width=600)

(h, w) = image.shape[:2]

 

# construct a blob from the image

imageBlob = cv2.dnn.blobFromImage(

cv2.resize(image, (300, 300)), 1.0, (300, 300),

(104.0, 177.0, 123.0), swapRB=False, crop=False)

 

# apply OpenCV's deep learning-based face detector to localize

# faces in the input image

detector.setInput(imageBlob)

detections = detector.forward()

在这里,我们:

  • 将图像加载到内存中并构造一个blob(第42-49行)。了解  cv2 dnn   这里是blobFromImage
  • 通过我们的探测器定位图像中的面   (第53和54行)。

鉴于我们的新 检测  ,让我们识别图像中的面孔。但首先我们需要过滤弱 检测   并提取 面部   投资回报率:

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

# 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

if confidence > args["confidence"]:

# compute the (x, y)-coordinates of the bounding box for the

# face

box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])

(startX, startY, endX, endY) = box.astype("int")

 

# extract the face ROI

face = image[startY:endY, startX:endX]

(fH, fW) = face.shape[:2]

 

# ensure the face width and height are sufficiently large

if fW < 20 or fH < 20:

continue

将从步骤#1中识别出此块  。我将在此再解释一下:

  • 我们遍历所有的 检测   在  57号线和提取 信心   每对  60号线
  • 然后我们将置信度   与命令行args   字典中包含的最小概率检测阈值 进行比较 ,确保计算出的概率大于最小概率(第63行)。
  • 从那里,我们提取 面部   ROI(第66-70行)以及确保其空间尺寸足够大(第74和75行)。

 

4)识别面部   ROI 的名称 只需几个步骤:

77

78

79

80

81

82

83

84

85

86

87

88

89

# construct a blob for the face ROI, then pass the blob

# through our face embedding model to obtain the 128-d

# quantification of the face

faceBlob = cv2.dnn.blobFromImage(face, 1.0 / 255, (96, 96),

(0, 0, 0), swapRB=True, crop=False)

embedder.setInput(faceBlob)

vec = embedder.forward()

 

# perform classification to recognize the face

preds = recognizer.predict_proba(vec)[0]

j = np.argmax(preds)

proba = preds[j]

name = le.classes_[j]

首先,我们构造一个faceBlob   (来自 面部   ROI)并将其传递 给 嵌入   以生成描述面部的128-D向量(第80-83行

然后,我们  通过我们的SVM识别器模型(第86行)传递 vec,其结果是我们对面对ROI的的预测  。

我们采用最高概率指数(第87行)并查询我们的标签编码器以找到 名称   (第89行)。在两者之间,我在第88行提取概率  。

注意: 你可以通过对概率应用额外的阈值测试来进一步滤除弱脸识别。例如,如果proba T   (其中 T   是你定义的变量),则插入 可以提供额外的过滤层,以确保较少的假阳性面部识别。

 

5)现在,让我们显示OpenCV人脸识别结果:

91

92

93

94

95

96

97

98

99

100

101

102

# draw the bounding box of the face along with the associated

# probability

text = "{}: {:.2f}%".format(name, proba * 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("Image", image)

cv2.waitKey(0)

对于我们在循环中识别的每个面孔(包括“未知”)人:

  • 我们  在第93行构造一个  包含名称和概率的 文本字符串 。
  • 然后我们在脸部周围画一个矩形并将文本放在盒子上方(第94-98行)。

然后我们最终在屏幕上显示结果,直到按下一个键(第101和102行)。

是时候使用OpenCV识别图像中的面部了!

效果:

解释:这里识别了两个用户,一个是我朋友:zhuohua;一个是我自己:pu

之前采集了几个朋友的脸部的图片进行训练,其中包括zhuohua,在识别会识别出来的;

源代码:

# python recognize.py --detector face_detection_model --embedding-model openface_nn4.small2.v1.t7 --recognizer output/recognizer.pickle  --le output/le.pickle --image images/pu.jpg

# import the necessary packages
import numpy as np
import argparse
import imutils
import pickle
import cv2
import os
import time

# 构造参数解析器并解析参数
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True,
	help="path to input image")
ap.add_argument("-d", "--detector", required=True,
	help="path to OpenCV's deep learning face detector")
ap.add_argument("-m", "--embedding-model", required=True,
	help="path to OpenCV's deep learning face embedding model")
ap.add_argument("-r", "--recognizer", required=True,
	help="path to model trained to recognize faces")
ap.add_argument("-l", "--le", required=True,
	help="path to label encoder")
ap.add_argument("-c", "--confidence", type=float, default=0.5,
	help="minimum probability to filter weak detections")
args = vars(ap.parse_args())

# 从磁盘加载我们的序列化面部检测器
print("[INFO] loading face detector...")
protoPath = os.path.sep.join([args["detector"], "deploy.prototxt"])
modelPath = os.path.sep.join([args["detector"],
	"res10_300x300_ssd_iter_140000.caffemodel"])
detector = cv2.dnn.readNetFromCaffe(protoPath, modelPath)

# 从磁盘加载我们的序列化面嵌入模型
print("[INFO] loading face recognizer...")
embedder = cv2.dnn.readNetFromTorch(args["embedding_model"])

# 加载实际的人脸识别模型和标签编码器
recognizer = pickle.loads(open(args["recognizer"], "rb").read())
le = pickle.loads(open(args["le"], "rb").read())

# 加载图像,将其大小调整为宽度为600像素(同时保持纵横比),然后抓取图像尺寸
image = cv2.imread(args["image"])
image = imutils.resize(image, width=600)
(h, w) = image.shape[:2]

# 从图像构造一个blob
imageBlob = cv2.dnn.blobFromImage(
	cv2.resize(image, (300, 300)), 1.0, (300, 300),
	(104.0, 177.0, 123.0), swapRB=False, crop=False)

#应用OpenCV的基于深度学习的人脸检测器来定位输入图像中的人脸
detector.setInput(imageBlob)
detections = detector.forward()

# loop over the detections
for i in range(0, detections.shape[2]):
	# 提取与预测相关的置信度(即概率)
	confidence = detections[0, 0, i, 2]

	# 过滤弱检测
	if confidence > args["confidence"]:
		# 计算面部边界框的(x,y)坐标
		box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
		(startX, startY, endX, endY) = box.astype("int")

		# 提取面部投资回报率
		face = image[startY:endY, startX:endX]
		(fH, fW) = face.shape[:2]

		# 确保面部宽度和高度足够大
		if fW < 20 or fH < 20:
			continue

		#为面部ROI构造一个blob,然后通过我们的面部嵌入模型传递blob以获得面部的128-d量化
		faceBlob = cv2.dnn.blobFromImage(face, 1.0 / 255, (96, 96),
			(0, 0, 0), swapRB=True, crop=False)
		embedder.setInput(faceBlob)
		vec = embedder.forward()

		# 执行分类以识别面部
		preds = recognizer.predict_proba(vec)[0]
		j = np.argmax(preds)
		proba = preds[j]
		name = le.classes_[j]

		# 绘制面部的边界框以及相关的概率
		text = "{}: {:.2f}%".format(name, proba * 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)

# 显示输出图像
cv2.imshow("Image", image)
cv2.waitKey(0)

在命令行终端执行命令,来执行此程序:

python recognize.py --detector face_detection_model --embedding-model openface_nn4.small2.v1.t7 --recognizer output/recognizer.pickle  --le output/le.pickle --image images/pu.jpg

希望对你有帮助。

猜你喜欢

转载自blog.csdn.net/qq_41204464/article/details/100832457