I am trying to use an SVM in Android using OpenCV's Android SDK. Everything seems to work correctly besides the predict() function.
I get the following error:
svm CvException error: (-215) samples.cols == var_count && samples.type() == CV_32F
in function virtual float cv::ml::SVMImpl::predict(cv::InputArray, cv::OutputArray, int) const
]
I am rather certain that the dimensions and types are correct, but I have a feeling I am overlooking something simple. Below is the description of my code with the relevant code.
I have 60 training examples with 150 features each. All examples and labels are in a 2D float array of dimension 60x151 called dataset_2Darr
. The right-most column has the labels stored as -1, 0, +1 for the three classes.
I first place the 60x150 sub-matrix in the Mat
object X
.
Then, I place the labels in the 60x1 Mat
object Y
.
X is float - CV_ 32FC1
Y is int - CV_32SC1
The relevant code is executed in 3 parts of the overall program. Here are the three parts:
Part 1: Global Variables in top of MainActivity.java:
static int M = 60; // Rows - examples
static int N = 150; // Cols - features
public static Mat X; // Data
public static Mat Y; // Labels
// Instantiate SVM object globally
static SVM classifier = SVM.create();
Part 2: Inside OnCreate():
// SVM Stuff:
classifier.setKernel(SVM.LINEAR);
classifier.setType(SVM.C_SVC);
classifier.setGamma(0.5);
classifier.setNu(0.5);
classifier.setC(1);
//classifier.setTermCriteria(criteria);
// Dataset stuff:
Y = new Mat(new Size(1,M),CvType.CV_32SC1); // Integer {-1, 0, +1}
int Y_rows = Y.rows(); // 60
int Y_cols = Y.cols(); // 1
X = new Mat(new Size(N,M),CvType.CV_32FC1); // Float
int X_rows = X.rows(); // 60
int X_cols = X.cols(); // 150
Part 3: Inside method that executes code:
for (int i=0; i < 60; i++) {
for(int j=0; j < 150; j++) {
X.put(i, j, dataset_2Darr[i][j]); // Copy 2D array into mat object
}
}
// Iterate down rows of right-most column
for (int i = 0; i < 60; ++i)
Y.put(i,0, (int)dataset_2Darr[i][150]); // Copy right most column into label array
// Train the model using X and Y
classifier.train(X, Ml.ROW_SAMPLE, Y);
// Create 1x150 feature vector to test:
Mat x = new Mat(new Size(150, 1),CvType.CV_32FC1); // Float
int x_rows = x.rows(); // 1
int x_cols = x.cols(); // 150
// Place dummy values inside matrix x
for (int i = 0; i < 150; i++) {
x.put(0, i, 0.2f);
}
//Mat outMat = new Mat();
//float response = classifier.predict(x, outMat, 0);
float prediction = classifier.predict(x);