如何使用DeepFace提取图像embedding向量,替换人脸识别项目的ResNet-34
人脸识别特征提取模块替换实现方案(DeepFace/VGGFace版)
前置准备
首先安装依赖库:
pip install deepface opencv-python imutils face-recognition pickle-mixin
说明:DeepFace内置VGGFace、Facenet等多种预训练人脸识别模型,无需手动实现网络结构,首次运行会自动下载对应权重文件。
一、encoding.py脚本修改
仅替换特征提取逻辑,剩余参数解析、遍历数据集、人脸检测、序列化保存逻辑完全不变,修改后代码如下:
from imutils import paths import face_recognition import argparse import pickle import cv2 import os # 新增导入DeepFace from deepface import DeepFace import numpy as np # construct the argument parser and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-i", "--dataset", required=True, help="path to input directory of faces + images") ap.add_argument("-e", "--encodings", required=True, help="path to serialized db of facial encodings") ap.add_argument("-d", "--detection-method", type=str, default="cnn", help="face detection model to use: either `hog` or `cnn`") args = vars(ap.parse_args()) # grab the paths to the input images in our dataset print("[INFO] quantifying faces...") imagePaths = list(paths.list_images(args["dataset"])) # initialize the list of known encodings and known names knownEncodings = [] knownNames = [] # loop over the image paths for (i, imagePath) in enumerate(imagePaths): # extract the person name from the image path print("[INFO] processing image {}/{}".format(i + 1, len(imagePaths))) name = imagePath.split(os.path.sep)[-2] # load the input image and convert it from BGR (OpenCV ordering) # to dlib ordering (RGB) image = cv2.imread(imagePath) rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # detect the (x, y)-coordinates of the bounding boxes # corresponding to each face in the input image boxes = face_recognition.face_locations(rgb, model=args["detection_method"]) # --------------------------修改部分开始-------------------------- # 替换原有ResNet34特征提取为VGGFace特征提取 encodings = [] for box in boxes: top, right, bottom, left = box # 裁剪出人脸区域 face_crop = rgb[top:bottom, left:right] # 提取VGGFace特征,enforce_detection设为False跳过二次人脸检测 embedding = DeepFace.represent( img_path=face_crop, model_name="VGG-Face", # 可替换为"Facenet"得到128维特征,适配原有阈值 enforce_detection=False )[0]["embedding"] encodings.append(np.array(embedding)) # --------------------------修改部分结束-------------------------- # loop over the encodings for encoding in encodings: # add each encoding + name to our set of known names and # encodings knownEncodings.append(encoding) knownNames.append(name) # dump the facial encodings + names to disk print("[INFO] serializing encodings...") data = {"encodings": knownEncodings, "names": knownNames} f = open(args["encodings"], "wb") f.write(pickle.dumps(data)) f.close()
二、预测脚本修改
同样仅替换特征提取逻辑,剩余加载编码、人脸检测、比对、绘图逻辑完全不变,修改后代码如下:
# import the necessary packages import face_recognition import argparse import pickle import cv2 # 新增导入DeepFace from deepface import DeepFace import numpy as np # construct the argument parser and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-e", "--encodings", required=True, help="path to serialized db of facial encodings") ap.add_argument("-i", "--image", required=True, help="path to input image") ap.add_argument("-d", "--detection-method", type=str, default="hog", help="face detection model to use: either `hog` or `cnn`") args = vars(ap.parse_args()) # load the known faces and embeddings print("[INFO] loading encodings...") data = pickle.loads(open(args["encodings"], "rb").read()) # load the input image and convert it from BGR to RGB image = cv2.imread(args["image"]) rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # detect the (x, y)-coordinates of the bounding boxes corresponding # to each face in the input image, then compute the facial embeddings # for each face print("[INFO] recognizing faces...") boxes = face_recognition.face_locations(rgb, model=args["detection_method"]) # --------------------------修改部分开始-------------------------- # 替换原有ResNet34特征提取为VGGFace特征提取 encodings = [] for box in boxes: top, right, bottom, left = box face_crop = rgb[top:bottom, left:right] embedding = DeepFace.represent( img_path=face_crop, model_name="VGG-Face", # 要和encoding.py用的模型名称完全一致 enforce_detection=False )[0]["embedding"] encodings.append(np.array(embedding)) # --------------------------修改部分结束-------------------------- # initialize the list of names for each face detected names = [] # loop over the facial embeddings for encoding in encodings: # attempt to match each face in the input image to our known # encodings matches = face_recognition.compare_faces(data["encodings"], encoding, tolerance=0.7) # VGGFace可适当调大阈值,Facenet用默认0.6即可 name = "Unknown" # check to see if we have found a match if True in matches: # find the indexes of all matched faces then initialize a # dictionary to count the total number of times each face # was matched matchedIdxs = [i for (i, b) in enumerate(matches) if b] counts = {} # loop over the matched indexes and maintain a count for # each recognized face face for i in matchedIdxs: name = data["names"][i] counts[name] = counts.get(name, 0) + 1 # determine the recognized face with the largest number of # votes (note: in the event of an unlikely tie Python will # select first entry in the dictionary) name = max(counts, key=counts.get) # update the list of names names.append(name) print(names) # loop over the recognized faces for ((top, right, bottom, left), name) in zip(boxes, names): # draw the predicted face name on the image cv2.rectangle(image, (left, top), (right, bottom), (0, 255, 0), 2) y = top - 15 if top - 15 > 15 else top + 15 cv2.putText(image, name, (left, y), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 2) # show the output image cv2.imshow("Image", image) cv2.waitKey(0)
注意事项
- 两个脚本的
model_name参数必须完全一致,否则特征空间不匹配会导致识别完全失效 - 若希望保持原有128维特征维度,可将
model_name改为Facenet,此时tolerance参数保持默认0.6即可 - 首次运行会自动下载对应预训练权重,存储在本地用户目录下的.deepface文件夹中,无需手动处理
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

