LBPH人脸识别predict()误判所有用户为本人的技术求助
人脸识别系统误识别问题
我的人脸识别系统接近完成时,发现cv2.face.LBPHFaceRecognizer_create().predict()方法把所有用户(包括埃隆·马斯克的人脸)都识别成我的名字Tahsin,正确结果应该是Unknown。
相关代码与配置
Face Recognizer.py
import json import cv2 import numpy as np import datetime import winsound print("请按ESC关闭窗口!") recognizer = cv2.face.LBPHFaceRecognizer_create() recognizer.read('Trainer/trainer.yml') cascadePath = "haarcascade_frontalface_default.xml" faceCascade = cv2.CascadeClassifier(cascadePath) font = cv2.FONT_HERSHEY_SIMPLEX id = 2 with open('index.json', 'r') as f: db = json.load(f) names = db['faces'].copy() cam = cv2.VideoCapture(0, cv2.CAP_DSHOW) cam.set(3, 640) cam.set(4, 480) minW = 0.1 * cam.get(3) minH = 0.1 * cam.get(4) while True: ret, img = cam.read() converted_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = faceCascade.detectMultiScale( converted_image, scaleFactor=1.2, minNeighbors=5, minSize=(int(minW), int(minH)), ) for (x, y, w, h) in faces: id, accuracy = recognizer.predict(converted_image[y:y + h, x:x + w]) # LBPH的accuracy是距离值,越小越相似,调整合理阈值 if (accuracy < 80): id = names[str(id)] cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) else: id = "Unknown" cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) if cv2.imwrite(f"Unknowns/{str(datetime.datetime.now().strftime('%Y-%m-%d-%X')).replace(':', '_')}.jpg", img): print("图片已保存!") winsound.Beep(2000, 500) cv2.putText(img, str(id), (x + 5, y - 5), font, 1, (255, 255, 255), 2) cv2.imshow('人脸检测', img) k = cv2.waitKey(10) & 0xff if k == 27: break cam.release() cv2.destroyAllWindows()
index.json
{ "faces": { "1": "Tahsin" } }
人脸样本采集与训练代码
import json import cv2 import numpy as np from PIL import Image import os cam = cv2.VideoCapture(0, cv2.CAP_DSHOW) cam.set(3, 640) cam.set(4, 480) detector = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') face_id = input("请输入数字用户ID: ") face_name = input("请输入姓名: ") print("正在采集样本,请看向镜头... ") count = 0 while True: ret, img = cam.read() converted_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = detector.detectMultiScale(converted_image, 1.3, 5) for (x, y, w, h) in faces: cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) count += 1 cv2.imwrite("samples/face." + str(face_id) + '.' + str(count) + ".jpg", converted_image[y:y + h, x:x + w]) k = cv2.waitKey(100) & 0xff if k == 27: break elif count >= 50: break cv2.imshow('image', img) with open('index.json', 'r') as f: db = json.load(f) if 'faces' in db: db['faces'][face_id] = face_name else: db['faces'] = {} db['faces'][face_id] = face_name with open('index.json', 'w') as f: json.dump(db, f, indent=4) print("样本采集完成!") cam.release() cv2.destroyAllWindows() path = 'samples' recognizer = cv2.face.LBPHFaceRecognizer_create() detector = cv2.CascadeClassifier("haarcascade_frontalface_default.xml") def Images_And_Labels(path): # 遍历所有样本图片,而非仅当前face_id的图片 imagePaths = [os.path.join(path, f) for f in os.listdir(path) if f.endswith('.jpg')] faceSamples = [] ids = [] for imagePath in imagePaths: gray_img = Image.open(imagePath).convert('L') img_arr = np.array(gray_img, 'uint8') id = int(os.path.split(imagePath)[-1].split(".")[1]) faces = detector.detectMultiScale(img_arr) for (x, y, w, h) in faces: faceSamples.append(img_arr[y:y + h, x:x + w]) ids.append(id) return faceSamples, ids print("正在训练人脸模型,需要几秒时间,请稍等...") faces, ids = Images_And_Labels(path) recognizer.train(faces, np.array(ids)) recognizer.write('trainer/trainer.yml') print("模型训练完成,可以进行人脸识别了。")
现象示例
埃隆·马斯克的人脸被错误识别为Tahsin(正确应为Unknown):
问题原因与修复方案
核心问题1:训练逻辑错误
原训练代码的Images_And_Labels函数仅读取当前输入face_id对应的样本,导致模型只学习了单个人的特征。遇到陌生人脸时,模型只能匹配唯一的已知类别,从而产生误识别。
修复方式:
修改样本读取逻辑,遍历所有样本图片:
# 原错误代码 imagePaths = [os.path.join(path, f) if f.split('.')[1] == face_id else None for f in os.listdir(path)] # 修复后代码 imagePaths = [os.path.join(path, f) for f in os.listdir(path) if f.endswith('.jpg')]
核心问题2:阈值判断逻辑错误
LBPH识别器的predict方法返回的accuracy是距离值,值越小表示人脸越相似(0为完全匹配)。原代码设置accuracy < 100就判定匹配,阈值过高导致几乎所有人脸都会被识别为已知用户。
修复方式:
将阈值调整为合理范围(建议50-80,可根据样本质量微调):
# 原错误代码 if (accuracy < 100): # 修复后代码 if (accuracy < 80):
其他次要问题修复
- 原识别代码遗漏
datetime和winsound模块导入,需补充以保证保存图片和蜂鸣功能正常运行; - 简化
names字典的生成逻辑,去除冗余循环。
内容的提问来源于stack exchange,提问作者Tahsin
相关产品推荐
相关产品推荐

