c++ - 使用 hu 矩训练 SVM

标签 c++ opencv svm

我正在学习 SVM,所以我制作了一个示例程序来训练 SVM 来检测符号是否在图像中。所有图像都是黑白的(符号为黑色,背景为白色)。我有 12 个训练图像,6 个正片(带有符号)和 6 个负片(没有它)。我使用 hu moments 获取每个图像的描述符,然后使用这些描述符构建训练矩阵。我还有一个 Labels 矩阵,其中包含每个图像的标签:如果是正则为 1,如果是负则为 0。但是我在训练 SVM 的那一行遇到了一个错误(类似于段错误)。这是我的代码:

using namespace cv;
using namespace std;

int main(int argc, char* argv[])
{
    //arrays where the labels and the features will be stored
    float labels[12] ;
    float trainingData[12][7] ;

    Moments moment;
    double hu[7];

  //===============extracting the descriptos for each positive image=========
    for ( int i = 0; i <= 5; i++){

        //the images are called t0.png ... t5.png and are in the folder train
        std::string path("train/t");
        path += std::to_string(i);
        path += ".png";

        Mat input = imread(path, 0); //read the images
        bitwise_not(input, input); //invert black and white
        Mat BinaryInput;
        threshold(input, BinaryInput, 100, 255, cv::THRESH_BINARY); //apply theshold

        moment = moments(BinaryInput, true); //calculate the moments of the current image
        HuMoments(moment, hu); //calculate the hu moments (this will be our descriptor)

        //setting the row i of the training data as the hu moments
        for (int j = 0; j <= 6; j++){
            trainingData[i][j] = (float)hu[j];
        }

        labels[i] = 1; //label=1 because is a positive image
    }

  //===============extracting the descriptos for each negative image=========
    for (int i = 0; i <= 5; i++){

        //the images are called tn0.png ... tn5.png and are in the folder train
        std::string path("train/tn");
        path += std::to_string(i);
        path += ".png";

        Mat input = imread(path, 0); //read the images
        bitwise_not(input, input); //invert black and white
        Mat BinaryInput;
        threshold(input, BinaryInput, 100, 255, cv::THRESH_BINARY); //apply theshold

        moment = moments(BinaryInput, true); //calculate the moments of the current image
        HuMoments(moment, hu); //calculate the hu moments (this will be our descriptor)

        for (int j = 0; j <= 6; j++){
            trainingData[i + 6][j] = (float)hu[j];
        }

         labels[i + 6] = 0;  //label=0 because is a negative image

    }
    
//===========================training the SVM================
    //we convert the labels and trainingData matrixes to Mat objects
    Mat labelsMat(12, 1, CV_32FC1, labels);
    Mat trainingDataMat(12, 7, CV_32FC1, trainingData);

    //create the SVM
    Ptr<ml::SVM> svm = ml::SVM::create();
    
    //set the parameters of the SVM
    svm->setType(ml::SVM::C_SVC);
    svm->setKernel(ml::SVM::LINEAR);
    CvTermCriteria criteria = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);
    svm->setTermCriteria(criteria);

     //Train the SVM !!!!!HERE OCCURS THE ERROR!!!!!!
     svm->train(trainingDataMat, ml::ROW_SAMPLE, labelsMat);


    //Testing the SVM...
    Mat test = imread("train/t1.png", 0); //this should be a positive test
    bitwise_not(test, test);
    Mat testBin;
    threshold(test, testBin, 100, 255, cv::THRESH_BINARY);

    Moments momentP = moments(testBin, true); //calculate the moments of the test image

    double huP[7];
    HuMoments(momentP, huP);

    Mat testMat(1, 7, CV_32FC1, huP); //setting the hu moments to the test matrix

    double resp = svm->predict(testMat); //pretiction of the SVM
    printf("%f", resp); //Response

    getchar();

}

我知道程序在该行之前运行良好,因为我打印了 labelsMattrainingDataMat 并且它们中的值是正确的。即使在控制台中,我也可以看到程序运行良好,直到执行该行。然后控制台显示此消息:

OpenCV error: Bad argument (in the case of classification problem the responses must be categorical;  either specify varType when creating TrainDatam or pass integer responses)

我真的不知道这是什么意思。知道什么可能导致问题吗?如果您需要任何其他详细信息,请告诉我。

编辑

对于 future 的读者:

问题在于我将 labels 数组定义为 float 组,将 LabelsMat 定义为 CV_32FC1 的 Mat 的方式。包含标签的数组内部需要有整数,所以我改变了:

float labels[12];

int labels[12];

也变了

Mat labelsMat(12, 1, CV_32FC1, labels);

Mat labelsMat(12, 1, CV_32SC1, labels);

这就解决了错误。谢谢

最佳答案

尝试改变:

Mat labelsMat(12, 1, CV_32FC1, labels);

Mat labelsMat(12, 1, CV_32SC1, labels);

发件人:http://answers.opencv.org/question/63715/svm-java-opencv-3/

如果这不起作用,希望其中一篇文章对您有所帮助:

Opencv 3.0 SVM train classification issues

OpenCV SVM Training Data

关于c++ - 使用 hu 矩训练 SVM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34425460/

相关文章:

c++ - 抛硬币的组合

c++ - libsvm : C++ vs. MATLAB : What's With The Different Accuracies?

java - 在 Java 应用程序中使用经过训练的 LibSVM 模型的最佳方式是什么?

machine-learning - 在 libsvm 中使用我自己的内核

c++ - 在 C++ 中与复制构造函数作斗争

c++ - 在通知期间注册/注销观察者时如何避免死锁?

c++ - 带有 C++11 线程的 Qtcreator

c++ - 运行 OpenCv 代码 "The program can' t 时出现系统错误,因为 opencv_core244.dll 丢失”

c++ - 解密不适用于已保存的图像,但适用于图像的像素操作矩阵

python - 使用 Shiny 对象改进背景提取 (OpenCV/Python)