Ошибка нормального байесовского классификатора OpenCV 3.0

Я пытаюсь создать классификатор для набора слов. Я нашел на этом веб-сайте вопрос (здесь), который помог я собрал приведенный ниже код вместе, но я застрял на classifier->train(trainingData,ml::ROW_SAMPLE, labels);. По сути, программа работает нормально, но когда доходит до этой строки, происходит сбой. Судя по всему, линия выполняет деление на ноль и, следовательно, дает сбой. Я просмотрел код и не нашел ошибки. Это может быть ошибка перевода из openCV 2 -> 3, не совсем уверен. Любая помощь будет принята с благодарностью!

#include <opencv2/core/core.hpp>
#include "opencv2/highgui/highgui.hpp"
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/ml.hpp>

#include <iostream>
#include <stdio.h>
#include <dirent.h>
#include <string.h>




using namespace std;
using namespace cv;

#define TRAINING_DATA_DIR "testImages/"
#define EVAL_DATA_DIR "evalImages/"


int dictSize = 1000;
TermCriteria tc(CV_TERMCRIT_ITER, 10, 0.001);
int retries = 1;
int flags = KMEANS_PP_CENTERS;

Ptr<FeatureDetector> detector = xfeatures2d::SURF::create();
Ptr<DescriptorExtractor> extractor = xfeatures2d::SURF::create();
Ptr<DescriptorMatcher> matcher = FlannBasedMatcher::create("FlannBased");



BOWKMeansTrainer bowTrainer(dictSize, tc, retries, flags);
BOWImgDescriptorExtractor bowDE(extractor, matcher);

void extractTrainingVocabulary(string path){
    struct dirent *de = NULL;
    DIR *d = NULL;
    d = opendir(path.c_str());

    if(d == NULL)
    {
        cerr << "Couldn't open directory" << endl;

    } else {
        // Add all the names of the files to be processed to a vector
        vector<string> files;
        while ((de = readdir(d))) {
            string nameOfFile(de->d_name);
            if ((strcmp(de->d_name,".") != 0) && (strcmp(de->d_name,"..") != 0)  && (strcmp(de->d_name,".DS_Store") != 0)) {
                files.push_back(nameOfFile);
            }
        }

        // Loop through all elements
        for (int f = 0; f < files.size(); f++){
            string fullPath = "./";
            fullPath += TRAINING_DATA_DIR;
            fullPath += files[f];

            cout << "[" << f+1 << "/" << files.size() << "]\tProcessing image: " << fullPath << endl;

            Mat input = imread(fullPath);
            if (!input.empty()){
                // Find all keypoints
                vector<KeyPoint> keypoints;
                detector->detect(input, keypoints);
                if (keypoints.empty()){
                    cerr << "Warning! could not find any keypoints in image " << fullPath << endl;
                } else {
                    // Extract the features
                    Mat features;
                    extractor->compute(input, keypoints, features);
                    // Add them to the trainer
                    bowTrainer.add(features);
                }
            } else {
                cerr << "Could not read image " << fullPath << endl;
            }
        }

    }
}

void extractBOWDescriptor(string path, Mat& descriptors, Mat& labels){
    struct dirent *de = NULL;
    DIR *d = NULL;
    d = opendir(path.c_str());

    if(d == NULL)
    {
        cerr << "Couldn't open directory" << endl;

    } else {
        // Add all the names of the files to be processed to a vector
        vector<string> files;
        while ((de = readdir(d))) {
            string nameOfFile(de->d_name);
            if ((strcmp(de->d_name,".") != 0) && (strcmp(de->d_name,"..") != 0)  && (strcmp(de->d_name,".DS_Store") != 0)) {
                files.push_back(nameOfFile);
            }
        }

        // Loop through all elements
        for (int f = 0; f < files.size(); f++){
            string fullPath = "./";
            fullPath += EVAL_DATA_DIR;
            fullPath += files[f];

            cout << "[" << f+1 << "/" << files.size() << "]\tProcessing image: " << fullPath << endl;

            Mat input = imread(fullPath);
            if (!input.empty()){
                // Find all keypoints
                vector<KeyPoint> keypoints;
                detector->detect(input, keypoints);
                if (keypoints.empty()){
                    cerr << "Warning! could not find any keypoints in image " << fullPath << endl;
                } else {
                    Mat bowDescriptor;
                    bowDE.compute(input, keypoints, bowDescriptor);
                    descriptors.push_back(bowDescriptor);
                    // Current file
                    string fileName = files[f];
                    // Strip extension
                    fileName.erase (fileName.end()-4, fileName.end());

                    float label = atof(fileName.c_str());
                    cout << "Filename: " << fileName << endl;

                    labels.push_back(label);
                }
            } else {
                cerr << "Could not read image " << fullPath << endl;
            }
        }

    }
}




