Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Training your own SVM OpenCV

Hi everyone. I have a project which bases on training my own SVM to detect particular silhouette. I wrote some code but it doesn't work so I want to be sure that I did everything ok. I want also mention that I am new in OpenCV world so sorry if I write some silly things but here is how I imagine it:

1) First of all, I collect some materials to train. I create two folders with some positive samples (my silhouette to detect - just about 200 samples) and negative folder (everything different - about 1300 samples). Pictures are 64x128.

2) The second step is to create a feature vector of each sample. Here I am not sure which information from the picture is important. In my case, I use HOG on my pictures and put gradient of each pixel to feature vector but maybe it is better to take for example H value from HSV picture? Here is some code:

std::vector<float> featureVector;
hog.compute(image, featureVector);

3) I creat Mat to keep all of this vectors. 1 row = 1 feature vector. So for example when I have 1500 samples then I got matrix with 1500 rows. This is how I do it:

trainingData = cv::Mat::ones(sizePositive + sizeNegative, 3780, CV_32FC1);
labels = cv::Mat::zeros(sizePositive + sizeNegative, 1, CV_32S);
for (int i = 0; i < sizePositive; i++)
{
    for (int j = 0; j < 3780; j++)
    {
        trainingData.at<float>(i, j) = features[j];
    }
    labels.at<float>(i, 0) = 1;
}

for (int i = 0; i < sizeNegative; i++)
{
    std::vector<float> features = calculateFeatures(filenamesNegative[i]);

    for (int j = 0; j < 3780; j++)
    {
        trainingData.at<float>(i+sizePositive, j) = features[j];
    }
    labels.at<float>(i+sizePositive, 0) = -1;
}

In this step, I also create labels matrix and put 1 when it is a positive sample and -1 when it is a negative sample.

4) After this, I am ready to train? I have trainingData with my features vectors and my labels which defines which sample was positive and which was negative. ( I checked XML files with my labels and trainingData and they look fine). Here is how I train my SVM:

cv::Ptr<cv::ml::SVM> svm = cv::ml::SVM::create();
// set the parameters
svm->setType(cv::ml::SVM::C_SVC);
svm->setKernel(cv::ml::SVM::RBF);

// create training data object
cv::Ptr<cv::ml::TrainData> tData = cv::ml::TrainData::create(trainingData, cv::ml::SampleTypes::ROW_SAMPLE, labels);

// train svm to optimal parameters using opencv autotraining
svm->trainAuto(tData);

What do you think? It is good thinking? I am doing something wrong? Because it seems that this SVM doesn't learn anything :/ I will be very grateful for your help and some advice.

Training your own SVM OpenCV

Hi everyone. I have a project which bases on training my own SVM to detect particular silhouette. I wrote some code but it doesn't work so I want to be sure that I did everything ok. I want also mention that I am new in OpenCV world so sorry if I write some silly things but here is how I imagine it:

1) First of all, I collect some materials to train. I create two folders with some positive samples (my silhouette to detect - just about 200 samples) and negative folder (everything different - about 1300 samples). Pictures are 64x128.

2) The second step is to create a feature vector of each sample. Here I am not sure which information from the picture is important. In my case, I use HOG on my pictures and put gradient of each pixel to feature vector but maybe it is better to take for example H value from HSV picture? Here is some code:

std::vector<float> featureVector;
hog.compute(image, featureVector);

3) I creat Mat to keep all of this vectors. 1 row = 1 feature vector. So for example when I have 1500 samples then I got matrix with 1500 rows. This is how I do it:

