convert Bitmap to Mat after capture image using android camera - android

Mat b = new Mat();
Bitmap bmp = getIntent().getExtras().getParcelable("image_send");
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_image);
Mat tmp = new Mat (bmp.getWidth(), bmp.getHeight(), CvType.CV_8UC1);
Utils.bitmapToMat(bmp, tmp);
Imgproc.cvtColor(tmp, tmp, Imgproc.COLOR_RGB2GRAY);
//Imgproc.cvtColor(tmp, tmp, Imgproc.COLOR_GRAY2RGB, 4);
Utils.matToBitmap(tmp, bmp);
iv = (ImageView) findViewById(R.id.imageView1);
iv.setImageBitmap(bmp);
}
Can't display the bmp. My app has stopped after taking a picture.

Utils.bitmapToMat converts an Android Bitmap to an OpenCV Mat. It requires a bitmap of type ARGB_8888 or RGB_565.
import org.opencv.android.Utils;
Mat mat = new Mat();
Bitmap bmp32 = bmp.copy(Bitmap.Config.ARGB_8888, true);
Utils.bitmapToMat(bmp32, mat);

Mat tmp = new Mat (bmp.getWidth(), bmp.getHeight(), CvType.CV_8UC1);
OpenCV Mat constructor expects rows, cols pair instead of width, height as its arguments, invert them.
Try:
Mat tmp = new Mat (bmp.getHeight(), bmp.getWidth(), CvType.CV_8UC1);

With Camera2 this task is very fast, only you need config the ImageReader with ImageFormat on YUV_420_888 and then proccess frames with OpenCV like this:
// You can read image with differents patterns for example grayscale:
Mat mGray(height, width, cv::IMREAD_GRAYSCALE, pFrameData);
A complete implementation in the next answer: https://stackoverflow.com/a/49331546/471690

Same problem with my app. In the main activity, I had to render OpenCV utilizable.
(I am assuming your app threw a link error when Mat library was used).
All sample apps do this. Include this your in main activity.
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
#Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
{
Log.i("OpenCVManager setup", "OpenCV loaded successfully");
//Use openCV libraries after this
} break;
default:
{
super.onManagerConnected(status);
} break;
}
}
};
#Override
public void onResume()
{
super.onResume();
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_9, this,
mLoaderCallback);
}

Related

How to have better results using Opencv Watershed algorithm in android?

I have an image composed of 3 objects and I need to extract those objects. I tried Watershed algorithm but it doesn't work as expected.
i don't have a good understanding of how this algorithm work so I can't figure out the real problem.
Here is my code
public Mat steptowatershed(Mat img)
{
Mat threeChannel = new Mat();
Imgproc.cvtColor(img, threeChannel, Imgproc.COLOR_BGR2GRAY);
Imgproc.threshold(threeChannel, threeChannel, 0, 255, Imgproc.THRESH_BINARY_INV + Imgproc.THRESH_OTSU);
Mat fg = new Mat(img.size(),CvType.CV_8U);
Imgproc.erode(threeChannel,fg,new Mat());
Mat bg = new Mat(img.size(),CvType.CV_8U);
Imgproc.dilate(threeChannel,bg,new Mat());
Imgproc.threshold(bg,bg,1, 128,Imgproc.THRESH_BINARY_INV);
Mat markers = new Mat(img.size(),CvType.CV_8U, new Scalar(0));
Core.add(fg, bg, markers);
Mat result1= new Mat();
Imgproc.cvtColor(img, img, Imgproc.COLOR_BGRA2BGR);
WatershedSegmenter segmenter = new WatershedSegmenter();
segmenter.setMarkers(markers);
result1 = segmenter.process(img);
return result1;
}
public class WatershedSegmenter
{
public Mat markers=new Mat();
public void setMarkers(Mat markerImage)
{
markerImage.convertTo(markers, CvType.CV_32SC1);
}
public Mat process(Mat image)
{
Imgproc.watershed(image,markers);
markers.convertTo(markers,CvType.CV_8U);
return markers;
}
}
Here is the original image
Here is the result image
I need the extract all 3 objects later.
I wish you guys help me solve this issue.

