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

OpenCV LBPH人脸识别train函数参数错误(-5)排查求助

OpenCV人脸识别训练报错排查与修复

问题描述

开发人脸识别项目时,反复触发OpenCV训练函数报错:

OpenCV(4.7.0) :-1: error: (-5:Bad argument) in function 'train'
重载解析失败:

  • Can't parse 'src'. Sequence item with index 0 has a wrong type
  • Can't parse 'src'. Sequence item with index 0 has a wrong type

附上完整代码:

#import OpenCV module
import cv2
#import os module for reading training data directories and paths
import os
import sys
from google.colab.patches import cv2_imshow
import numpy as np

def face_detect(img):
    #image = cv2.imread(imagePath)
    #convert the test image to gray image as opencv face detector expects gray images
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # HaarCascade file, to detect the face.
    faceCascade = cv2.CascadeClassifier("/content/haarcascade_frontalface_alt.xml")
    grays = []
    faces = faceCascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5)

    #if no faces are detected then return original img
    if(len(faces) == 0):
        return None, None
    
    # For drawing rectangles over multiple faces in the image
    #for (x, y, w, h) in faces:
        #cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)
    
    # Show Detected faces.
    #cv2_imshow(image)
    #cv2.waitKey(1)
    
    # Append the detected faces into grays list.
    for i in range(0, len(faces)):
        (x, y, w, h) = faces[i]
        grays.append(gray[y:y+w, x:x+h])
    print("------------------------------------------------------------")
    print("Detecting Face -\-")
    return grays, faces

def training_data(data_folder_path):
    dirs = os.listdir(data_folder_path)
    #list to hold all subject faces
    faces = []
    #list to hold labels for all subjects
    labels = []
    for dir_name in dirs:
        if not dir_name.startswith("s"):
            continue;
        label = int(dir_name.replace("s", ""))
        subject_dir_path = data_folder_path + "/" + dir_name
        subject_images_names = os.listdir(subject_dir_path)
        for image_name in subject_images_names:
            if image_name.startswith("."):
                continue;
            image_path = subject_dir_path + "/" + image_name
            #read image
            image = cv2.imread(image_path)
            # Show Detected faces.
            cv2_imshow(image)
            cv2.waitKey(100)
            face, rect = face_detect(image)
            if face is not None:
                faces.append(face)
                labels.append(label)
    cv2.destroyAllWindows()
    cv2.waitKey(1)
    cv2.destroyAllWindows()    
    return faces, labels

#let's first prepare our training data
#data will be in two lists of same size
#one list will contain all the faces
#and other list will contain respective labels for each face
faces, labels = training_data("/content/training-data")
#print total faces and labels
print("Total faces: ", len(faces))
print("Total labels: ", len(labels))
#create our LBPH face recognizer 
face_recognizer = cv2.face.LBPHFaceRecognizer_create()
#train our face recognizer of our training faces
face_recognizer.train(faces, np.array(labels))

def draw_rectangle(img, rect):
    (x, y, w, h) = rect
    cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)

label = ["", "Pei Han", "Tan"]
def predict(test_img):
    img = test_img.copy()
    print("\n")
    print("Face Prediction Running -\-")
    face, rect = face_detect(img)
    print(len(face), "faces detected.")
    for i in range(0, len(face)):
        labeltemp = face_recognizer.predict(face[i])
        label_text = label[labeltemp]
        draw_rectangle(img, rect)
        cv2.putText(img, str(label_text), (i), cv2.FONT_HERSHEY_PLAIN, 1.5, (0, 255, 0), 2)
    return img

# Read the test image.
test_img = "/content/test-data/test.jpg"
predicted_img = predict(test_img)
#cv2.imshow(label[1], predicted_img)
cv2_imshow(predicted_img)
cv2.waitKey(1)
cv2.destroyAllWindows()
print("Recognized faces = "), label

问题根源分析

报错核心是face_recognizer.train()接收的训练数据格式不符合要求,具体问题有3处:

  • 训练数据嵌套列表:face_detect()返回的是多个人脸的列表,training_data()直接将该列表追加到总列表中,导致faces变成嵌套结构,但OpenCV要求输入一维的人脸矩阵列表
  • 人脸裁剪坐标错误:gray[y:y+w, x:x+h]混淆了宽度和高度的取值范围,正确的裁剪应该是gray[y:y+h, x:x+w]
  • 预测函数参数错误:predict()接收的是图像路径字符串,却直接当作图像矩阵处理,导致后续人脸检测失败

