C++ OpenCV SVM 预测不工作

C++ OpenCV SVM Predict Not Working

正在尝试创建功能 SVM。我有 114 张训练图像、60 张 Positive/54 负片和 386 张测试图像供 SVM 进行预测。

我读入训练图像特征 float 是这样的:

trainingDataFloat[i][0] = trainFeatures.rows;
trainingDataFloat[i][1] = trainFeatures.cols;

测试图像也一样:

testDataFloat[i][0] = testFeatures.rows;
testDataFloat[i][2] = testFeatures.cols;

然后,使用 Micka 的 ,我将 testDataFloat 变成一维数组,然后像这样将它提供给 Mat,以便预测 SVM:

float* testData1D = (float*)testDataFloat;
Mat testDataMat1D(height*width, 1, CV_32FC1, testData1D);
float testPredict = SVMmodel.predict(testDataMat1D);

一切就绪后,出现调试错误:

cvPreparePredictData

中输入参数的大小不匹配(样本大小与用于训练的样本大小不同)

查看 this post 我发现(感谢 berak):

"all images (used in training & prediction) have to be the same size"

所以我加入了一个 re-size 函数,可以 re-size 图像以任何你想要的大小都是方形的 (100x100, 200x200, 1000, 1000 etc.)

运行 再次将图像 re-sized 复制到程序现在从中加载图像的新目录,我得到与之前完全相同的错误:

cvPreparePredictData

中输入参数的大小不匹配(样本大小与用于训练的样本大小不同)

我只是不知道该怎么做。为什么它仍然抛出该错误?

编辑

我变了

Mat testDataMat1D(TestDFheight*TestDFwidth, 1, CV_32FC1, testData1D);

Mat testDataMat1D(1, TestDFheight*TestDFwidth, CV_32FC1, testData1D);

并将 .predict 放在 featuresfloat 的循环中,这样每张图像都会单独给 .predict 因为 this question。随着 int 的交换,.cols = 1 和 .rows = TestDFheight*TestDFwidth 程序似乎实际上是 运行,但随后停在图像 160(.exe has stopped working)...所以这是一个新问题。

编辑 2

添加了一个简单的

std::cout << testPredict;

查看 SVM 的确定输出,它似乎正匹配所有内容,直到图像 160,它停止 运行ning:

请检查您的训练和测试特征向量。

我假设您的要素数据是某种形式的 cv::Mat,每行都包含要素。 在这种情况下,您希望训练矩阵是每个图像的每个特征矩阵的串联。 这些行看起来不正确:

trainingDataFloat[i][0] = trainFeatures.rows;
trainingDataFloat[i][1] = trainFeatures.cols;

这是将二维矩阵的一个元素设置为 trainFeatures 中的行数和列数。这与 trainFeatures 矩阵中的实际数据无关。

你想检测什么?如果每张图片都是正面和负面的例子,那么你是否试图检测图像中的某些东西?你有什么特点?

如果您尝试在每个图像的基础上检测图像中的对象,那么您需要一个特征向量来描述一个向量中的整个图像。在这种情况下,你会用你的训练数据做这样的事情:

int N; // Set to number of images you plan on using for training
int feature_size; // Set to the number of features extracted in each image.  Should be constant across all images.

cv::Mat X = cv::Mat::zeros(N, feature_size, CV_32F); // Feature matrix
cv::Mat Y = cv::Mat::zeros(N, 1, CV_32F); // Label vector
// Now use a for loop to copy data into X and Y, Y = +1 for positive examples and -1 for negative examples
for(int i = 0; i < trainImages.size(); ++i)
{
  X.row(i) = trainImages[i].features; // Where features is a cv::Mat row vector of size N of the extracted features
  Y.row(i) = trainImages[i].isPositive ? 1:-1; 
}
// Now train your cv::SVM on X and Y.