How to insert KeyPoints in MatOfKeyPoints - java

How do I build up a MatOfKeyPoint correctly?
My code so far is:
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
String sourcePath = path;
Features2d features2d = new Features2d();
Mat srcImgMat = Highgui.imread(sourcePath);
MatOfKeyPoint mat = new MatOfKeyPoint(srcImgMat);
Now I have some KeyPoints that I create and its position.
KeyPoint tempKeypoint = new KeyPoint();
But I can't insert them in the mat because the methode put doesn't support such type. What can I do?

Related

Why ORB does not find keypoints

Im trying to merge two images but ORB does not find keypoints. This is just an example using the same image, dark points are caused by acquisition and are not good reference points so I apply a mask to avoid them. The problem is that no keypoints are detected if black points are masked and I wonder what the problem is.
final ORB orb = ORB.create(100);
MatOfKeyPoint keypoints = new MatOfKeyPoint();
Mat descriptors = new Mat();
final Mat ones = Mat.ones(426, 195, CV_8U);
orb.detectAndCompute(draw, zeroMask, keypoints, descriptors);
MatOfKeyPoint keypoints2 = new MatOfKeyPoint();
Mat descriptors2 = new Mat();
final List<KeyPoint> keyPoints = keypoints.toList();
orb.detectAndCompute(draw, zeroMask, keypoints2, descriptors2);
final DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);
final MatOfDMatch matches = new MatOfDMatch();
matcher.match(descriptors, descriptors2, matches);
final Mat links = new Mat();
final MatOfByte ones1 = new MatOfByte();
org.opencv.features2d.Features2d.drawMatches(draw, keypoints, draw, keypoints2, matches, links, new Scalar(0), new Scalar(0), ones1);

Android : OpenCv comparing two images issue

I want to compare two image in percent in android , here is my codes
Mat img1 = Highgui.imread("storage/external_SD/a.png");
Mat img2 = Highgui.imread("storage/external_SD/b.png");
MatOfKeyPoint keypoints1 = new MatOfKeyPoint();
MatOfKeyPoint keypoints2 = new MatOfKeyPoint();
Mat descriptors1 = new Mat();
Mat descriptors2 = new Mat();
//Definition of ORB keypoint detector and descriptor extractors
FeatureDetector detector = FeatureDetector.create(FeatureDetector.ORB);
DescriptorExtractor extractor = DescriptorExtractor.create(DescriptorExtractor.ORB);
//Detect keypoints
detector.detect(img1, keypoints1);
detector.detect(img2, keypoints2);
//Extract descriptors
extractor.compute(img1, keypoints1, descriptors1);
extractor.compute(img2, keypoints2, descriptors2);
//Definition of descriptor matcher
DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);
//Match points of two images
MatOfDMatch matches = new MatOfDMatch();
matcher.match(descriptors1,descriptors2 ,matches);
For example my method out put should be :
Images is 90% same
But i dont know what should i do after matcher.match(descriptors1,descriptors2 ,matches); method, can you please advise me ?
As I remember method match() must return value of double or float.
I did same thing with face comparison and I did (according to your case):
double value = matcher.match(descriptors1,descriptors2 ,matches);
There are 2 similar questions around this. Check it out. Must be useful.
OpenCV filtering ORB matches
OpenCV - Java - No match with 2 opposite images using DescriptorMatcher

Display Keypoints on Image in Android - OpenCV

