如何使用基于一组图像的 opencv 训练 SVM?

Posted

技术标签:

【中文标题】如何使用基于一组图像的 opencv 训练 SVM?【英文标题】:How to train an SVM with opencv based on a set of images? 【发布时间】:2013-05-28 10:28:24 【问题描述】:

我有一个包含 JPG 格式的正片和另一个负片图像的文件夹,我想根据这些图像训练一个 SVM,我已经完成了以下操作,但收到一个错误:

Mat classes = new Mat();
Mat trainingData = new Mat();

Mat trainingImages = new Mat();
Mat trainingLabels = new Mat();

CvSVM clasificador;

for (File file : new File(path + "positives/").listFiles()) 
        Mat img = Highgui.imread(file.getAbsolutePath());
        img.reshape(1, 1);

        trainingImages.push_back(img);
        trainingLabels.push_back(Mat.ones(new Size(1, 1), CvType.CV_32FC1));
    

    for (File file : new File(path + "negatives/").listFiles()) 
        Mat img = Highgui.imread(file.getAbsolutePath());
        img.reshape(1, 1);

        trainingImages.push_back(img);
        trainingLabels.push_back(Mat.zeros(new Size(1, 1), CvType.CV_32FC1));
    

    trainingImages.copyTo(trainingData);
    trainingData.convertTo(trainingData, CvType.CV_32FC1);
    trainingLabels.copyTo(classes);

    CvSVMParams params = new CvSVMParams();
    params.set_kernel_type(CvSVM.LINEAR);

    clasificador = new CvSVM(trainingData, classes, new Mat(), new Mat(), params);

当我尝试运行时,我得到:

OpenCV Error: Bad argument (train data must be floating-point matrix) in cvCheckTrainData, file ..\..\..\src\opencv\modules\ml\src\inner_functions.cpp, line 857
Exception in thread "main" CvException [org.opencv.core.CvException: ..\..\..\src\opencv\modules\ml\src\inner_functions.cpp:857: error: (-5) train data must be floating-point matrix in function cvCheckTrainData
]
    at org.opencv.ml.CvSVM.CvSVM_1(Native Method)
    at org.opencv.ml.CvSVM.<init>(CvSVM.java:80)

我无法训练 SVM,知道吗?谢谢

【问题讨论】:

我正在尝试根据我已经获得的 segmets 对车牌进行分类,我的代码基于此示例:github.com/MasteringOpenCV/code/blob/master/… 您是否尝试过使用 CV_64F?为了绝对确定,您是否在 trainingData 被传递到 CvSVM 之前检查了它的类型? 感谢@morynicz,'CvType.typeToString(trainingData.type())' 将返回“CV_32FC3”.. 还尝试转换为 CV_64F 时出现相同的错误 【参考方案1】:

假设您通过重塑图像并使用它来训练 SVM 知道自己在做什么,最可能的原因是您的

Mat img = Highgui.imread(file.getAbsolutePath());

无法实际读取图像,生成一个矩阵imgdata 属性为空,最终将在 OpenCV 代码中触发以下内容:

// check parameter types and sizes
if( !CV_IS_MAT(train_data) || CV_MAT_TYPE(train_data->type) != CV_32FC1 )
    CV_ERROR( CV_StsBadArg, "train data must be floating-point matrix" );

基本上train_data 不满足第一个条件(作为有效矩阵)而不是不满足第二个条件(类型为 CV_32FC1)。

此外,尽管 reshape 对 *this 对象起作用,但它的作用类似于过滤器,其效果不是永久的。如果它在单个语句中使用而没有立即被使用或分配给另一个变量,它将是无用的。更改代码中的以下几行:

img.reshape(1, 1);
trainingImages.push_back(img);

到:

trainingImages.push_back(img.reshape(1, 1));

【讨论】:

【参考方案2】:

正如错误所说,您需要将矩阵的类型从整数类型(可能是 CV_8U)更改为浮点数类型,即 CV_32F 或 CV_64F。要做到这一点您可以使用cv::Mat::convertTo()。 Here 有点关于矩阵的深度和类型。

【讨论】:

实际上我是这样做的:'trainingData.convertTo(trainingData, CvType.CV_32FC1);'我的“类”填充了 [1] CV_32FC1 个矩阵 糟糕。抱歉,没看到。

以上是关于如何使用基于一组图像的 opencv 训练 SVM?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用opencv 训练分类器以及训练过程中的问题

如何使用具有面部特征的 openCV 训练支持向量机(svm)分类器?

如何在 Python 中使用 OpenCV 3.0 中的 HOG 功能训练 SVM 分类器?

如何标记 PCA 获得的训练投影以用于训练 SVM 进行分类? MATLAB

如何使用 OpenCV 3 训练 SVM 以识别“欧元”硬币?

在 OpencV 中训练 SVM 分类器?