三、提取人脸的面部嵌入(Python)(extract_embeddings.py)

1. 代码部分

此代码块为extract_embeddings.py内的代码

# USAGE
# python extract_embeddings.py --dataset dataset --embeddings output/embeddings.pickle
# \ --detector face_detection_model --embedding-model openface_nn4.small2.v1.t7

# 加载必要的包
from imutils import paths
import numpy as np
import imutils
import pickle
import cv2
import os

def extract_embeddings():
    ## 从磁盘加载序列化人脸检测器(serialized face detector)
    ## 使用OpenCV的基于Caffe的深度学习人脸检测器来定位图像中人脸。
    ## 用途:检测或定位人脸在图像中的位置
    print("[INFO] loading face detector...")
    # 用cv2.dnn.readNetFromCaffe来加载Caffe模型定义prototxt,以及预训练模型。
    protoPath = os.path.sep.join(['face_detection_model', "deploy.prototxt"])
    modelPath = os.path.sep.join(['face_detection_model',
    	"res10_300x300_ssd_iter_140000.caffemodel"])
    detector = cv2.dnn.readNetFromCaffe(protoPath, modelPath)
    
    ## 从磁盘加载序列化面部嵌入模型(serialized face embedding model)
    ## 使用OpenCV的基于Torch的深度学习面部嵌入模型来提取面部嵌入(face embedding)
    ## 用途:用于提取人脸的128维(128-D)面部嵌入
    print("[INFO] loading face recognizer...")
    embedder = cv2.dnn.readNetFromTorch(r'openface_nn4.small2.v1.t7')
    
    ## 获得输入人脸数据库的路径
    # imagePaths列表包含数据集中每个图像的路径。
    # 这个功能是通过imutils包中的函数paths.list_images实现的
    print("[INFO] quantifying faces...")
    imagePaths = list(paths.list_images(r'dataset'))
    
    ## 初始化提取的面部嵌入和相应的人名
    # 我们将把提取的面部嵌入和相应的人名保存在下述两个列表中
    knownEmbeddings = []
    knownNames = []
    
    ## 初始化我们成功处理的人脸的数量
    total = 0
    
    ## 在人脸数据库中循环,这个循环将从每个图像中找到的人脸上提取面部嵌入
    for (i, imagePath) in enumerate(imagePaths):
    	## 从图像路径(人脸数据库)中提取人名
    	print("[INFO] processing image {}/{}".format(i + 1,
    		len(imagePaths)))
        # 通过使用imagePath.split拆分字符
        # 该函数生成一个沿着目录树向下走的文件夹/文件名(字符串)列表
        # 我们获取倒数第二个索引,即人名
        # 示例:
        # >>> imagePaths = list(paths.list_images("dataset"))
        # >>> imagePath = imagePaths[0]
        # >>> imagePath
        # 'dataset/adrian/00004.jpg'
        # >>> imagePath.split(os.path.sep)
        # ['dataset', 'adrian', '00004.jpg']
        # >>> imagePath.split(os.path.sep)[-2]
        # 'adrian'
    	name = imagePath.split(os.path.sep)[-2]
        
        ## 加载图像,将其宽度调整为600像素(同时保持纵横比),并读取图像尺寸
    	image = cv2.imread(imagePath)
    	image = imutils.resize(image, width=600)
        # 读取图像的尺寸
    	(h, w) = image.shape[:2]
    
        ## 应用OpenCV中的基于深度学习的人脸检测器来检测和定位输入图像中的人脸 
    	# 使用cv2.dnn.blobFromImag来对输入图像进行归一化,从而产生一个已知的blob形状。
        # 也即从图像来创建一个blob
        # 此处的知识点参考收藏:Deep learning: How OpenCV’s blobFromImage works
    	imageBlob = cv2.dnn.blobFromImage(
    		cv2.resize(image, (300, 300)), 1.0, (300, 300),
    		(104.0, 177.0, 123.0), swapRB=False, crop=False)
        # 将imageBlob传递到detector神经网络来检测图像中的面部
    	detector.setInput(imageBlob)
        # 以imageBlob为输入,在神经网络中完成一次正向传播,并将分类结果保存至detections
        # 注:我们不是在训练DNN,而是在使用预训练模型,
        #     因此只需要将blob从网络中传递过去,来获取结果,不需要反向传播。
        # detections列表包含图像中的人脸的概率和定位人脸的坐标
        # 注:一张照片可能检测出多张人脸,也就是说可能会有多个识别为人脸的边界框
    	detections = detector.forward()
        
        ## 确保即将处理的图像中包括人脸,如果不包括,则读取下一张图片
    	# 在图像中检测到了至少一个人脸才会进入if语句主体
    	if len(detections) > 0:
            # 本程序假设每个照片中只有一张人脸
            # 因此找到概率最大的边界框
            # 也就是说要提取最高置信度的人脸的面部嵌入
    		i = np.argmax(detections[0, 0, :, 2])
    		confidence = detections[0, 0, i, 2]
            
            ## 确保即将处理的图像中人脸的概率大于一个阈值
            # 设定过滤弱检测的最小概率阈值,若图像的置信度满足该阈值则进行面部嵌入的提取
    		if confidence > 0.5:
                
                ## 计算人脸边界框(the bounding box for the face)的(x,y)坐标
    			box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
    			(startX, startY, endX, endY) = box.astype("int")
    
    			## 提取人脸的感兴趣区域(ROI)并获取感兴趣区域(ROI)的维度(即ROI的宽度和高度)
    			face = image[startY:endY, startX:endX]
    			(fH, fW) = face.shape[:2]
    
    			## 确保提取到的人脸的感兴趣区域(ROI)足够的大
                ## 如果不满足设定值,则不进行后续处理,直接读取下一张图像
    			if fW < 20 or fH < 20:
    				continue
                
                ## 使用OpenCV的基于Torch的深度学习面部嵌入模型来提取面部嵌入
                ## 借此来获得描述人脸的128维(128-D)面部嵌入
                # 这次为人脸的感兴趣区域(ROI)构造一个blob
                # (不同于第73行代码,73行是为整个图像构造blob)
    			faceBlob = cv2.dnn.blobFromImage(face, 1.0 / 255,
    				(96, 96), (0, 0, 0), swapRB=True, crop=False)
                # 将faceBlob传递给面部嵌入模型卷积神经网络(embedder CNN)
    			embedder.setInput(faceBlob)
                # 在神经网络中完成一次正向传播,并将分类结果保存至vec
                # 获得描述人脸的128维(128-D)面部嵌入
                # 注:我们将把这些数据作为人脸识别模型的训练数据
    			vec = embedder.forward()
    
                ## 将人名和相应的面部嵌入添加到各自的列表中
    			knownNames.append(name)
    			knownEmbeddings.append(vec.flatten())
                # 成功处理的人脸数量的总数目加一
    			total += 1
                #之后便是继续循环图像,检测人脸,并为人脸数据集中的每个图像提取面部嵌入
    
    ## 循环结束后将面部嵌入和人名存储到磁盘中
    print("[INFO] serializing {} encodings...".format(total))
    # 将面部嵌入和人名添加到data字典中
    data = {"embeddings": knownEmbeddings, "names": knownNames}
    # 将字典写入embeddings.pickle文件中
    f = open(r'output/embeddings.pickle', "wb")
    f.write(pickle.dumps(data))
    f.close()

## 测试脚本用  
if __name__ == '__main__':
    extract_embeddings()

2. 函数结构说明

在这里插入图片描述

3. 程序流程图

在这里插入图片描述

4. 函数图解

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5. 使用说明

本函数需搭配视频流人脸识别系统一起使用。
视频流人脸识别系统的系统函数见此博客:一、视频流人脸识别系统的系统函数的构建(Python)
文中用到的deploy.prototxt、res10_300x300_ssd_iter_140000.caffemodel、openface_nn4.small2.v1.t7文件在此处下载:人脸识别集成包

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吮指原味张

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值