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

基于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()

问题原因

这个断言错误的核心是预测时输入的特征向量维度与训练时不匹配:

  1. 训练阶段,train方法传入原始灰度图像,通过find_lbp_histogram提取LBPH分块直方图作为特征,特征长度由分块数和LBPH bins数决定(此处为8×8块 × 2^8 bins = 1280维)。
  2. 测试阶段,错误地将face_img.ravel()后的像素数组(100×100=10000维)传入predict方法,而predict内部会对这个1D数组再次调用find_lbp_histogram。此时1D数组会被当成高为10000、宽为1的“图像”,计算出的分块直方图维度和训练时完全不同,导致SVM预测时特征维度不匹配,触发断言错误。
  3. 仅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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 05:48:13