int main(int argc, char ** argv) {
    // ============================ LEARN ============================
    cout << "Creating dict" << endl;
    extractTrainingVocabulary(TRAINING_DATA_DIR);




    vector<Mat> descriptors = bowTrainer.getDescriptors();

    int count=0;
    for(vector<Mat>::iterator iter=descriptors.begin();iter!=descriptors.end();iter++){
        count+=iter->rows;
    }

    cout << "Clustering " << count << " features. This might take a while..." << endl;

    Mat dictionary = bowTrainer.cluster();

    cout << "Writing to dict...";
    FileStorage fs("dict.yml",FileStorage::WRITE);
    fs << "vocabulary" << dictionary;
    fs.release();
    cout << "Done!" << endl;

    // =========================== EXTRACT ===========================
    // This will have to be loaded if we run it in two different instances
    bowDE.setVocabulary(dictionary);

    cout << "Processing training data..." << endl;
    Mat trainingData(0, dictSize, CV_32FC1);
    Mat labels(0,1,CV_32FC1);

    extractBOWDescriptor(EVAL_DATA_DIR, trainingData, labels);



    Ptr<ml::NormalBayesClassifier> classifier = ml::NormalBayesClassifier::create();

    if (trainingData.data == NULL || labels.data == NULL){
        cerr << "Mats are NULL!!" << endl;
    } else {
      classifier->train(trainingData,ml::ROW_SAMPLE, labels);
    }
//#warning Not yet tested
//    cout << "Processing evaluation data" << endl;
//    Mat evalData(0,dictSize,CV_32FC1);
//    Mat groundTruth(0,1,CV_32FC1);
//    extractBOWDescriptor(EVAL_DATA_DIR, evalData, groundTruth);

    return 0;
}

РЕДАКТИРОВАТЬ

Как и было запрошено, вот ошибка.

  • Через терминал: Floating point exception: 8
  • XCode 6: Thread 1:EXC_ARITHMETIC (code=EXC_i386_DIV, subcode=0x0)

person ruben1691    schedule 09.07.2015    source источник
comment
Можете добавить исключение?   -  person user_0    schedule 09.07.2015
comment
добавлено в исходный вопрос   -  person ruben1691    schedule 09.07.2015
comment
У меня такая же проблема с классификатором SVM opencv 3.0.0. Вы нашли решение?   -  person Kaiwen Huang    schedule 22.10.2015


Ответы (2)


Пожалуйста, попробуйте изменить

labels.push_back(label);

to

labels.push_back((int)label);

У меня была такая же проблема с обучением SVM, и я понял, что метки классов должны быть целыми числами.

Ваше здоровье!

person jaycwb92    schedule 25.09.2015

Просто чтобы поделиться, как я решил ту же проблему в моем проекте os x.

Судя по всему, кажется, что матрица, содержащая метки, тоже является проблемой в моем проекте. По какой-то странной причине создание матрицы любым другим способом или приведение типов к int значениям, вставленным в матрицу, у меня не сработали.

Проблема была решена только следующим образом: пример кода учебника OpenCV 3.0.0 SVM инициализировал свою матрицу меток. Учебник по OpenCV SVM

Что проходит:

int labels[4] = {1, -1, -1, -1};
Mat labelsMat(4, 1, CV_32SC1, labels);

После того, как я изменил свою матрицу меток, которая должна быть инициализирована как таковая из массива целочисленных меток, ошибка исчезла.

person Kaiwen Huang    schedule 22.10.2015