下载arcface_onnx.py,然后执行下面的代码就可以算出两个照片的相似度,进而判断两者是不是同一个人。
加载模型
import os
import os.path as osp
import argparse
import cv2
import numpy as np
import onnxruntime
from scrfd import SCRFD
from arcface_onnx import ArcFaceONNX
onnxruntime.set_default_logger_severity(3)
assets_dir = osp.expanduser('~/.insightface/models/buffalo_l')
detector = SCRFD(os.path.join(assets_dir, 'det_10g.onnx'))
detector.prepare(0)
model_path = os.path.join(assets_dir, 'w600k_r50.onnx')
rec = ArcFaceONNX(model_path)
rec.prepare(0)
加载图片
image1 = cv2.imread('img1.jpg')
image2 = cv2.imread('img2.jpg')
人脸检测
和前面的文章一样,detector
返回的人脸框和五个关键点。
bboxes1, kpss1 = detector.autodetect(image1, max_num=1)
if bboxes1.shape[0]==0:
return -1.0, "Face not found in Image-1"
bboxes2, kpss2 = detector.autodetect(image2, max_num=1)
if bboxes2.shape[0]==0:
return -1.0, "Face not found in Image-2"
获取图片里面人脸照片的特征
kps1 = kpss1[0]
kps2 = kpss2[0]
feat1 = rec.get(image1, kps1)
feat2 = rec.get(image2, kps2)
get
方法做了两件事:
norm_crop
根据人脸的 5 个关键点位进行对齐和拉伸,返回的是(112, 112, 3)的数组get_feat
就是根据新的图片进行推断,获取到一个(512,)的特征数组。在进行推断之前,需要对知道模型对于输入的规范,再将图片按照该规范进行处理cv2.dnn.blobFromImages
。
def get(self, img, kps):
aimg = face_align.norm_crop(img, landmark=kps, image_size=self.input_size[0])
embedding = self.get_feat(aimg).flatten()
return embedding
def norm_crop(img, landmark, image_size=112, mode='arcface'):
M, pose_index = estimate_norm(landmark, image_size, mode)
warped = cv2.warpAffine(img, M, (image_size, image_size), borderValue=0.0)
return warped
def get_feat(self, imgs):
if not isinstance(imgs, list):
imgs = [imgs]
input_size = self.input_size
blob = cv2.dnn.blobFromImages(imgs, 1.0 / self.input_std, input_size,
(self.input_mean, self.input_mean, self.input_mean), swapRB=True)
net_out = self.session.run(self.output_names, {self.input_name: blob})[0]
return net_out
计算相似度
sim = rec.compute_sim(feat1, feat2)
if sim<0.2:
conclu = 'They are NOT the same person'
elif sim>=0.2 and sim<0.28:
conclu = 'They are LIKELY TO be the same person'
else:
conclu = 'They ARE the same person'
print(f"sim: {sim}")
compute_sim
是计算两个特征的余弦相似度,feat1.dot(feat2)
计算两者的点积,np.linalg.norm
是用来计算特征的范数。
def compute_sim(self, feat1, feat2):
sim = feat1.dot(feat2) / (np.linalg.norm(feat1) * np.linalg.norm(feat2))
return sim