修复后的完整代码

#import OpenCV module
import cv2
#import os module for reading training data directories and paths
import os
import sys
from google.colab.patches import cv2_imshow
import numpy as np

def face_detect(img):
    #convert the test image to gray image as opencv face detector expects gray images
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # HaarCascade file, to detect the face.
    faceCascade = cv2.CascadeClassifier("/content/haarcascade_frontalface_alt.xml")
    grays = []
    faces = faceCascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5)

    #if no faces are detected then return original img
    if(len(faces) == 0):
        return None, None
    
    # Append the detected faces into grays list.
    for (x, y, w, h) in faces:
        # 修复裁剪坐标:y到y+h(高度),x到x+w(宽度)
        grays.append(gray[y:y+h, x:x+w])
    print("------------------------------------------------------------")
    print("Detecting Face -\-")
    return grays, faces

def training_data(data_folder_path):
    dirs = os.listdir(data_folder_path)
    #list to hold all subject faces
    faces = []
    #list to hold labels for all subjects
    labels = []
    for dir_name in dirs:
        if not dir_name.startswith("s"):
            continue;
        label = int(dir_name.replace("s", ""))
        subject_dir_path = data_folder_path + "/" + dir_name
        subject_images_names = os.listdir(subject_dir_path)
        for image_name in subject_images_names:
            if image_name.startswith("."):
                continue;
            image_path = subject_dir_path + "/" + image_name
            #read image
            image = cv2.imread(image_path)
            if image is None:
                print(f"无法读取图像: {image_path}")
                continue
            # Show Detected faces.
            cv2_imshow(image)
            cv2.waitKey(100)
            face_list, rect_list = face_detect(image)
            if face_list is not None:
                # 修复嵌套列表:将单个人脸逐个追加到总列表
                for face in face_list:
                    faces.append(face)
                    labels.append(label)
    cv2.destroyAllWindows()
    cv2.waitKey(1)
    cv2.destroyAllWindows()    
    return faces, labels

#let's first prepare our training data
faces, labels = training_data("/content/training-data")
#print total faces and labels
print("Total faces: ", len(faces))
print("Total labels: ", len(labels))
#create our LBPH face recognizer 
face_recognizer = cv2.face.LBPHFaceRecognizer_create()
#train our face recognizer of our training faces
face_recognizer.train(faces, np.array(labels))

def draw_rectangle(img, rect):
    (x, y, w, h) = rect
    cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)

label = ["", "Pei Han", "Tan"]
def predict(test_img_path):
    # 修复参数错误:先读取路径为图像矩阵
    img = cv2.imread(test_img_path).copy()
    print("\n")
    print("Face Prediction Running -\-")
    face_list, rect_list = face_detect(img)
    if face_list is None:
        print("未检测到人脸")
        return img
    print(len(face_list), "faces detected.")
    for i in range(len(face_list)):
        # 修复predict返回值处理:取标签ID(元组第一个元素)
        label_idx, confidence = face_recognizer.predict(face_list[i])
        label_text = label[label_idx]
        draw_rectangle(img, rect_list[i])
        # 调整文本位置到人脸上方
        cv2.putText(img, label_text, (rect_list[i][0], rect_list[i][1]-10), cv2.FONT_HERSHEY_PLAIN, 1.5, (0, 255, 0), 2)
    return img

# Read the test image.
test_img_path = "/content/test-data/test.jpg"
predicted_img = predict(test_img_path)
cv2_imshow(predicted_img)
cv2.waitKey(1)
cv2.destroyAllWindows()
print("Recognized faces = ", label)

额外优化说明

  • 添加图像读取失败判断,避免损坏图像导致后续报错
  • 修复predict()中标签取值逻辑:face_recognizer.predict()返回元组(标签ID, 置信度),需取第一个元素作为索引
  • 调整预测文本绘制位置,避免出现在图像左上角,改为对应人脸上方

内容的提问来源于stack exchange,提问作者Jin En Ng

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 23:13:09