In a nutshell, the data of SVM needed are training data and labels.
Training data
rows : corresponding to specific samples(ex : images)
columns : corresponding to the features(ex : pixels)
In the case of image, all of the pixels values would be considered as features.
cv::Mat trainingData; for(size_t i = 0; i != numTrainData; ++i){ std::stringstream name; name<<leaf<<i<<".png"; cv::Mat samples = cv::imread(name.str()); //reshape it to 1 channel and 1 row samples.reshape(1, 1); trainingData.push_back(samples); } //convert all of the image to floating point values trainingData.convertTo(trainingData, CV_32F);
That is, if the original samples are look like a 4X4, after transform, it would become a 1X16 matrix.
Although this is an example for image, but it could apply to everything, the most important part is transform the samples into a 1 row and 1 channel cv::Mat, put all of the features(data) of the samples into the column.
The function of reshape is very convenient, but it could not tackle with non-continuous image, we have to transform them into a suitable cv::Mat by ourselves.Here is a generic transform function design for images.
template<typename T = uchar, typename U = float> void transform_to_svm_training_data(cv::Mat &input) { if(input.isContinuous()){ input = input.reshape(1, 1); input.convertTo(input, cv::DataType<U>().depth); return; } cv::Mat output(1, input.total() * input.channels(), cv::DataType<U>().depth); auto output_ptr = output.ptr<U>(0); OCV::for_each_channels<T>(input, [&](T a) { *output_ptr = a; ++output_ptr; }); input = output; }
There are one more thing to keep in mind, all of the samples of the training data should have same numbers of features, all of the features should have the same type.The codes of OCV::for_each_channels can found on github, the principal of it could refer to opencv and generic programming.
Labels
rows : same as the number of rows of the training data, the samples and the rows of the labels are mapping to each other.
columns : specify what are the samples belong to? For example if you were classifying leafs and non- leafts, you would need to specify which one is leaf and which one is non-leaf in the training data(ex : 1 == leaf; -1 == non-leaf).
Examples
cv::Mat trainingImages; std::vector<int> trainingLabels; for(int i = 0; i != numPlates; ++i) { std::stringstream ss; ss << path_Plates << i << ".jpg"; cv::Mat img = cv::imread(ss.str(), 0); transform_to_svm_training_data(img); //every labels are associated to the training data trainingImages.push_back(img); trainingLabels.emplace_back(1); } for(int i = 0; i != numNoPlates; ++i) { std::stringstream ss; ss << path_NoPlates << i << ".jpg"; cv::Mat img = cv::imread(ss.str(), 0); transform_to_svm_training_data(img); trainingImages.push_back(img); trainingLabels.emplace_back(0); } cv::Mat classes; cv::Mat trainingData = trainingImages; cv::Mat(trainingLabels).copyTo(classes); trainingData.convertTo(trainingData, CV_32FC1); cv::FileStorage fs("SVM.xml", cv::FileStorage::WRITE); fs << "TrainingData" << trainingData; fs << "classes" << classes;
No comments:
Post a Comment