You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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):

其他次要问题修复

  1. 原识别代码遗漏datetime和winsound模块导入,需补充以保证保存图片和蜂鸣功能正常运行;
  2. 简化names字典的生成逻辑,去除冗余循环。

内容的提问来源于stack exchange,提问作者Tahsin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 16:15:30