trainingData = cv::Mat::ones(sizePositive + sizeNegative, 3780, CV_32FC1);
labels = cv::Mat::zeros(sizePositive + sizeNegative, 1, CV_32S);
for (int i = 0; i < sizePositive; i++)
{
    for (int j = 0; j < 3780; j++)
    {
        trainingData.at<float>(i, j) = features[j];
    }
    labels.at<float>(i, labels.at<int>(i, 0) = 1;
}

for (int i = 0; i < sizeNegative; i++)
{
    std::vector<float> features = calculateFeatures(filenamesNegative[i]);

    for (int j = 0; j < 3780; j++)
    {
        trainingData.at<float>(i+sizePositive, j) = features[j];
    }
    labels.at<float>(i+sizePositive, labels.at<int>(i+sizePositive, 0) = -1;
}

In this step, I also create labels matrix and put 1 when it is a positive sample and -1 when it is a negative sample.

4) After this, I am ready to train? I have trainingData with my features vectors and my labels which defines which sample was positive and which was negative. ( I checked XML files with my labels and trainingData and they look fine). Here is how I train my SVM:

cv::Ptr<cv::ml::SVM> svm = cv::ml::SVM::create();
// set the parameters
svm->setType(cv::ml::SVM::C_SVC);
svm->setKernel(cv::ml::SVM::RBF);

// create training data object
cv::Ptr<cv::ml::TrainData> tData = cv::ml::TrainData::create(trainingData, cv::ml::SampleTypes::ROW_SAMPLE, labels);

// train svm to optimal parameters using opencv autotraining
svm->trainAuto(tData);

What do you think? It is good thinking? I am doing something wrong? Because it seems that this SVM doesn't learn anything :/ I will be very grateful for your help and some advice.

Training your own SVM OpenCV

Hi everyone. I have a project which bases on training my own SVM to detect particular silhouette. I wrote some code but it doesn't work so I want to be sure that I did everything ok. I want also mention that I am new in OpenCV world so sorry if I write some silly things but here is how I imagine it:

1) First of all, I collect some materials to train. I create two folders with some positive samples (my silhouette to detect - just about 200 samples) and negative folder (everything different - about 1300 samples). Pictures are 64x128.

2) The second step is to create a feature vector of each sample. Here I am not sure which information from the picture is important. In my case, I use HOG on my pictures and put gradient of each pixel to feature vector but maybe it is better to take for example H value from HSV picture? Here is some code:

std::vector<float> featureVector;
hog.compute(image, featureVector);

3) I creat Mat to keep all of this vectors. 1 row = 1 feature vector. So for example when I have 1500 samples then I got matrix with 1500 rows. This is how I do it:

trainingData = cv::Mat::ones(sizePositive + sizeNegative, 3780, CV_32FC1);
labels = cv::Mat::zeros(sizePositive + sizeNegative, 1, CV_32S);
for (int i = 0; i < sizePositive; i++)
{
    for (int j = 0; j < 3780; j++)
    {
        trainingData.at<float>(i, j) = features[j];
    }
    labels.at<int>(i, 0) = 1;
}

for (int i = 0; i < sizeNegative; i++)
{
    std::vector<float> features = calculateFeatures(filenamesNegative[i]);

    for (int j = 0; j < 3780; j++)
    {
        trainingData.at<float>(i+sizePositive, j) = features[j];
    }
    labels.at<int>(i+sizePositive, 0) = -1;
}

In this step, I also create labels matrix and put 1 when it is a positive sample and -1 when it is a negative sample.

4) After this, I am ready to train? I have trainingData with my features vectors and my labels which defines which sample was positive and which was negative. ( I checked XML files with my labels and trainingData and they look fine). Here is how I train my SVM:

cv::Ptr<cv::ml::SVM> svm = cv::ml::SVM::create();
// set the parameters
svm->setType(cv::ml::SVM::C_SVC);
svm->setKernel(cv::ml::SVM::RBF);

// create training data object
cv::Ptr<cv::ml::TrainData> tData = cv::ml::TrainData::create(trainingData, cv::ml::SampleTypes::ROW_SAMPLE, labels);

// train svm to optimal parameters using opencv autotraining
svm->trainAuto(tData);

What do you think? It is good thinking? I am doing something wrong? Because it seems that this SVM doesn't learn anything :/ I will be very grateful for your help and some advice.

P.S. Here is my database with negative and positive samples. At the beginning I wanted to train my svm to just recognize people (not particular silhouette) : https://drive.google.com/drive/folders/1xijQrOayS_9s93UnYbv8mxxIoqlaJU0Z