Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Problem using Bayes Classifier

Hello, I'm a first timer with OpenCV and while I have read the documentation and devs tutorial found here and there, I still haven't managed to make the machine learning library work in any way: I'm still trying to use a Bayes Classifier in order to train it with a dataset of potholes images (on which I have manually applied regions using the OpenCV tool).

What I specifically don't understand is what does the Bayes->train(...) want as training set and class/label set? A vector of Mats? A Mats of Mats? The latter don't work since the image have all different size and some of the aren't that big so resizing them would be a very nice option. The first also don't work, giving me the following error

OpenCV Error: Assertion failed (0 <= i && i < (int)v.size()) in cv::debug_build_guard::_InputArray::getMat_, file D:\opencv\sources\modules\core\src\matrix.cpp, line 1275

The code I'm executing is the following:

enum CLASSES {
    BACKGROUND, // 0
    POTHOLE // 1
};

struct Box {
    Point2i bottom_right;
    Point2i top_left;

    bool contains(Point2i);
};

struct Annotation {

    string image_path;
    string image_name;
    vector<Box> objects;

};

const string data_root_path = "D:/Xander_C/Downloads/sctm/potehole_detection_dataset/";

bool Box::contains(Point2i p) {
    return p.x <= this->bottom_right.x && p.x >= this->top_left.x && p.y <= this->bottom_right.y && p.y >= this->top_left.y;
}

void hold() {
    char * c = "a";
    int i = scanf_s(c);
}

void load_annotations(const string & filename, vector<Annotation> & annotations) 
{

    ifstream infile(filename);
    string line;
    while (std::getline(infile, line))
    {

        istringstream iss(line);
        vector<string> results(istream_iterator<string>{iss}, istream_iterator<string>());
        vector<Box> locators;

        for (size_t i = 2; i < results.size(); i += 4) 
        {

            Point2i bottom_right(stoi(results[i]), stoi(results[i + 1]));
            Point2i top_left(stoi(results[i + 2]), stoi(results[i + 3]));

            Box b = { bottom_right, top_left };

            locators.push_back(b);
        }

        string image_name = results[0].substr(results[0].find_last_of("\\")+1);

        clog << image_name << endl;

        struct Annotation a = {results[0], image_name, locators };

        annotations.push_back(a);
    }
}

void images_load(const vector<Annotation> & annotations, vector< Mat > & loaded_images)
{
    for (size_t i = 0; i < annotations.size(); ++i)
    {
        Mat img = imread(annotations[i].image_path, IMREAD_COLOR);
        if (img.empty())
        {
            cout << annotations[i].image_path << " is invalid!" << endl;
        }
        else {
            loaded_images.push_back(img);
        }
    }
}

void mask_extraction(const vector<Mat> & images, const vector<Annotation> & annotations, vector<Mat> & training_set, vector<Mat> & classes_set) 
{
    for (size_t i = 0; i < images.size(); ++i) 
    {

        Mat image = images[i];
        vector<Box> windows = annotations[i].objects;
        Mat classes(image.rows, image.cols, CV_32FC1);

        for (size_t row = 0; row < image.rows; ++row) 
        {

            for (size_t col = 0; col < image.cols; ++col) 
            {

                for (size_t w = 0; w < windows.size(); ++w) 
                {

                    if (windows[w].contains(Point2i(row, col))) 
                    {
                        classes.at<int>(row, col) = CLASSES::POTHOLE;
                    }
                    else 
                    {
                        classes.at<int>(row, col) = CLASSES::BACKGROUND;
                    }
                }
            }
        }

        image.convertTo(image, CV_32FC1);

        training_set.push_back(image.reshape(1, 1));
        classes_set.push_back(classes.reshape(1, 1));
    }
}

int main(int argc, char*argv[]) {

    string annotations_path = data_root_path + "positive_annotations.txt";
    string algorithm_save_location = data_root_path + "trained_bayes.xml";

    //Load images from annotation file
    vector<Annotation> annotations;
    vector<Mat> loaded_images;

    // Parse the annotation file and extract the absolute image paths, number of regions and Pair of bottom right and top left corners of the region
    load_annotations(annotations_path, annotations); 

    // Properly load the images into a vector of Mat
    images_load(annotations, loaded_images);

    clog << "Loaded " << loaded_images.size() << " images." << endl;

    vector<Mat> training_set;
    vector<Mat> classes; // take all the pixels inside the locators squares
    mask_extraction(loaded_images, annotations, training_set, classes);

    Ptr<NormalBayesClassifier> Bayes = NormalBayesClassifier::create();

    Bayes->train(training_set, ml::SampleTypes::ROW_SAMPLE, classes);

    Bayes->save(algorithm_save_location);

    hold();

    return 1;
}