SVM train doesn't accept my data

asked 2014-04-29 12:24:56 -0600

mrj1m0thy gravatar image

updated 2014-04-30 10:04:32 -0600

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 ...
(more)
edit retag flag offensive close merge delete

Comments

Better to Post your code here , your url's are not working .

FLY gravatar imageFLY ( 2014-04-30 01:53:48 -0600 )edit

vector<vector<double>> allData;

Mat trainingData(amount, 6, CV_32FC1, &allData); // you're passing in double data, so make it CV_64FC1

berak gravatar imageberak ( 2014-04-30 02:11:48 -0600 )edit

I changed it and still got an exception.

mrj1m0thy gravatar imagemrj1m0thy ( 2014-04-30 09:59:50 -0600 )edit
1

ah, sorry. it expects continuos memory for the data ptr, so allData is probably the wrong thing here

can't you push your svm-rows straight into the (empty) trainingMat and later reshape it ?

berak gravatar imageberak ( 2014-04-30 10:15:34 -0600 )edit

So your saying i should use the Mat to store my data from the start and then just put it into the train function at the end? If so, i don't think it will work because i don't think Mat's support dynamic sizes. In the code Mat trainingData(amount, 6, CV_64FC1, &allData); , amount is dynamic so the size of the matrix always changes. If Mat's support dynamic sizing then this would be great. But that is why I'm using vectors because the support dynamic sizes.

mrj1m0thy gravatar imagemrj1m0thy ( 2014-04-30 11:03:05 -0600 )edit

oh, it does allow the same dynamic push_back operations as a vector

// start with an empty Mat, but specify the rowsize
Mat trainingData(0,6,CV_64F);

// then, while looping over your items,
  trainData.push_back(aspect_ratio);
  trainData.push_back(solidity);
  trainData.push_back(equi_diameter);
  trainData.push_back(perimeter);
  trainData.push_back(contArea);
  trainData.push_back(extent);
berak gravatar imageberak ( 2014-04-30 12:07:28 -0600 )edit

So it automatically resets to the next colomn once 6 have been pushed?

mrj1m0thy gravatar imagemrj1m0thy ( 2014-04-30 12:37:36 -0600 )edit

it should.

when you can't assume this, still push one thing after another, then finally:

trainData=trainData.reshape(1,amount)
berak gravatar imageberak ( 2014-04-30 12:47:44 -0600 )edit

It doesn't order it properly when pushed. It just puts them next to eachother instead of in the same colomn. In other words it stays a one dimensional array.

mrj1m0thy gravatar imagemrj1m0thy ( 2014-04-30 13:12:38 -0600 )edit