Why my application is crushing when i use openCv Mat

I am new in openCV android image Processing. but i am facing some problem. when i use openCV in android and i use Mat then my apps will crushed.... what is the problem with this.....
My code is here..:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageView img=(ImageView) findViewById(R.id.imageView);
Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.in);
Mat tmp = new Mat (b.getWidth(), b.getHeight(), CvType.CV_8UC1);
Utils.bitmapToMat(b, tmp);
Imgproc.cvtColor(tmp, tmp, Imgproc.COLOR_RGB2GRAY);
//there could be some processing
Imgproc.cvtColor(tmp, tmp, Imgproc.COLOR_GRAY2RGB, 4);
Utils.matToBitmap(tmp, b);
img.setImageBitmap(b);
}
There are multiple problems:
Mat constructor is Mat(height, width, type), you inverted height and width.
CV_8UC1 is a single channel (grayscale). So if it IS necessary to create the Mat in advance, you should create a Mat with appropriate number of channels. I assume you want to use a RGB image, so use CV_8UC3. But typically, functions re-allocate the Mat if the size doesn't fit. If that's the case with bitmapToMat too, then there is another problem.
Afaik, android uses RGBA as standard color-space. So PROBABLY after Utils.bitmapToMat(b, tmp); tmp is a 4 channel RGBA matrix. So please try Imgproc.cvtColor(tmp, tmp, Imgproc.COLOR_RGBA2GRAY); and later Imgproc.cvtColor(tmp, tmp, Imgproc.COLOR_GRAY2RGBA, 4); if you aren't sure you should add some checks like if Mat.channels isn't 3, don't try to convert RGB2GRAY if the check fails you can try to find out what the real number of channels is and why.

How to process an image with OpenCV onPictureTaken?

I've been trying to process an image as soon as the picture was taken i.e. in the onPictureTaken() callback. As it was to my understanding I should convert the byte array to an OpenCV matrix, but the entire app freezes when I try to do that. Basically all I did was this:
#Override
public void onPictureTaken(byte[] bytes, Camera camera) {
Log.w(TAG, "picture taken!");
if (bytes != null) {
Bitmap image = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Mat matImage = new Mat();
// This is where my app freezes.
Utils.bitmapToMat(image, matImage);
Log.w(TAG, matImage.dump());
}
mCamera.startPreview();
mCamera.setPreviewCallback(this);
}
Does anyone know why it freezes and how to solve it?
Note: I've used the OpenCV4Android tutorial 3 as a base.
Update 1: I've also tried to parste the bytes (without any success) as follows:
Mat mat = Imgcodecs.imdecode(
new MatOfByte(bytes),
Imgcodecs.CV_LOAD_IMAGE_UNCHANGED
);
Update 2: Supposedly this should work, it did not for me though.
Mat mat = new Mat(1, bytes.length, CvType.CV_8UC3);
mat.put(0, 0, bytes);
Nor did this variant:
Bitmap image = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Mat mat = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC1);
mat.put(0, 0, bytes);
Update 3: This did not work for me either:
Mat mat = new MatOfByte(bytes);
I've got some help of a colleague of mine. He managed to fix the problem by doing the following:
BitmapFactory.Options opts = new BitmapFactory.Options(); // This was missing.
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opts);
Mat mat = new Mat();
Utils.bitmapToMat(bitmap, mat);
// Note: when the matrix is to large mat.dump() might also freeze your app.
Log.w(TAG, mat.size());
Hopefully this'll help all of you who are also struggling with this.

Android Opencv exception on converting MAT to bitmap after processing