I'm trying display a image with keypoints detected. In my code, i get a list of key points, my i can't display the image on screen. I think that my problem is on converting the image to bitmap from MAT.
What i'm doing wrong ?
Here is my code:
Mat teste = new Mat();
Mat mRgba = teste.clone();
Mat outputMat = new Mat();
BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
Bitmap bitmap = drawable.getBitmap();
Utils.bitmapToMat(bitmap, teste);
MatOfKeyPoint myKeyPoints = new MatOfKeyPoint();
FeatureDetector orb = FeatureDetector.create(FeatureDetector.ORB);
orb.detect(teste, myKeyPoints);
List<KeyPoint> referenceKeypointsList =
myKeyPoints.toList();
Imgproc.cvtColor(teste, mRgba, Imgproc.COLOR_RGBA2RGB,4);
Features2d.drawKeypoints(mRgba, myKeyPoints, mRgba, new Scalar(2,254,255), Features2d.DRAW_RICH_KEYPOINTS);
Imgproc.cvtColor(mRgba, outputMat, Imgproc.COLOR_RGB2RGBA);
Utils.matToBitmap(outputMat, bitmap);
imageView.setImageBitmap(bitmap);
Look my code. It works fine
int whichDescriptor = siftDescriptor; //freakDescriptor;
// Features SEARCH
int detectorType = FeatureDetector.SIFT;
FeatureDetector detector = FeatureDetector.create(detectorType);
Mat mask = new Mat();
MatOfKeyPoint keypoints = new MatOfKeyPoint();
detector.detect(image, keypoints , mask);
if (!detector.empty()){
// Draw kewpoints
Mat outputImage = new Mat();
Scalar color = new Scalar(0, 0, 255); // BGR
int flags = Features2d.DRAW_RICH_KEYPOINTS; // For each keypoint, the circle around keypoint with keypoint size and orientation will be drawn.
Features2d.drawKeypoints(image, keypoints, outputImage, color , flags);
displayImage(Mat2BufferedImage(outputImage), "Feautures_"+detectorType);
}
displayImage() and Mat2BufferedImage() are referenced here
link1
or link2

SVM prediction of images OpenCV

I'm able to train the system but when I try to predict, Bad argument exception is raised.
OpenCV Error: Bad argument (The sample is not a valid vector) in cvPreparePredictData, file ........\opencv\modules\ml\src\inner_functions.cpp, line 1099
Exception in thread "main" CvException [org.opencv.core.CvException: cv::Exception: ........\opencv\modules\ml\src\inner_functions.cpp:1099: error: (-5) The sample is not a valid vector in function cvPreparePredictData
]
This is my code:
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat classes = new Mat();
Mat trainingData = new Mat();
Mat trainingImages = new Mat();
Mat trainingLabels = new Mat();
CvSVM clasificador;
String path="C:\\java workspace\\ora\\images\\Color_Happy_jpg";
for (File file : new File(path).listFiles()) {
Mat img=new Mat();
Mat con = Highgui.imread(path+"\\"+file.getName(),Highgui.CV_LOAD_IMAGE_GRAYSCALE);
con.convertTo(img, CvType.CV_32FC1,1.0/255.0);
img.reshape(1, 1);
trainingImages.push_back(img);
trainingLabels.push_back(Mat.ones(new Size(1, 75), CvType.CV_32FC1));
}
System.out.println("divide");
path="C:\\java workspace\\ora\\images\\Color_Sad_jpg";
for (File file : new File(path).listFiles()) {
Mat img=new Mat();
Mat m=new Mat(new Size(640,480),CvType.CV_32FC1);
Mat con = Highgui.imread(file.getAbsolutePath(),Highgui.CV_LOAD_IMAGE_GRAYSCALE);
con.convertTo(img, CvType.CV_32FC1,1.0/255.0);
img.reshape(1, 1);
trainingImages.push_back(img);
trainingLabels.push_back(Mat.zeros(new Size(1, 75), CvType.CV_32FC1));
}
trainingLabels.copyTo(classes);
CvSVMParams params = new CvSVMParams();
params.set_kernel_type(CvSVM.LINEAR);
CvType.typeToString(trainingImages.type());
CvSVM svm=new CvSVM();
clasificador = new CvSVM(trainingImages,classes, new Mat(), new Mat(), params);
clasificador.save("C:\\java workspace\\ora\\images\\svm.xml");
Mat out=new Mat();
clasificador.load("C:\\java workspace\\ora\\images\\svm.xml");
Mat sample=Highgui.imread("C:\\java workspace\\ora\\images\\Color_Sad_jpg\\EMBfemale20-2happy.jpg",Highgui.CV_LOAD_IMAGE_GRAYSCALE);
sample.convertTo(out, CvType.CV_32FC1,1.0/255.0);
out.reshape(1, 75);
System.out.println(clasificador.predict(out));
1.
your trainLabels are still wrong.
you need a float mat with numrows==numimages and 1 col. so, 1 label per image.
so your sad faces should have :
trainingLabels.push_back(-1.0);
and your happy ones should have :
trainingLabels.push_back(1.0);
2.
the sample for the prediction has to be processed in the same way as for the training.
sample.convertTo(out, CvType.CV_32FC1,1.0/255.0);
out.reshape(1, 1);

