摄像头输入手写数字识别:SVC维度错误(数组维度4,要求≤2)求助
问题分析与解决
核心错误原因
- 输入维度不匹配:SVM分类器(SVC)要求输入是2维数组(形状为
(样本数, 特征数)),但你的代码里把处理后的图像reshape成了4维(1,28,28,1),直接触发了Found array with dim 4. SVC expected <=2的错误。 - 训练与预测的图像尺寸不匹配:你用的
digits数据集是8×8的灰度图,每个样本展开为64维特征(digits['data']形状为(1797, 64)),但你把摄像头采集的图像缩成了28×28,即使展开也会是784维,和训练时的特征维度完全不兼容,就算解决维度问题,模型也无法正确预测。
修正步骤
1. 统一图像尺寸与训练数据一致
将摄像头采集的图像缩放到8×8,和digits数据集的图像尺寸匹配。
2. 正确调整输入维度
把处理后的8×8图像展开为1×64的2维数组,符合SVC的输入要求。
3. 修正代码中的其他问题
cap.release()和cv2.destroyAllWindows()放在了while循环内部,会导致摄像头刚启动就被释放,移到循环外。- SVC的
predict()方法直接返回预测的类别标签,不需要用np.argmax()处理。
修正后的完整代码
from sklearn import svm from sklearn import datasets import numpy as np import cv2 from skimage import img_as_ubyte from skimage.color import rgb2gray # 训练SVM模型 svc = svm.SVC(gamma=0.001, C=100.) digits = datasets.load_digits() x = digits['data'] y = digits['target'] svc.fit(x, y) # 摄像头配置 width = 640 height = 480 cameraNo = 0 cap = cv2.VideoCapture(cameraNo) cap.set(3, width) cap.set(4, height) while True: success, img_orig = cap.read() if not success: break # 读取失败时退出循环 # 图像预处理 img_gray = rgb2gray(img_orig) img_gray_u8 = img_as_ubyte(img_gray) (thresh, im_binary) = cv2.threshold(img_gray_u8, 128, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU) # 缩放到8×8,和训练数据尺寸一致 img_resized = cv2.resize(im_binary, (8, 8)) im_gray_invert = 255 - img_resized cv2.imshow("invert image", im_gray_invert) # 调整为SVC要求的输入形状:(1, 64) im_final = im_gray_invert.flatten().reshape(1, -1) # 直接预测,不需要argmax ans = svc.predict(im_final)[0] print(ans) # 在原图上显示预测结果 cv2.putText(img_orig, 'Predicted Digit : ' + str(ans), (50, 50), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 0, 255), 1) cv2.imshow("Original Image", img_orig) # 按q退出 if cv2.waitKey(1) & 0xFF == ord('q'): break # 释放资源,放在循环外 cap.release() cv2.destroyAllWindows()
可选优化:改用MNIST数据集(28×28)
如果你想保留28×28的图像尺寸,可以改用MNIST数据集训练SVM,示例代码如下:
from sklearn import svm from sklearn.datasets import fetch_openml from sklearn.model_selection import train_test_split # 加载MNIST数据集(28×28) mnist = fetch_openml('mnist_784', version=1, cache=True, as_frame=False) x = mnist.data / 255.0 # 归一化 y = mnist.target x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42) # 训练SVM svc = svm.SVC(gamma=0.001, C=100.) svc.fit(x_train, y_train) # 后续摄像头处理部分,只需要把图像缩成28×28,然后展开为1×784即可 # im_final = im_gray_invert.flatten().reshape(1, -1)
内容的提问来源于stack exchange,提问作者william makarius
相关产品推荐
相关产品推荐

