OpenCV kNN训练报错求助:训练数据需为浮点型矩阵
解决OpenCV kNN训练时的"train data must be floating-point matrix"错误
让我们一步步排查和解决你的问题:
1. 核心错误原因
你遇到的cvCheckTrainData错误,本质是因为传入knn.train()的train数据形状不符合要求——OpenCV的kNN期望2维浮点矩阵(样本数 × 单样本特征数),但你当前的train是4维数组(拆分后的行 × 每行单元格数 × 图像高度 × 图像宽度),同时还存在拆分行数错误、标签数量不匹配的问题。
2. 分步修正代码
第一步:修正图像拆分逻辑
你的原图是468x108,每行39个数字、共9行,所以每个数字的原始尺寸是468/39=12px宽,108/9=12px高。经过resize(fx=2, fy=2)后,每个数字变成24x24px,此时应该把灰度图垂直拆分成9行(而非你代码中的12行):
# 修正vsplit的参数为9,对应9行数字 cells = [np.hsplit(row, 39) for row in np.vsplit(gray, 9)]
第二步:将图像数据转换为kNN所需的2维浮点矩阵
拆分后的cells是嵌套列表,转成numpy数组后是(9, 39, 24, 24)的4维结构,我们需要把每个24x24的数字图像展平成1维向量,最终得到351 × 576的矩阵(351=9×39个样本,576=24×24个特征):
x = np.array(cells) # 展平每个数字图像为一维,并转换为float32类型 train = x.reshape(-1, 24*24).astype(np.float32)
第三步:修正训练标签的数量
你的数据集总共有9×39=351个样本,数字1-9每个应该出现39次(而非你代码中的468次),所以标签数组要对应调整:
k = [1,2,3,4,5,6,7,8,9] # 每个数字重复39次,总数量351,和样本数匹配 train_labels = np.repeat(k, 39)[:, np.newaxis]
第四步:验证数据形状(可选但推荐)
在训练前可以打印形状,确保符合要求:
print("Train data shape:", train.shape) # 预期输出 (351, 576) print("Train labels shape:", train_labels.shape) # 预期输出 (351, 1)
3. 修正后的完整代码
import cv2 import numpy as np image = cv2.imread('images/digits_sudoku4.png') image = cv2.resize(image, None, fx=2, fy=2) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 修正拆分逻辑:9行,每行39个数字 cells = [np.hsplit(row, 39) for row in np.vsplit(gray, 9)] x = np.array(cells) # 转换为kNN需要的2维浮点矩阵 train = x.reshape(-1, 24*24).astype(np.float32) # 生成匹配的训练标签 k = [1,2,3,4,5,6,7,8,9] train_labels = np.repeat(k, 39)[:, np.newaxis] # 初始化并训练kNN knn = cv2.KNearest() knn.train(train, train_labels) cv2.imshow('Sudoku', gray) cv2.waitKey(0) cv2.destroyAllWindows()
额外提示
- 如果你后续要测试模型,测试数据也需要做同样的展平处理,确保特征数和训练数据一致(都是576)。
- 注意OpenCV 2.4的
KNearest是旧版API,如果你后续升级到OpenCV 3+,可以使用cv2.ml.KNearest_create(),API会有一些变化,但核心逻辑是一样的。
内容的提问来源于stack exchange,提问作者Mumbaikar007
相关产品推荐
相关产品推荐

