使用 SVM 在 SUV 和轿车之间进行分类
Using SVMs to classify between SUVs and sedans
我正在尝试使用 OpenCV 实现支持向量机,对轿车和 SUV 的图像进行分类。我大量引用了这个 post:using OpenCV and SVM with images
我有 29 张轿车和 SUV 的训练图像,我将每张图像拉伸成 1 个非常长的行,从而使我的训练垫大小为 29ximage_area。下图显示 training_mat 全部为白色,我不确定这是否正确,可能会影响我的结果。
这可能是因为 training_mat 是浮点类型。例如,如果将 training_mat 更改为 CV_8UC1,我可以清楚地看到每个图像都在 training_mat 中展开,但是 svm->train 函数不接受 training_mat.
我使用 labels_mat 作为实施的监督版本。 1 表示 SUV,-1 表示轿车。在下图中,当我尝试使用 SVM 模型预测 SUV 时,我得到的值类似于 -800000000000。无论我做什么(更改参数、使用全白测试图像、全黑测试图像、将标签更改为仅 1 或 -1)我总是得到相同的 -80000000000 值。现在任何负面结果可能只意味着 -1(轿车)但我不能确定,因为它永远不会改变。如果有人对此有见解,我们将不胜感激
这是我的代码、结果,全白training_mat。
int num_train_images = 29; //29 images will be used to train the SVM
int image_area = 150 * 200;
Mat training_mat(num_train_images, image_area, CV_32FC1); // Creates a 29 rows by 30000 columns... 29 150x200 images will be put into 1 row per image
//Converts 29 2D images into a really long row per image
for (int file_count = 1; file_count < (num_train_images + 1); file_count++)
{
ss << name << file_count << type; //'Vehicle_1.jpg' ... 'Vehicle_2.jpg' ... etc ...
string filename = ss.str();
ss.str("");
Mat training_img = imread(filename, 0); //Reads the training images from the folder
int ii = 0; //Scans each column
for (int i = 0; i < training_img.rows; i++)
{
for (int j = 0; j < training_img.cols; j++)
{
training_mat.at<float>(file_count - 1, ii) = training_img.at<uchar>(i, j); //Fills the training_mat with the read image
ii++;
}
}
}
imshow("Training Mat", training_mat);
waitKey(0);
//Labels are used as the supervised learning portion of the SVM. If it is a 1, its an SUV test image. -1 means a sedan.
int labels[29] = { 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1 };
//Place the labels into into a 29 row by 1 column matrix.
Mat labels_mat(num_train_images, 1, CV_32S);
cout << "Beginning Training..." << endl;
//Set SVM Parameters (not sure about these values)
Ptr<SVM> svm = SVM::create();
svm->setType(SVM::C_SVC);
svm->setKernel(SVM::RBF);
svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));
svm->setGamma(1);
svm->setDegree(3);
cout << "Parameters Set..." << endl;
svm->train(training_mat, ROW_SAMPLE, labels_mat);
cout << "End Training" << endl;
waitKey(0);
Mat test_image(1, image_area, CV_32FC1); //Creates a 1 x 1200 matrix to house the test image.
Mat SUV_image = imread("SUV_1.jpg", 0); //Read the file folder
int jj = 0;
for (int i = 0; i < SUV_image.rows; i++)
{
for (int j = 0; j < SUV_image.cols; j++)
{
test_image.at<float>(0, jj) = SUV_image.at<uchar>(i, j); //Fills the training_mat
jj++;
}
}
//Should return a 1 if its an SUV, or a -1 if its a sedan
float result = svm->predict(test_image);
if (result < 0)
cout << "Sedan" << endl;
else
cout << "SUV" << endl;
cout << "Result: " << result << endl;
namedWindow("Test Image", CV_WINDOW_NORMAL);
imshow("Test Image", SUV_image);
waitKey(0);
参考这个 post 来解决我遇到的这个问题。
在这里,我使用 HOG 特征而不是图像的纯像素值。 training_mat 不再是白色,分类器运行良好。此外,输出结果为 1 或 -1。
我正在尝试使用 OpenCV 实现支持向量机,对轿车和 SUV 的图像进行分类。我大量引用了这个 post:using OpenCV and SVM with images
我有 29 张轿车和 SUV 的训练图像,我将每张图像拉伸成 1 个非常长的行,从而使我的训练垫大小为 29ximage_area。下图显示 training_mat 全部为白色,我不确定这是否正确,可能会影响我的结果。
这可能是因为 training_mat 是浮点类型。例如,如果将 training_mat 更改为 CV_8UC1,我可以清楚地看到每个图像都在 training_mat 中展开,但是 svm->train 函数不接受 training_mat.
我使用 labels_mat 作为实施的监督版本。 1 表示 SUV,-1 表示轿车。在下图中,当我尝试使用 SVM 模型预测 SUV 时,我得到的值类似于 -800000000000。无论我做什么(更改参数、使用全白测试图像、全黑测试图像、将标签更改为仅 1 或 -1)我总是得到相同的 -80000000000 值。现在任何负面结果可能只意味着 -1(轿车)但我不能确定,因为它永远不会改变。如果有人对此有见解,我们将不胜感激
这是我的代码、结果,全白training_mat。
int num_train_images = 29; //29 images will be used to train the SVM
int image_area = 150 * 200;
Mat training_mat(num_train_images, image_area, CV_32FC1); // Creates a 29 rows by 30000 columns... 29 150x200 images will be put into 1 row per image
//Converts 29 2D images into a really long row per image
for (int file_count = 1; file_count < (num_train_images + 1); file_count++)
{
ss << name << file_count << type; //'Vehicle_1.jpg' ... 'Vehicle_2.jpg' ... etc ...
string filename = ss.str();
ss.str("");
Mat training_img = imread(filename, 0); //Reads the training images from the folder
int ii = 0; //Scans each column
for (int i = 0; i < training_img.rows; i++)
{
for (int j = 0; j < training_img.cols; j++)
{
training_mat.at<float>(file_count - 1, ii) = training_img.at<uchar>(i, j); //Fills the training_mat with the read image
ii++;
}
}
}
imshow("Training Mat", training_mat);
waitKey(0);
//Labels are used as the supervised learning portion of the SVM. If it is a 1, its an SUV test image. -1 means a sedan.
int labels[29] = { 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1 };
//Place the labels into into a 29 row by 1 column matrix.
Mat labels_mat(num_train_images, 1, CV_32S);
cout << "Beginning Training..." << endl;
//Set SVM Parameters (not sure about these values)
Ptr<SVM> svm = SVM::create();
svm->setType(SVM::C_SVC);
svm->setKernel(SVM::RBF);
svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));
svm->setGamma(1);
svm->setDegree(3);
cout << "Parameters Set..." << endl;
svm->train(training_mat, ROW_SAMPLE, labels_mat);
cout << "End Training" << endl;
waitKey(0);
Mat test_image(1, image_area, CV_32FC1); //Creates a 1 x 1200 matrix to house the test image.
Mat SUV_image = imread("SUV_1.jpg", 0); //Read the file folder
int jj = 0;
for (int i = 0; i < SUV_image.rows; i++)
{
for (int j = 0; j < SUV_image.cols; j++)
{
test_image.at<float>(0, jj) = SUV_image.at<uchar>(i, j); //Fills the training_mat
jj++;
}
}
//Should return a 1 if its an SUV, or a -1 if its a sedan
float result = svm->predict(test_image);
if (result < 0)
cout << "Sedan" << endl;
else
cout << "SUV" << endl;
cout << "Result: " << result << endl;
namedWindow("Test Image", CV_WINDOW_NORMAL);
imshow("Test Image", SUV_image);
waitKey(0);
参考这个 post 来解决我遇到的这个问题。
在这里,我使用 HOG 特征而不是图像的纯像素值。 training_mat 不再是白色,分类器运行良好。此外,输出结果为 1 或 -1。