Convert Mat to Bitmap by opencv - android

I'm trying to convert Mat rectangle from onCameraFrame to bitmap then send the bitmap to ocr function because i need to make the ocr works on real-time on ROI according to rectangle. I tried these lines:
Mat mgray= inputFrame.gray();
Mat grayInnerWindow = mgray.submat(100, 100 +500, 150, 200 + 50);
Imgproc.cvtColor(mIntermediateMat, rgbaInnerWindow, Imgproc.COLOR_GRAY2BGRA, 4);
rgbaInnerWindow.release();
Size sizeGray = grayInnerWindow.size();
int rowss = (int) sizeGray.height;
int colss = (int) sizeGray.width;
Mat tmp = new Mat(colss, rowss, CvType.CV_8UC4);
Imgproc.cvtColor(rgbaInnerWindow, tmp, Imgproc.COLOR_RGBA2BGRA, 4);
Bitmap bmp = Bitmap.createBitmap(tmp.cols(), tmp.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(tmp, bmp);
ImageView Img = (ImageView)findViewById(R.id.image_manipulations_activity_surface_view);
Img.setImageBitmap(bmp);
but when i run it terminated.

you are releasing rgbaInnerWindow, then you re-use it as input to cvtColor.
yep, that will burn, rgbaInnerWindow is invalid/empty now..
also, why all those cvtColor calls ? can't you just pass an 8bit grayscale image to your ocr?
(converting a 4channel, all grayscale image from rgba to bgra is utterly useless)

Related

Converting Bitmap To Mat through Utils.bitmapToMat changes its color [duplicate]

So I make a bitmap from a blob with the next code:
byte[] blob = contact.getMP();
ByteArrayInputStream inputStream = new ByteArrayInputStream(blob);
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
Bitmap scalen = Bitmap.createScaledBitmap(bitmap, 320, 240, false);
and it gives back the next output, which is good
Then I do the following to make the bitmap into a Mat, but then my colors just change...
//Mat ImageMat = new Mat();
Mat ImageMat = new Mat(320, 240, CvType.CV_32F);
Utils.bitmapToMat(scalen, ImageMat);
I have no idea why, nor another way to make the bitmap into a Mat. What is wrong?
The format of color channels in Android Bitmap are RGB
But in opencv Mat, the channels are BGR by default.
So when you do Utils.bitmapToMat(), [B,G,R] values are stored in [R,G,B] channels. The red and blue channels are interchanged.
One possible solution is to apply cvtcolor on the opencv Mat you got as below:
Imgproc.cvtColor(ImageMat, ImageMat, Imgproc.COLOR_BGR2RGB);
It worked for me.

Convert a bitmap to mat and vice versa in OpenCV

I have an Android Bitmap in my code and I would like to run the
cvCanny method on it. However, it needs to be in a Mat first. How do I
convert the data to Mat, and how do I convert it back to Bitmap when
I'm done?
First import org.opencv.android.Utils
Then use:
Mat src = new Mat();
Utils.bitmapToMat(bitmap, src);
To perform edge detection:
Mat dest = new Mat();
Imgproc.Canny(src, dest, min, max);
Bitmap edgeBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(dest, edgeBitmap);
//edgeBitmap is ready

How to set transparent background to grabcut output image with open cv?

> Hi, I am using OpenCV android library grabcut() method to extract an image from background, but the problem is that the output bitmap contains background Same as original image and object become white .I need Object as its same as original image and background transparent
I am using this code
private static Bitmap makeBlackTransparent(Bitmap image) {
// convert image to matrix
Mat src = new Mat(image.getWidth(), image.getHeight(), CvType.CV_8UC4);
Utils.bitmapToMat(image, src);
// init new matrices
Mat dst = new Mat(image.getWidth(), image.getHeight(), CvType.CV_8UC4);
Mat tmp = new Mat(image.getWidth(), image.getHeight(), CvType.CV_8UC4);
Mat alpha = new Mat(image.getWidth(), image.getHeight(), CvType.CV_8UC4);
// convert image to grayscale
Imgproc.cvtColor(src, tmp, Imgproc.COLOR_BGR2GRAY);
// threshold the image to create alpha channel with complete transparency in black background region and zero transparency in foreground object region.
Imgproc.threshold(tmp, alpha, 100, 255, Imgproc.THRESH_BINARY);
// split the original image into three single channel.
List<Mat> rgb = new ArrayList<Mat>(3);
Core.split(src, rgb);
// Create the final result by merging three single channel and alpha(BGRA order)
List<Mat> rgba = new ArrayList<Mat>(4);
rgba.add(rgb.get(0));
rgba.add(rgb.get(1));
rgba.add(rgb.get(2));
rgba.add(alpha);
Core.merge(rgba, dst);
// convert matrix to output bitmap
Bitmap output = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(dst, output);
return output;
}
There are 2 problems in your code:
Firstly you need to segment out the white background, so adjust your thresh to be near 220 - 240 and also use THRESH_BINARY_INV instead of THRESH_BINARY :
Imgproc.threshold(tmp, alpha, 230, 255, Imgproc.THRESH_BINARY_INV);
Secondly, you must pre-multiply the ARGB layers, as Android ImageView behaves weird without premultiplication, for that you need to use cvtColor with COLOR_RGBA2mRGBA flag:
// Create the final result by merging three single channel and alpha(BGRA order)
List<Mat> rgba = new ArrayList<Mat>(4);
rgba.add(rgb.get(0));
rgba.add(rgb.get(1));
rgba.add(rgb.get(2));
rgba.add(alpha);
Core.merge(rgba, dst);
Imgproc.cvtColor(dst, dst, Imgproc.COLOR_RGBA2mRGBA);

Android Image Processing using OpenCV

I am processing a camera frame using OpenCV. The functionality is working fine. However, it takes between 40~60 ms to process each frame. I am wondering if there is a possibility to improve the execution time. Following are the steps I take before I pass the mat to OpenCV cascade classifier.
mPixelBuf.rewind();
GLES20.glReadPixels(0, 0, mWidth, mHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, mPixelBuf);
Bitmap bmp = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
mPixelBuf.rewind();
bmp.copyPixelsFromBuffer(mPixelBuf);
// received inverted(upside-down) bitmap. Fixing it.
android.graphics.Matrix m = new android.graphics.Matrix();
m.preScale(1, -1);
Bitmap flipped = Bitmap.createBitmap(bmp, 0, 0, mWidth, mHeight, m, false);
Mat mat = new Mat();
// convert bitmap to mat
Utils.bitmapToMat(flipped, mat);
// apply gray scale
Imgproc.cvtColor(mat, mat, Imgproc.COLOR_BGR2GRAY);
// pass the mat to cascade classifier...
I guess there could be some smart ways to avoid this extra processing or perhaps reduce the image resolution for faster image processing.

Android OpenCV Highgui.imread wrong color

i have code to load image from sdcard and post it to ImageView.
Mat mRgba = Highgui.imread(dir);
Bitmap bmp = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(),Bitmap.Config.ARGB_8888);
Utils.matToBitmap(mRgba, bmp);
mImage.setImageBitmap(bmp, true, null, 5.0f);
the image is loaded but it's wrong color. Color seem to be inverted (but not inverted).
Here is image comparison
I tried to load image by
Bitmap bmp = BitmapFactory.decodeFile(dir);
It worked correctly. But i have to use Highgui.imread.
What wrong with my code?
You will have to use something like this:
Mat inputImage = Highgui.imread(pathToFile);
Mat tmp = new Mat();
Imgproc.cvtColor(inputImage, tmp, Imgproc.COLOR_BGR2RGB);
Bitmap imageToShow = Bitmap.createBitmap(tmp.cols(), tmp.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(tmp, imageToShow);
You're trying to load a bitmap supposing that the image is 8-bit/color RGBA: are you sure of that?
Also note that ARGB is not RGBA. You may need to re-arrange the bytes of each pixel. Something like
int pixel = get_the_pixel();
int alpha = 0xff & pixel;
pixel = pixel<<8 | alpha;
set_the_pixel(pixel);
You'll want to do something more efficient than accessor methods shown here, but you get the idea.

Categories

Resources