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