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

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

我正在尝试在 cocos2d-x 游戏中使用 OpenCV SVM 分类器。这是一个简单的测试函数:

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){

    }
}

它给出了一个输出:

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

基于本教程:

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

特别是这个方法:

// 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){

    }

}

我已经 运行 在终端中使用了它并且它工作了。

这是 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;
}

我在这里找到了它:

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

这个断言是什么意思?有人可以向我解释吗?我该如何解决这个问题?

断言说

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

这意味着样本的列数不正确或类型不正确 CV_32F

您好像忘记了reshape函数,所以您的数据违反了第一个条件。我认为为了应用 svm,数据需要是向量,即 1 x n 矩阵。