How to use KNearest in java?
Hi! I don't know how to use KNearest in OpenCV 3.0 in java. I really can't find any documentation in java. Can someone help me? Thanks in advance!
Hi! I don't know how to use KNearest in OpenCV 3.0 in java. I really can't find any documentation in java. Can someone help me? Thanks in advance!
for opencv machinelearning you will have to convert your features to float, and flatten them int o a single row per feature. then you stack your features into a single huge Mat, and build a response/labels Mat with one number (the label/id) per feature row:
[data] [labels]
feature1 1
feature2 1
feature3 2
feature4 2
feature5 1
...
the layout will be either ROW_SAMPLE (most commonly used) or COL_SAMPLE
here's some code to try:
import org.opencv.core.*;
import org.opencv.imgproc.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.ml.*;
import org.opencv.utils.*;
import java.util.*;
class SimpleSample {
static{ System.loadLibrary(Core.NATIVE_LIBRARY_NAME); }
public static void main(String[] args) {
// samples/data/digits.png, have a look at it.
Mat digits = Imgcodecs.imread("digits.png", 0);
// setup train/test data:
Mat trainData = new Mat(),
testData = new Mat();
List<Integer> trainLabs = new ArrayList<Integer>(),
testLabs = new ArrayList<Integer>();
// 10 digits a 5 rows:
for (int r=0; r<50; r++) {
// 100 digits per row:
for (int c=0; c<100; c++) {
// crop out 1 digit:
Mat num = digits.submat(new Rect(c*20,r*20,20,20));
// we need float data for knn:
num.convertTo(num, CvType.CV_32F);
// 50/50 train/test split:
if (c % 2 == 0) {
// for opencv ml, each feature has to be a single row:
trainData.push_back(num.reshape(1,1));
// add a label for that feature (the digit number):
trainLabs.add(r/5);
} else {
testData.push_back(num.reshape(1,1));
testLabs.add(r/5);
}
}
}
// make a Mat of the train labels, and train knn:
KNearest knn = KNearest.create();
knn.train(trainData, Ml.ROW_SAMPLE, Converters.vector_int_to_Mat(trainLabs));
// now test predictions:
for (int i=0; i<testData.rows(); i++)
{
Mat one_feature = testData.row(i);
int testLabel = testLabs.get(i);
Mat res = new Mat();
float p = knn.findNearest(one_feature, 1, res);
System.out.println(testLabel + " " + p + " " + res.dump());
}
//// hmm, the 'real world' test case probably looks more like this:
//// make sure, you follow the very same preprocessing steps used in the train phase:
// Mat one_feature = Imgcodecs.imread("one_digit.png", 0);
// Mat feature; one_feature.convertTo(feature, CvTypes.CV_32F);
// Imgproc.resize(feature, feature, Size(20,20));
// int predicted = knn.findNearest(feature.reshape(1,1), 1);
}
}
Could you please include the link for the used picture ?
@j0hnd3v -- no. it needs a single Mat with consecutive data.
(but ofc. you can collect your data into a list, and convert to Mat for training, if that's easier for you)
Asked: 2016-03-11 05:34:47 -0600
Seen: 4,015 times
Last updated: Mar 13 '16
Unresolved inclusion in OpenCV+Android tutorial
How to convert Floating point image to 32-bit single-channel?
How to translate this to Java?
android: how to put a column into Mat
OpenCV Tutorial 1 - Add OpenCV on API 8
Running the OpenCV4Android application on my PC
Using OpenCV as a stress detector
have a look at the docs , try a bit, and come back with more specific problems ?
As you can see java documentation doesn't say much. However I have to detect digits, I can't use third part libraries so I can't use OCR like tesseract or similar. I have 500 image samples for each digit (size 20x20) and I should want to use them to train my KNearest object. I have to use the method:
1) But in which format should I put my samples Mat? And what int layout stay for? Then if I understand I have to use the method:
2) In this function my Mat samples is the Mat responses of train function, right? But in which format will be my Mat results? Thanks in advance for your answers and sorry for my English^^