使用 hu 矩训练 SVM
Training an SVM using hu moments
我正在学习 SVM,所以我正在制作一个示例程序来训练 SVM 来检测符号是否在图像中。所有图像都是黑白的(符号为黑色,背景为白色)。我有 12 个训练图像,6 个正片(带有符号)和 6 个负片(没有它)。我使用 hu moments
来获取每个图像的描述符,然后我用这些描述符构建训练矩阵。我还有一个 Labels
矩阵,其中包含每个图像的标签:如果是正数则为 1,如果是负数则为 0。但是我在训练 SVM 的那一行遇到了一个错误(类似于分段错误)。这是我的代码:
using namespace cv;
using namespace std;
int main(int argc, char* argv[])
{
//arrays where the labels and the features will be stored
float labels[12] ;
float trainingData[12][7] ;
Moments moment;
double hu[7];
//===============extracting the descriptos for each positive image=========
for ( int i = 0; i <= 5; i++){
//the images are called t0.png ... t5.png and are in the folder train
std::string path("train/t");
path += std::to_string(i);
path += ".png";
Mat input = imread(path, 0); //read the images
bitwise_not(input, input); //invert black and white
Mat BinaryInput;
threshold(input, BinaryInput, 100, 255, cv::THRESH_BINARY); //apply theshold
moment = moments(BinaryInput, true); //calculate the moments of the current image
HuMoments(moment, hu); //calculate the hu moments (this will be our descriptor)
//setting the row i of the training data as the hu moments
for (int j = 0; j <= 6; j++){
trainingData[i][j] = (float)hu[j];
}
labels[i] = 1; //label=1 because is a positive image
}
//===============extracting the descriptos for each negative image=========
for (int i = 0; i <= 5; i++){
//the images are called tn0.png ... tn5.png and are in the folder train
std::string path("train/tn");
path += std::to_string(i);
path += ".png";
Mat input = imread(path, 0); //read the images
bitwise_not(input, input); //invert black and white
Mat BinaryInput;
threshold(input, BinaryInput, 100, 255, cv::THRESH_BINARY); //apply theshold
moment = moments(BinaryInput, true); //calculate the moments of the current image
HuMoments(moment, hu); //calculate the hu moments (this will be our descriptor)
for (int j = 0; j <= 6; j++){
trainingData[i + 6][j] = (float)hu[j];
}
labels[i + 6] = 0; //label=0 because is a negative image
}
//===========================training the SVM================
//we convert the labels and trainingData matrixes to Mat objects
Mat labelsMat(12, 1, CV_32FC1, labels);
Mat trainingDataMat(12, 7, CV_32FC1, trainingData);
//create the SVM
Ptr<ml::SVM> svm = ml::SVM::create();
//set the parameters of the SVM
svm->setType(ml::SVM::C_SVC);
svm->setKernel(ml::SVM::LINEAR);
CvTermCriteria criteria = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);
svm->setTermCriteria(criteria);
//Train the SVM !!!!!HERE OCCURS THE ERROR!!!!!!
svm->train(trainingDataMat, ml::ROW_SAMPLE, labelsMat);
//Testing the SVM...
Mat test = imread("train/t1.png", 0); //this should be a positive test
bitwise_not(test, test);
Mat testBin;
threshold(test, testBin, 100, 255, cv::THRESH_BINARY);
Moments momentP = moments(testBin, true); //calculate the moments of the test image
double huP[7];
HuMoments(momentP, huP);
Mat testMat(1, 7, CV_32FC1, huP); //setting the hu moments to the test matrix
double resp = svm->predict(testMat); //pretiction of the SVM
printf("%f", resp); //Response
getchar();
}
我知道程序在该行之前是 运行 正常的,因为我打印了 labelsMat
和 trainingDataMat
并且其中的值是正确的。即使在控制台中,我也可以看到该程序 运行 正常,直到执行该行为止。然后控制台显示此消息:
OpenCV error: Bad argument (in the case of classification problem the responses must be categorical; either specify varType when creating TrainDatam or pass integer responses)
我真的不知道这是什么意思。知道什么可能导致问题吗?如果您需要任何其他详细信息,请告诉我。
编辑
对于未来的读者:
问题出在我将 labels
数组定义为浮点数组,将 LabelsMat
定义为 CV_32FC1
的垫子的方式。包含标签的数组需要在里面有整数,所以我改变了:
float labels[12];
至
int labels[12];
也变了
Mat labelsMat(12, 1, CV_32FC1, labels);
至
Mat labelsMat(12, 1, CV_32SC1, labels);
这解决了错误。谢谢
正在尝试更改:
Mat labelsMat(12, 1, CV_32FC1, labels);
到
Mat labelsMat(12, 1, CV_32SC1, labels);
发件人:http://answers.opencv.org/question/63715/svm-java-opencv-3/
如果这不起作用,希望其中一篇帖子能对您有所帮助:
Opencv 3.0 SVM train classification issues
我正在学习 SVM,所以我正在制作一个示例程序来训练 SVM 来检测符号是否在图像中。所有图像都是黑白的(符号为黑色,背景为白色)。我有 12 个训练图像,6 个正片(带有符号)和 6 个负片(没有它)。我使用 hu moments
来获取每个图像的描述符,然后我用这些描述符构建训练矩阵。我还有一个 Labels
矩阵,其中包含每个图像的标签:如果是正数则为 1,如果是负数则为 0。但是我在训练 SVM 的那一行遇到了一个错误(类似于分段错误)。这是我的代码:
using namespace cv;
using namespace std;
int main(int argc, char* argv[])
{
//arrays where the labels and the features will be stored
float labels[12] ;
float trainingData[12][7] ;
Moments moment;
double hu[7];
//===============extracting the descriptos for each positive image=========
for ( int i = 0; i <= 5; i++){
//the images are called t0.png ... t5.png and are in the folder train
std::string path("train/t");
path += std::to_string(i);
path += ".png";
Mat input = imread(path, 0); //read the images
bitwise_not(input, input); //invert black and white
Mat BinaryInput;
threshold(input, BinaryInput, 100, 255, cv::THRESH_BINARY); //apply theshold
moment = moments(BinaryInput, true); //calculate the moments of the current image
HuMoments(moment, hu); //calculate the hu moments (this will be our descriptor)
//setting the row i of the training data as the hu moments
for (int j = 0; j <= 6; j++){
trainingData[i][j] = (float)hu[j];
}
labels[i] = 1; //label=1 because is a positive image
}
//===============extracting the descriptos for each negative image=========
for (int i = 0; i <= 5; i++){
//the images are called tn0.png ... tn5.png and are in the folder train
std::string path("train/tn");
path += std::to_string(i);
path += ".png";
Mat input = imread(path, 0); //read the images
bitwise_not(input, input); //invert black and white
Mat BinaryInput;
threshold(input, BinaryInput, 100, 255, cv::THRESH_BINARY); //apply theshold
moment = moments(BinaryInput, true); //calculate the moments of the current image
HuMoments(moment, hu); //calculate the hu moments (this will be our descriptor)
for (int j = 0; j <= 6; j++){
trainingData[i + 6][j] = (float)hu[j];
}
labels[i + 6] = 0; //label=0 because is a negative image
}
//===========================training the SVM================
//we convert the labels and trainingData matrixes to Mat objects
Mat labelsMat(12, 1, CV_32FC1, labels);
Mat trainingDataMat(12, 7, CV_32FC1, trainingData);
//create the SVM
Ptr<ml::SVM> svm = ml::SVM::create();
//set the parameters of the SVM
svm->setType(ml::SVM::C_SVC);
svm->setKernel(ml::SVM::LINEAR);
CvTermCriteria criteria = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);
svm->setTermCriteria(criteria);
//Train the SVM !!!!!HERE OCCURS THE ERROR!!!!!!
svm->train(trainingDataMat, ml::ROW_SAMPLE, labelsMat);
//Testing the SVM...
Mat test = imread("train/t1.png", 0); //this should be a positive test
bitwise_not(test, test);
Mat testBin;
threshold(test, testBin, 100, 255, cv::THRESH_BINARY);
Moments momentP = moments(testBin, true); //calculate the moments of the test image
double huP[7];
HuMoments(momentP, huP);
Mat testMat(1, 7, CV_32FC1, huP); //setting the hu moments to the test matrix
double resp = svm->predict(testMat); //pretiction of the SVM
printf("%f", resp); //Response
getchar();
}
我知道程序在该行之前是 运行 正常的,因为我打印了 labelsMat
和 trainingDataMat
并且其中的值是正确的。即使在控制台中,我也可以看到该程序 运行 正常,直到执行该行为止。然后控制台显示此消息:
OpenCV error: Bad argument (in the case of classification problem the responses must be categorical; either specify varType when creating TrainDatam or pass integer responses)
我真的不知道这是什么意思。知道什么可能导致问题吗?如果您需要任何其他详细信息,请告诉我。
编辑
对于未来的读者:
问题出在我将 labels
数组定义为浮点数组,将 LabelsMat
定义为 CV_32FC1
的垫子的方式。包含标签的数组需要在里面有整数,所以我改变了:
float labels[12];
至
int labels[12];
也变了
Mat labelsMat(12, 1, CV_32FC1, labels);
至
Mat labelsMat(12, 1, CV_32SC1, labels);
这解决了错误。谢谢
正在尝试更改:
Mat labelsMat(12, 1, CV_32FC1, labels);
到
Mat labelsMat(12, 1, CV_32SC1, labels);
发件人:http://answers.opencv.org/question/63715/svm-java-opencv-3/
如果这不起作用,希望其中一篇帖子能对您有所帮助:
Opencv 3.0 SVM train classification issues