当我使用内部 mac 摄像头时,方框会正确绘制。但是当我使用网络摄像头时,这些框会从脸部绘制移位。
import os
import sys
import glob
import time
import math
import cv2
import numpy as np
from tqdm import tqdm
COSINE_THRESHOLD = 0.5
def match(recognizer, feature1, dictionary):
max_score = 0.0
sim_user_id = ""
for user_id, feature2 in zip(dictionary.keys(), dictionary.values()):
score = recognizer.match(
feature1, feature2, cv2.FaceRecognizerSF_FR_COSINE)
if score >= max_score:
max_score = score
sim_user_id = user_id
if max_score < COSINE_THRESHOLD:
return False, ("", 0.0)
return True, (sim_user_id, max_score)
def recognize_face(image, face_detector, face_recognizer, file_name=None):
channels = 1 if len(image.shape) == 2 else image.shape[2]
if channels == 1:
image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
if channels == 4:
image = cv2.cvtColor(image, cv2.COLOR_BGRA2BGR)
if image.shape[0] > 1000:
image = cv2.resize(image, (0, 0),
fx=500 / image.shape[0], fy=500 / image.shape[0])
height, width, _ = image.shape
face_detector.setInputSize((width, height))
try:
dts = time.time()
_, faces = face_detector.detect(image)
if file_name is not None:
assert len(faces) > 0, f'the file {file_name} has no face'
faces = faces if faces is not None else []
features = []
print(f'time detection = {time.time() - dts}')
for face in faces:
rts = time.time()
aligned_face = face_recognizer.alignCrop(image, face)
feat = face_recognizer.feature(aligned_face)
print(f'time recognition = {time.time() - rts}')
features.append(feat)
return features, faces
except Exception as e:
print(e)
print(file_name)
return None, None
def main():
# contain npy for embedings and registration photos
directory = '/Users/triplec/Sites/FRV/SFACEYUNET/'
# Init models face detection & recognition
weights = os.path.join(directory, "models",
"face_detection_yunet_2022mar.onnx")
face_detector = cv2.FaceDetectorYN_create(weights, "", (0, 0))
face_detector.setScoreThreshold(0.87)
weights = os.path.join(directory, "models", "face_recognizer_fast.onnx")
face_recognizer = cv2.FaceRecognizerSF_create(weights, "")
# Get registered photos and return as npy files
# File name = id name, embeddings of a photo is the representative for the id
# If many files have the same name, an average embedding is used
dictionary = {}
# the tuple of file types, please ADD MORE if you want
types = ('*.jpg', '*.png', '*.jpeg', '*.JPG', '*.PNG', '*.JPEG')
files = []
for a_type in types:
files.extend(glob.glob(os.path.join(directory, 'images', a_type)))
files = list(set(files))
for file in tqdm(files):
image = cv2.imread(file)
feats, faces = recognize_face(
image, face_detector, face_recognizer, file)
if faces is None:
continue
user_id = os.path.splitext(os.path.basename(file))[0]
dictionary[user_id] = feats[0]
print(f'there are {len(dictionary)} ids')
capture = cv2.VideoCapture(1)
if not capture.isOpened():
sys.exit()
while True:
start_hand = time.time()
result, image = capture.read()
if result is False:
cv2.waitKey(0)
break
fetures, faces = recognize_face(image, face_detector, face_recognizer)
if faces is None:
continue
for idx, (face, feature) in enumerate(zip(faces, fetures)):
result, user = match(face_recognizer, feature, dictionary)
box = list(map(int, face[:4]))
color = (0, 255, 0) if result else (0, 0, 255)
thickness = 2
cv2.rectangle(image, box, color, thickness, cv2.LINE_AA)
id_name, score = user if result else (f"unknown_{idx}", 0.0)
text = "{0} ({1:.2f})".format(id_name, score)
position = (box[0], box[1] - 10)
font = cv2.FONT_HERSHEY_SIMPLEX
scale = 0.6
cv2.putText(image, text, position, font, scale,
color, thickness, cv2.LINE_AA)
cv2.imshow("face recognition", image)
key = cv2.waitKey(1)
if key == ord('q'):
break
end_hand = time.time()
print(f'speed of a loop = {end_hand - start_hand} means {1/(end_hand - start_hand)} frames per second')
cv2.destroyAllWindows()
if __name__ == '__main__':
main()
本来我使用Opencv 4.6.0.66,尝试更新opencv没有成功解决问题。尝试在网上搜索,但没有
我看了很多帖子,最后决定凭经验定义正确的位移:
for idx, (face, feature) in enumerate(zip(faces, fetures)):
result, user = match(face_recognizer, feature, dictionary)
box = list(map(int, face[:4]))
percentage = 1.2
# Apply the percentage increase to each dimension of the box
box[0] = int(box[0] + box[0] * percentage)
box[2] = int(box[2] + box[2] * percentage)
box[1] = int(box[1] + box[1] * percentage)
box[3] = int(box[3] + box[3] * percentage)
color = (0, 255, 0) if result else (0, 0, 255)
thickness = 2
cv2.rectangle(image, box, color, thickness, cv2.LINE_AA)
这是一个老问题,但对于任何有这个问题的人来说
问题出在这一行
if image.shape[0] > 1000:
image = cv2.resize(image, (0, 0),
fx=500 / image.shape[0], fy=500 / image.shape[0])
这个问题是由于你识别出较小尺寸的图像,但以原始尺寸显示它,你有两种方法,一种方法是重新缩放到较小的尺寸,通过移动(移动,而不是复制)该行,之前
fetures, faces = recognize_face(image, face_detector, face_recognizer)
像这样:
if image.shape[0] > 1000:
image = cv2.resize(image, (0, 0), fx=500 / image.shape[0], fy=500 / image.shape[0])
fetures, faces = recognize_face(image, face_detector, face_recognizer)
另一种方法是在将面部区域(框)放置到原始图像上之前重新缩放和重新定位面部区域,以保持图像的原始质量,在此行之后:
box = list(map(int, face[:4]))
您重新缩放和重新定位的比例是原始尺寸/较小尺寸