基于SVM与LBPH的人脸识别模型测试遇(-215断言失败)报错求助
问题:SVM预测时触发Assertion failed错误
处理Test/image1.png时出现如下报错:
An error occurred while processing image Test/image1.png: OpenCV(4.8.0) D:\a\opencv-python\opencv-python\opencv\modules\ml\src\svm.cpp:2013: error: (-215:Assertion failed) samples.cols == var_count && samples.type() == CV_32F in function 'cv::ml::SVMImpl::predict'
相关代码
文件:svmLBPH.py
import cv2 import numpy as np from skimage.feature import local_binary_pattern class LBPH_SVM_Recognizer(): def __init__(self, max_iter= 100, epsilon = 0.001, C= 100, Gamma = 0.001) : self.svm = cv2.ml.SVM_create() self.svm.setKernel(cv2.ml.SVM_CHI2) self.svm.setType(cv2.ml.SVM_C_SVC) self.svm.setTermCriteria((cv2.TERM_CRITERIA_MAX_ITER, max_iter, epsilon)) self.svm.setC(C) self.svm.setGamma(Gamma) self.face_histogram = [] self.y = [] def find_lbp_histogram(self, image, P=8, R=1, eps=1e-7, n_window=(8,8)): E = [] h, w = image.shape h_sz = int(np.floor(h/n_window[0])) w_sz = int(np.floor(w/n_window[1])) lbp_img = local_binary_pattern(image, P=P, R=R, method="default") for (x, y, C) in self.sliding_window(lbp_img, stride=(h_sz, w_sz), window=(h_sz, w_sz)): if C.shape[0] != h_sz or C.shape[1] != w_sz: continue H = np.histogram(C, bins=2**P, range=(0, 2**P), density=True)[0] E.extend(H) return E def sliding_window(self, image, stride, window): for y in range(0, image.shape[0], stride[0]): for x in range(0, image.shape[1], stride[1]): yield (x, y, image[y:y + window[1], x:x + window[0]]) def train(self, x, y): self.y = y # Convert histogram matrix into feature vectors self.face_histograms = [self.find_lbp_histogram(img) for img in x] hist_mat = np.array(self.face_histograms, dtype=np.float32) hist_mat = hist_mat.reshape(len(hist_mat), -1) # Merubah matriks histogram menjadi satu baris self.svm.train(hist_mat, cv2.ml.ROW_SAMPLE, y) def predict(self, x): hists = [self.find_lbp_histogram(img) for img in x] hist_mat = np.array(hists, dtype=np.float32) ret, idx = self.svm.predict(hist_mat, True) confidence = 1.0 / (1.0 + np.exp(-ret)) # convert retVal to confidence level (0-1) sigmoid return idx, confidence
文件:trainModelSVMLBPH.ipynb
# Load your trained LBPH_SVM model lbph_svm_model = LBPH_SVM_Recognizer() lbph_svm_model.svm.load("../ServerTeleBot/lbph_svm_model_v1.yml") # Initialize the face cascade classifier face_cascade = cv2.CascadeClassifier('haarcascades/haarcascade_frontalface_default.xml') # Directory containing test images direktori_test = "Test/" # Loop through all .png files in the test directory for filename in os.listdir(direktori_test): if filename.endswith(".png"): gambar_path = os.path.join(direktori_test, filename) try: # Load the test image frame = cv2.imread(gambar_path) if frame is not None: gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) gray = gray.astype(np.uint8) # Convert to uint8 type lbp_img = local_binary_pattern(gray, P=8, R=1, method="default") faces = face_cascade.detectMultiScale(gray, 1.1, 5) for (x, y, w, h) in faces: face_img = gray[y:y+h, x:x+w] face_img = cv2.resize(face_img, (100, 100)) # Ensure that the data type is CV_32F and reshape as needed hist = face_img.ravel() hist = np.float32(hist).reshape(1, -1) # Perform the prediction using your trained LBPH_SVM model idx, confidence = lbph_svm_model.predict([hist]) # Convert the predicted index to a label label_kelas = labels[int(idx[0])] # Display the test image with predicted class and confidence plt.imshow(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)) plt.title(f"Predicted Class: {label_kelas}, Confidence: {confidence[0]:.2f}") plt.axis('off') plt.show() else: print("Failed to load the test image:", gambar_path) except Exception as e: print(f"An error occurred while processing image {gambar_path}: {str(e)}") cv2.destroyAllWindows()
问题原因
这个断言错误的核心是预测时输入的特征向量维度与训练时不匹配:
- 训练阶段,
train方法传入原始灰度图像,通过find_lbp_histogram提取LBPH分块直方图作为特征,特征长度由分块数和LBPH bins数决定(此处为8×8块 × 2^8 bins = 1280维)。 - 测试阶段,错误地将
face_img.ravel()后的像素数组(100×100=10000维)传入predict方法,而predict内部会对这个1D数组再次调用find_lbp_histogram。此时1D数组会被当成高为10000、宽为1的“图像”,计算出的分块直方图维度和训练时完全不同,导致SVM预测时特征维度不匹配,触发断言错误。 - 仅image1.png报错,是因为这张图的人脸检测结果经过resize后,传入的1D数组在
find_lbp_histogram中生成的特征长度恰好触发了断言,其他图可能因巧合未触发,但本质都是错误的输入方式。
解决方案
1. 修正测试代码的输入逻辑
直接将resize后的2D灰度人脸图像传入predict,让模型内部正确提取LBPH特征,替换测试代码中以下部分:
# 原错误代码 hist = face_img.ravel() hist = np.float32(hist).reshape(1, -1) idx, confidence = lbph_svm_model.predict([hist]) # 修改为 idx, confidence = lbph_svm_model.predict([face_img])
2. 添加鲁棒性检查(可选)
- 在
LBPH_SVM_Recognizer的find_lbp_histogram方法开头添加输入维度检查,避免传入非2D图像:
def find_lbp_histogram(self, image, P=8, R=1, eps=1e-7, n_window=(8,8)): # 确保输入为2D灰度图像 if len(image.shape) != 2: raise ValueError("Input must be a 2D grayscale image") E = [] # 后续代码不变
- 在测试代码中添加人脸检测为空的处理:
faces = face_cascade.detectMultiScale(gray, 1.1, 5) if not len(faces): print(f"No faces detected in {gambar_path}") continue for (x, y, w, h) in faces: # 后续代码不变
内容的提问来源于stack exchange,提问作者mitahu developer
相关产品推荐
相关产品推荐

