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
相关产品推荐
相关产品推荐

