2017-02-20 5 views
1

Я пытаюсь использовать классификатор SVC OpenCV в игре cocos2d-x. Вот простой тест функции:Ошибка OpenCV: утверждение не выполнено (samples.cols == var_count && samples.type() == CV_32F) в предсказании

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

Что это значит утверждают? Может кто-нибудь объяснить это мне? Как я могу это исправить?

ответ

2

утверждение говорит

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

, что означает, что образец либо не имеет нужного количества столбцов или не имеет тип CV_32F.

Похоже, вы забыли функцию reshape, поэтому ваши данные нарушают первое условие. Я думаю, что для применения svm данные должны быть вектором, то есть 1 x n.

+0

cv :: Mat testMat2 = testMat.clone(). Reshape (1, 1); - Я попробовал, и результат такой же. – Makalele

+0

Попробуйте загрузить изображение в виде серого изображения: 'imread (" test.jpg ", 0)' –

+0

Я даже попробовал: cv :: cvtColor (testMat, greyMat, cv :: COLOR_BGR2GRAY); – Makalele

Смежные вопросы