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);
Related
I am using OpenCV to detect the similarities between two images. Unfortunately, my line of code that converts my Mat back to a bitmap is causing my app to crash. Does anyone have any ideas what would be causing this? Here is my code:
Bitmap centerBit = BitmapFactory.decodeResource(getResources(), R.drawable.center);
Mat center = new Mat();
Utils.bitmapToMat(centerBit,center);
Mat resultCenter = new Mat();
Imgproc.matchTemplate(center,center,resultCenter,Imgproc.TM_SQDIFF_NORMED);
Bitmap bm = Bitmap.createBitmap(resultCenter.cols(), resultCenter.rows(),Bitmap.Config.ARGB_8888);
Utils.matToBitmap(resultCenter, bm); //THIS LINE CAUSING APP TO CRASH
ImageView iv = (ImageView) findViewById(R.id.imageView);
iv.setImageBitmap(bm);
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
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);
I want to rotate an overlay item (a drawable) according to my bearing onLocationChanged. How do I do this? I tried with the drawable, with the itemizedOverlay, and with the overlayItem, but no success.
public void bearingRotation(float boatBearing){
Bitmap bm = ((BitmapDrawable)drawableCurrPos).getBitmap();
Matrix mat = new Matrix();
mat.postRotate(boatBearing);
Bitmap bMapRotate = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),bm.getHeight(), mat, true);
drawableCurrPos = new BitmapDrawable(bMapRotate);
}
I would suggest that you convert that drawable to bitmap.
Bitmap bm = ((BitmapDrawable)drawable).getBitmap();
Matrix mat = new Matrix();
mat.postRotate(90);
Bitmap bMapRotate = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),bm.getHeight(), mat, true);
Convert this bMapRotate using BitmapDrawable and apply that as a pin pointer to your location.