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
Related
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);
I am trying to extract contours objects from this:
Which is the S component of a HSV image obtained from this:
My code:
Mat hsvImage = new Mat();
Imgproc.cvtColor(image, hsvImage, Imgproc.COLOR_BGR2HSV);
List<Mat> images = new ArrayList<>();
Core.split(hsvImage, images);
Mat blur = new Mat();
Imgproc.medianBlur(images.get(1), blur, 1);
Mat thresh = new Mat();
Imgproc.threshold(blur, thresh, 40, 255, Imgproc.THRESH_BINARY);
List<MatOfPoint> contours = new ArrayList<>();
Imgproc.findContours(thresh, contours, new Mat(), Imgproc.RETR_LIST,
Imgproc.CHAIN_APPROX_NONE);`
Results are not bad, but I need to improve detection.
I would like to remove image background, but I don't know if is possible and how. Any suggestion would be appreciated.
I am trying to slice (crop) part of my image to another so it can be worked on separately. I have found contours and now trying to save every contour in new Mat but it is giving error
Mat crop;
Imgproc.findContours(m, contours, new Mat() ,Imgproc.RETR_EXTERNAL , Imgproc.CHAIN_APPROX_SIMPLE);
for(int i=0; i <contours.size();i++)
{
Rect rect = Imgproc.boundingRect(contours.get(i));
crop = m.submat(rect);
}
Utils.matToBitmap(crop, bm);
ImageView iv = (ImageView) findViewById(R.id.imageView1);
iv.setImageBitmap(bm);
Here m is my Mat where image is saved
Error:
What I always do in this situation is to create a new mat using the constructor with a rect:
Mat cropped = new Mat(mOriginal, boudingRect);
Edit:
Your bitmap should also have the same size:
bm = Bitmap.createBitmap(crop.size().width,crop.size().height, Bitmap.Config.ARGB_8888);
After cropping an image how can I resize it?
Mat croppedimage = cropImage( image, rect );
Mat resizeimage = croppedimage.resize( any dimension ); //need to change this line
I think, you want this.
e.g.
Mat croppedimage = cropImage(image,rect);
Mat resizeimage = new Mat();
Size sz = new Size(100,100);
Imgproc.resize( croppedimage, resizeimage, sz );
If you want to scale an image using OpenCV java then do the following:
import static org.opencv.imgproc.Imgproc.*;
import static org.opencv.imgcodecs.Imgcodecs.imread;
Main code:
Mat src = imread("imageName.jpg");
Mat resizeimage = new Mat();
Size scaleSize = new Size(300,200);
resize(src, resizeimage, scaleSize , 0, 0, INTER_AREA);
For downscaling it is recommended to use: INTER_AREA and for upscaling use INTER_CUBIC
For more details: OpenCV Ref for Resize
Please read manual for c++ method Resize it's the same to java.
You can choose a type of interpolation. In some cases it's important for a best result.
Mat croppedImage = cropImage(image,rect);
Mat resizeImage = new Mat(anyHeight, anyWidth, croppedImage.type());
int interpolation = Imgproc.INTER_CUBIC;
Imgproc.resize(croppedImage, resizeImage, resizeImage.size(), 0, 0, interpolation );
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);