I've been trying to figure out how to use the svm train function. From what i understand from some online sources, you have to have an array of your data followed by another array that labels the positions to be either good or bad data. What i have is code that finds contours in the picture, extracts the properties, puts them in a vector and then the vector is put into a Mat which is them passed into the train function. But everytime i get to the train function it crashes with an exception at memory location. I believe that vectors aren't accepted by the Mat constructor and this could possibly be the source of the problem. I would like to know what the problem is if it is not that. And if it is, would there be a way to get it to work with the vectors?
The function for the detection and training:
http://pastebin.com/GgN6k3Pb
All the code:
http://pastebin.com/ZvN8eukr
void contourDetection(){
//Vector that represents the hierarchy of the contours
vector< Vec4i > hierarchy;
///Find contours and store in a contours, then store the contour hierarchies in hierarchy
cv::findContours(dst, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE);
double area;
int count = 0, all = 0;
CvSVM detector;
bool exit = false;
vector<vector<double>> allData;
vector<float> labels;
//Load the training data
detector.load("Muskrat_Counting_SVM.xml");
//Size of the whole picture
int totSize = dst.total();
//Iterate through all parent contours
for (int i = 0; i < contours.size() && exit == false; i = hierarchy[i][0])
{
//Find the size of the outer contours (lakes)
area = contourArea(contours[i]);
//Find the biggest contours (presumed to be the lakes)**Needs optimization
if (area > totSize*.20)// && area < totSize*.5)
{
//Draw the lake
draw(contours[i], "red");
//Using hierarchy array to determine hierarchy, this loop is for the child contours
for (int j = hierarchy[i][2]; hierarchy[j][0] > 0 && exit == false; j = hierarchy[j][0]){
//Find contour size
double contArea = contourArea(contours[j]);
if (contArea > 20 && contArea < 300){ //When size of the contour is inbetween those area
//Get the location of the center of the contour for zooming
Moments mu = moments(contours[j], false);
pCen = Point2f(mu.m10 / mu.m00, mu.m01 / mu.m00);
all++;
//Draw current contour
draw(contours[j], "orange");
//Evaluate next contour
zoom(Mat(frame));
//Output question
cout << "Is this a contour? (Y or N) ";
string input;
while (exit == false){
//Retrieve user input
getline(cin, input);
cout << endl;
cout << "\n\nGetting next contour...";
//If user enters Y
if (strUpper(input) == "Y" || strUpper(input) == "N")
{
if (strUpper(input) == "Y"){
//Draw the correct contour green
draw(contours[j], "green");
//Count the drawn contours
count++;
labels.push_back(1);
}
else{
draw(contours[j], "red");
labels.push_back(-1);
}
///////////////////////###################Get training data############################////////////////////////////
//Get aspect ratio
Rect rect = boundingRect(contours[j]);
double aspect_ratio = float(rect.width) / rect.height;
//Get extent
double rect_area = float(rect.width)*rect.height;
double extent = float(contArea) / rect_area;
//Get solidity
vector<Point> hull;
convexHull(contours[j], hull);
double hull_area = contourArea(hull);
double solidity = float(contArea) / hull_area;
//Get equivalent diameter
double equi_diameter = sqrt(4 * contArea / 3.14159265);
//Perimeter
double perimeter = arcLength(contours[j], true);
//Compile data
vector<double> data = { aspect_ratio, extent, solidity, equi_diameter, perimeter, contArea };
allData.push_back(data);
//For prediction
/*float response = detector.predict(trainingData);
if (response == 1)
{
draw(contours[j], "green");
count++;
all++;
}
else if (response == -1)
{
draw(contours[j], "red");
all++;
}*/
////////////////////////////////////////////.........
break;
}
//Identified as not a push-up (False detection)
/*else if (strUpper(input) == "N")
{
draw(contours[j], "red");
break;
}*/
//Exits training process
else if (strUpper(input) == "QUIT")
exit = true;
//Incorrect entry
else
cout << endl << "Enter Y or N..." << endl;
}
}
}
}
}
int amount = allData.size();
//Produce matrix containing training data
Mat trainingData(amount, 6, CV_32FC1, CV_64FC1, &allData);
//Array to label data
Mat labelsMat(amount, 1, CV_32FC1, &labels);
CvSVMParams params; //
params.svm_type = CvSVM::C_SVC; //Required data for training
params.kernel_type = CvSVM::LINEAR; //
//params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6); //
//Append training data to SVM
detector.train(trainingData, labelsMat, Mat(), Mat(), params);
//detector.train_auto(trainingData, labelsMat, Mat(), Mat(), params);
//Save the machine learning data
detector.save("Muskrat_Counting_SVM.xml");
system("cls");
info();
cout << "\n\nTotal Circled: " << count << endl; //Output how many contours that were detected
cout << "Total: " << all << endl; //Total amount of contours before refinement
}