My goal is to take bytearray at onPreviewFrame convert it into openCv MAT for some processing and later display processed frame in imageview.
My implementation of onPreviewFrame is as follows:
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
Mat cvMat=Byte_to_Mat(data);
Imgproc.cvtColor(cvMat, cvMat, Imgproc.COLOR_YUV2BGR_NV12, 4);
Imgproc.cvtColor(cvMat, cvMat, Imgproc.COLOR_BGR2GRAY, 4);
Bitmap bm = Bitmap.createBitmap(cvMat.cols(), cvMat.rows(), Bitmap.Config.ARGB_8888);
public Mat Byte_to_Mat(byte[] data) {
Mat jpegData = new Mat(1, data.length, CvType.CV_8UC1);
jpegData.put(0, 0, data);
Mat bgrMat = new Mat();
bgrMat = Imgcodecs.imdecode(jpegData, Imgcodecs.IMREAD_COLOR);
return bgrMat;
}
However Bitmap.createBitmap throws following exception
java.lang.IllegalArgumentException: width and height must be > 0

Android OpenCV color segmentation display on ImageView

I have searched everywhere for a solution but I haven't found any. I know this is a recurrent question, so I'll try to be precise.
I want to perform color segmentation in HSV using Android and OpenCV. I have an array of HSV samples corresponding to the color I want to segment, from which I obtain mean and std in order to obtain a range of values like:
lowerBoundH = new Scalar(meanSamples[0]-stdSamples[0]);
lowerBoundS = new Scalar(meanSamples[1]-stdSamples[1]);
upperBoundH = new Scalar(meanSamples[0]+stdSamples[0]);
upperBoundS = new Scalar(meanSamples[1]+stdSamples[1]);
Once I obtain these ranges for H, S and V I do the following (I only work with channels H & S):
mH = new Mat();
mS = new Mat();
List<Mat> channels = new ArrayList<Mat>(2);
// convert inputFrame to HSV for segmentation
Mat hsvFrame = new Mat();
convertToHSV(inputFrame, hsvFrame);
Core.split(hsvFrame, channels);
// get H&S channels of the HSVimage
mH = channels.get(0);
mS = channels.get(1);
if(mH!=null & mS!=null){
mHinRange = new Mat();
mSinRange = new Mat();
Core.inRange(mH, lowerBoundH, upperBoundH, mHinRange);
Core.inRange(mS, lowerBoundS, upperBoundS, mSinRange);
Mat filtered = new Mat(hsvFrame.height(), hsvFrame.width(), CvType.CV_8UC1, new Scalar(4));
Core.bitwise_and(mHinRange, mSinRange, filtered);
Mat aux = new Mat();
Mat mRgb = new Mat();
inputFrame.copyTo(mRgb);
Imgproc.cvtColor(filtered, mRgb, Imgproc.COLOR_GRAY2BGR, 0);
Imgproc.cvtColor(mRgb, aux, Imgproc.COLOR_BGR2RGBA, 0);
return aux;
}else{
Log.v("NULL","H OR S CHANNELS ARE NULL");
return null;
}
Then, I convert that segmented Mat to Bitmap in order to display it in an ImageView like so:
Bitmap bmp = null;
Mat tmp = new Mat(result.height(),result.width(), CvType.CV_8UC1, new Scalar(4));
try {
bmp = Bitmap.createBitmap(tmp.cols(), tmp.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(tmp, bmp);
}catch (CvException e){Log.d("Exception",e.getMessage());}
qrImage.setImageBitmap(bmp);
But when I display the resulting image I get a completely black image. I know this is wrong because the camera is facing directly to the colored object I want to segment.
What am I doing wrong?
What a stupid mistake. I was creating the Bitmap from the empty tmp Mat.
Instead, I need to create it using the result Mat:
Bitmap bmp = null;
try {
bmp = Bitmap.createBitmap(result.cols(), result.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(result, bmp);
}catch (CvException e){Log.d("Exception",e.getMessage());}
qrImage.setImageBitmap(bmp);

Categories

Resources