Watershed in Opencv Android

I was trying to implement watershed function from OpenCV on Android. However my program always crashed at the place where watershed function is called. I can output the marker's result perfectly fine. But the watershed function always just crashes. Here is my code:
Mat threeChannel = new Mat();
Imgproc.cvtColor(mRgba, threeChannel, Imgproc.COLOR_BGR2GRAY);
Imgproc.threshold(threeChannel, threeChannel, 100, 255, Imgproc.THRESH_BINARY);
Mat fg = new Mat(mRgba.size(),CvType.CV_8U);
Imgproc.erode(threeChannel,fg,new Mat(),new Point(-1,-1),2);
Mat bg = new Mat(mRgba.size(),CvType.CV_8U);
Imgproc.dilate(threeChannel,bg,new Mat(),new Point(-1,-1),3);
Imgproc.threshold(bg,bg,1, 128,Imgproc.THRESH_BINARY_INV);
Mat markers = new Mat(mRgba.size(),CvType.CV_8U, new Scalar(0));
Core.add(fg, bg, markers);
WatershedSegmenter segmenter = new WatershedSegmenter();
segmenter.setMarkers(markers);
Mat result = segmenter.process(mRgba);
return result;
WatershedSegmenter calss is as follows:
public class WatershedSegmenter{
public Mat markers;
public void setMarkers(Mat markerImage)
{
markerImage.convertTo(markers, CvType.CV_32S);
}
public Mat process(Mat image)
{
Imgproc.watershed(image, markers);
markers.convertTo(markers,CvType.CV_8U);
return markers;
}
}
Has anybody managed to get this working on Android before? I managed to get it to work in C++ with Qt before following this tutorial: link. However I haven't got any luck on Android at the moment.
I found out the reason of crash now. watershed is taking a 8 bit 3 channel format of data, and RGBA is a 4 channel data. I just convert it from RGBA to RGB, and it solved all the issues.
Your Mat doesn't match the correct .depth() and/or .channel().
The first step is to double-check each Mat has the type you think it does by using the myMat.depth() and myMat.channels() functions. The function watershed uses two Mat arguments. The first should be an 8-bit, 3-channel image, and the second should be a 32-bit single-channel image.
If they are not the right kind of image, use cvtColor to convert from what you have to what you need.
Try out this solution
BitmapFactory.Options o = new BitmapFactory.Options();
o.inDither = false;
o.inSampleSize=4;
int width , height ;
width = src_Bitmap.getWidth();
height = src_Bitmap.getHeight();
Mat rgba = new Mat();
Mat gray_mat= new Mat();
Mat threeChannel = new Mat();
Utils.bitmapToMat(src_Bitmap,gray_mat);
Imgproc.cvtColor(gray_mat,rgba , Imgproc.COLOR_RGBA2RGB);
Imgproc.cvtColor(rgba, threeChannel, Imgproc.COLOR_RGB2GRAY);
Imgproc.threshold(threeChannel, threeChannel, 100, 255, Imgproc.THRESH_OTSU);
Mat fg = new Mat(rgba.size(),CvType.CV_8U);
Imgproc.erode(threeChannel,fg,new Mat(),new Point(-1,-1),2);
Mat bg = new Mat(rgba.size(),CvType.CV_8U);
Imgproc.dilate(threeChannel,bg,new Mat(),new Point(-1,-1),3);
Imgproc.threshold(bg,bg,1, 128,Imgproc.THRESH_BINARY_INV);
Mat markers = new Mat(rgba.size(),CvType.CV_8U, new Scalar(0));
Core.add(fg, bg, markers);
// Start the WaterShed Segmentation :
Mat marker_tempo = new Mat();
markers.convertTo(marker_tempo, CvType.CV_32S);
Imgproc.watershed(rgba, marker_tempo);
marker_tempo.convertTo(markers,CvType.CV_8U);
result_Bitmap=Bitmap.createBitmap(width,height,Bitmap.Config.RGB_565);
Imgproc.applyColorMap( markers, markers,4 );
Utils.matToBitmap( markers,result_Bitmap);
myImageView.setImageBitmap(result_Bitmap);

Categories

Resources