import argparse
import numpy as np
import cv2 as cv
def str2bool(v)
if v.lower() in ['on', 'yes', 'true', 'y', 't']
return True
如果 v.lower() 在 ['off', 'no', 'false', 'n', 'f'] 中:
返回 错误
否则:
提升 NotImplementedError
parser = argparse.ArgumentParser()
parser.add_argument('--image1', '-i1', type=str, help='输入图像 1 的路径。略过即可使用默认摄像头检测。')
parser.add_argument('--image2', '-i2', type=str, help='输入图像 2 的路径。当给出图像 1 和图像 2 的参数时,程序会尝试在两张图像上找到面部并运行面部识别算法。')
parser.add_argument('--video', '-v', type=str, help='输入视频的路径。')
parser.add_argument('--scale', '-sc', type=float, default=1.0, help='用于调整输入视频帧大小的缩放因子。')
parser.add_argument('--face_detection_model', '-fd', type=str, default='face_detection_yunet_2021dec.onnx', help='面部检测模型的路径。可在 https://github.com/opencv/opencv_zoo/tree/master/models/face_detection_yunet 下载该模型')
parser.add_argument('--face_recognition_model', '-fr', type=str, default='face_recognition_sface_2021dec.onnx', help='面部识别模型的路径。可在 https://github.com/opencv/opencv_zoo/tree/master/models/face_recognition_sface 下载该模型')
parser.add_argument('--score_threshold', type=float, default=0.9, help='过滤掉分数 < score_threshold 的面部。')
parser.add_argument('--nms_threshold', type=float, default=0.3, help='抑制 iou >= nms_threshold 的包围框。')
parser.add_argument('--top_k', type=int, default=5000, help='在 NMS 之前保留前 top_k 个包围框。')
parser.add_argument('--save', '-s', type=str2bool, default=错误, help='设置为 true 可保存结果。使用摄像头时,此标记无效。')
args = parser.parse_args()
定义 visualize(input, faces, fps, thickness=2)
如果 faces[1] 不是 空
对于 idx, face 在 enumerate(faces[1])
打印('面部 {}, 左上角坐标: ({:.0f}, {:.0f}), 框宽度: {:.0f}, 框高度 {:.0f}, 分数: {:.2f}'.format(idx, face[0], face[1], face[2], face[3], face[-1]))
coords = face[:-1].astype(np.int32)
cv.rectangle(input, (coords[0], coords[1]), (coords[0]+coords[2], coords[1]+coords[3]), (0, 255, 0), thickness)
cv.circle(input, (coords[4], coords[5]), 2, (255, 0, 0), thickness)
cv.circle(input, (coords[6], coords[7]), 2, (0, 0, 255), thickness)
cv.circle(input, (coords[8], coords[9]), 2, (0, 255, 0), thickness)
cv.circle(input, (coords[10], coords[11]), 2, (255, 0, 255), thickness)
cv.circle(input, (coords[12], coords[13]), 2, (0, 255, 255), thickness)
cv.putText(input,
'FPS: {:.2f}'.format(fps), (1, 16), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
if __name__ == '__main__'
args.face_detection_model,
"",
(320, 320),
args.score_threshold,
args.nms_threshold,
args.top_k
)
if args.image1 is not None
img1Width = int(img1.shape[1]*args.scale)
img1Height = int(img1.shape[0]*args.scale)
img1 =
cv.resize(img1, (img1Width, img1Height))
tm.start()
detector.setInputSize((img1Width, img1Height))
faces1 = detector.detect(img1)
tm.stop()
assert faces1[1] is not None, '无法在 {} 中找到人脸'.format(args.image1)
visualize(img1, faces1, tm.getFPS())
if args.save
print('结果已保存到 result.jpg\n')
if args.image2 is not None
tm.reset()
tm.start()
detector.setInputSize((img2.shape[1], img2.shape[0]))
faces2 = detector.detect(img2)
tm.stop()
断言 faces2[1] 为 非 None, “在 {} 中找不到面部”.format(args.image2)
visualize(img2, faces2, tm.getFPS())
args.face_recognition_model,"")
face1_align = recognizer.alignCrop(img1, faces1[1][0])
face2_align = recognizer.alignCrop(img2, faces2[1][0])
face1_feature = recognizer.feature(face1_align)
face2_feature = recognizer.feature(face2_align)
cosine_similarity_threshold = 0.363
l2_similarity_threshold = 1.128
cosine_score = recognizer.match(face1_feature, face2_feature, cv.FaceRecognizerSF_FR_COSINE)
l2_score = recognizer.match(face1_feature, face2_feature, cv.FaceRecognizerSF_FR_NORM_L2)
msg = '不同的身份'
如果 cosine_score >= cosine_similarity_threshold
msg = '相同身份'
print('他们有 {}。余弦相似度:{},阈值:{}(值越高相似度越高,最大 1.0)。'.format(msg, cosine_score, cosine_similarity_threshold))
msg = '不同的身份'
如果 l2_score <= l2_similarity_threshold
msg = '相同身份'
print('他们有 {}。NormL2 距离:{},阈值:{}(值越低相似度越高,最小 0.0)。'.format(msg, l2_score, l2_similarity_threshold))
否则:
如果 args.video 非 None
deviceId = args.video
否则:
deviceId = 0
frameWidth = int(cap.get(cv.CAP_PROP_FRAME_WIDTH)*args.scale)
frameHeight = int(cap.get(cv.CAP_PROP_FRAME_HEIGHT)*args.scale)
detector.setInputSize([frameWidth, frameHeight])
hasFrame, frame = cap.read()
如果 非 hasFrame
print('未获取帧!')
终止
frame =
cv.resize(frame, (frameWidth, frameHeight))
tm.start()
faces = detector.detect(frame)
tm.stop()
visualize(frame, faces, tm.getFPS())
static Ptr< FaceDetectorYN > create(CV_WRAP_FILE_PATH const String &model, CV_WRAP_FILE_PATH const String &config, const Size &input_size, float score_threshold=0.9f, float nms_threshold=0.3f, int top_k=5000, int backend_id=0, int target_id=0)
使用给定参数创建人脸检测器类的实例。
static Ptr< FaceRecognizerSF > create(CV_WRAP_FILE_PATH const String &model, CV_WRAP_FILE_PATH const String &config, int backend_id=0, int target_id=0)
使用给定的参数创建此类的实例。
cv::String findFile(const cv::String &relative_path, bool required=true, bool silentMode=false)
尝试查找请求的数据文件。
void destroyAllWindows()
销毁所有 HighGUI 窗口。
void rectangle(InputOutputArray img, Point pt1, Point pt2, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)
绘制一个简单的、粗的或填充满的右上正方形。
void putText(InputOutputArray img, const String &text, Point org, int fontFace, double fontScale, Scalar color, int thickness=1, int lineType=LINE_8, bool bottomLeftOrigin=false)
绘制一个文本字符串。
void circle(InputOutputArray img, Point center, int radius, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)
绘制一个圆。