简体   繁体   中英

OpenCV Error: Assertion failed (samples.cols == var_count && samples.type() == CV_32F) in predict

I'm trying to use OpenCV SVM classifier in cocos2d-x game. Here's a simple test function:

void HelloWorld::testOpenCV(){
    // Load SVM classifier
    auto classifierPath = FileUtils::getInstance()->fullPathForFilename("classifier.yml");
    cv::Ptr<cv::ml::SVM> svm = cv::ml::StatModel::load<cv::ml::SVM>(classifierPath);

    string filename = "test.jpg";

    auto img = new Image();
    img->initWithImageFile(filename);

    int imageSize = (int)img->getDataLen();
    int imageXW = img->getWidth();
    int imageYW = img->getHeight();
    unsigned char * srcData = img->getData();

    CCLOG("imageXW=%d, imageYW=%d", imageXW, imageYW);
    int ch = imageSize/(imageXW*imageYW);
    CCLOG("image=%dch raw data...", ch);

    cv::Mat testMat = createCvMatFromRaw(srcData, imageXW, imageYW, ch);
    testMat.convertTo(testMat, CV_32F);

    // try to predict which number has been drawn
    try{
        int predicted = svm->predict(testMat);

        CCLOG("Recognizing following number -> %d", predicted);

    }catch(cv::Exception ex){

    }
}

And it gives an output:

imageXW=28, imageYW=28
image=3ch raw data...
OpenCV Error: Assertion failed (samples.cols == var_count && samples.type() == CV_32F) in predict, file /Volumes/build-storage/build/master_iOS-mac/opencv/modules/ml/src/svm.cpp, line 1930

It is based on this tutorial:

https://www.simplicity.be/article/recognizing-handwritten-digits/

Especially on this method:

// Standard library
#include <iostream>
#include <vector>
#include <string>

// OpenCV
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/ml.hpp>

// POSIX
#include <unistd.h>

/**
 * main
 **/ 
int main( int argc, char** argv )
{

    //
    // Load SVM classifier 
    cv::Ptr<cv::ml::SVM> svm = cv::ml::StatModel::load<cv::ml::SVM>("classifier.yml");


    // read image file (grayscale)
    cv::Mat imgMat = cv::imread("test.jpg", 0);

    // convert 2d to 1d 
    cv::Mat testMat = imgMat.clone().reshape(1,1);
    testMat.convertTo(testMat, CV_32F);

    // try to predict which number has been drawn
    try{
        int predicted = svm->predict(testMat);

        std::cout << std::endl  << "Recognizing following number -> " << predicted << std::endl << std::endl;

        std::string notifyCmd = "notify-send -t 1000 Recognized: " + std::to_string(predicted);
        system(notifyCmd.c_str());

    }catch(cv::Exception ex){

    }

}

I've ran it in terminal and it worked.

Here's an implementation of createCvMatFromRaw:

cv::Mat HelloWorld::createCvMatFromRaw(unsigned char *rawData, int rawXW, int rawYW, int ch)
{
    cv::Mat cvMat( rawYW, rawXW, CV_8UC4); // 8 bits per component, 4 channels

    for (int py=0; py<rawYW; py++) {
        for (int px=0; px<rawXW; px++) {
            int nBasePos = ((rawXW * py)+px) * ch;
            cvMat.at<cv::Vec4b>(py, px) = cv::Vec4b(rawData[nBasePos + 0],
                                                    rawData[nBasePos + 1],
                                                    rawData[nBasePos + 2],
                                                    0xFF);

        }
    }

    return cvMat;
}

I've found it here:

http://blog.szmake.net/archives/845

What does this assert mean? Can someone explain it to me? How can I fix this?

The assertion says

OpenCV Error: Assertion failed (samples.cols == var_count && samples.type() == CV_32F)

which means that the sample either doesn't have the right number of columns or doesn't have type CV_32F .

It looks like you forgot the reshape function, so your data violates the first condition. I think in order to apply svm , the data needs to be a vector, ie 1 xn matrix.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM