Bitmap to Mat gives wrong colors back - java

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.

Related

Byte array into the greyscale. Android take photo

When I am making photo in android I receive a byte array from camera. I would like to convert this array(image) into the 2 colors - white and black. Any ideas? Changing camera mode to mono/negative is not a sollution for me.
Greetings.
EDIT1: Code is in Java
First of all, you need to create bitmap from your array:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inMutable = true;
// data is your byte array
Bitmap bmpOriginal = BitmapFactory.decodeByteArray(data, 0, data.length, options);
Canvas canvas = new Canvas(bmpOriginal);
Bitmap bmpGrayscale = toGrayscale(bmpOriginal);
bmpOriginal.recycle(); // free memory immediately, as your bitmap is not garbage collected by now.
Then, you can pass your bmpOriginal, which is colored image, to converting method
public Bitmap toGrayscale(Bitmap bmpOriginal) {
int width, height;
height = bmpOriginal.getHeight();
width = bmpOriginal.getWidth();
Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bmpGrayscale);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
c.drawBitmap(bmpOriginal, 0, 0, paint);
return bmpGrayscale;
}
Above code will give you grayscale bitmap. It simply applies zero saturation filter to image. As the saturation is the purity of a color, the less purity - the less color difference. After applying above filter the only difference you get is brightness. The brightest is white, the darkest - black. If you want to convert it back to byte array you can try something like this:
Bitmap bmpGrayscale = intent.getExtras().get("data");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmpGrayscale.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
bmpGrayscale.recycle(); // free memory immediately, as your bitmap is not garbage collected by now.

How to convert ByteBuffer to Bitmap Image?

I am working on creating an image super-resolution application that uses a TensorFlow Lite model. The model gives the output Image in the form of ByteBuffer and I convert the ByteBuffer to Bitmap. Next, I display this Bitmap but nothing shows up. The code I am using can be seen below:
ByteBuffer out = ByteBuffer.allocate(4 * 384 * 384 * 3);
tflite.run(byteBuffer,out);
byte[] imageBytes= new byte[out.remaining()];
out.get(imageBytes);
final Bitmap outPut_Image = BitmapFactory.decodeByteArray(imageBytes,0,imageBytes.length);
//Toast.makeText(this,tflite.toString(),Toast.LENGTH_LONG).show();
Toast.makeText(this, "Working",Toast.LENGTH_LONG).show();
ImageView imageView = (ImageView) this.findViewById(R.id.imageView2);
imageView.setImageBitmap(outPut_Image);
Please advise me what I am doing wrong here.
BitmapFactory.decodeByteArray() is used for compressed image data such as JPEG.
For raw RGB888 data, I think you should convert it to ARGB_8888 format first.
After that you can use the following snippet to create Bitmap object.
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(buffer);

How to convert byte array to Mat object in Java

I want to convert byte array to Mat object, but it throws
java.lang.UnsupportedOperationException: Provided data element number (60181) should be multiple of the Mat channels count (3)
at org.opencv.core.Mat.put(Mat.java:992)
It is my code:
byte[] bytes = FileUtils.readFileToByteArray(new File("aaa.jpg"));
Mat mat = new Mat(576, 720, CvType.CV_8UC3);
//Imgcodecs.imencode(".jpg", mat, new MatOfByte(bytes));
mat.put(0, 0, bytes);
I tried many ways and also googled a lot, but did not find any solution.
Note: I know Imgcodecs.imread("aaa.jpg"); and
BufferedImage img = ImageIO.read(new ByteArrayInputStream(byteArray));
Mat mat = new Mat(img.getHeight(), img.getWidth(), CvType.CV_8UC3);
mat.put(0, 0, ((DataBufferByte) img.getRaster().getDataBuffer()).getData());
But I want to directly convert byte array to Mat without any extra process to speed up the process time.
Thanks in advance!
I solved the problem like this:
byte[] bytes = FileUtils.readFileToByteArray(new File("aaa.jpg"));
Mat mat = Imgcodecs.imdecode(new MatOfByte(bytes), Imgcodecs.CV_LOAD_IMAGE_UNCHANGED);
Now it works well and much faster than *bytes->BufferedImage->Mat*
Try it please. I'm using this.
BufferedImage b = ImageIO.read(url);
BufferedImage b1 = new BufferedImage(b.getWidth(), b.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
b1=b;
byte [] pixels = ((DataBufferByte)b1.getRaster().getDataBuffer()).getData();
Mat myPic = new Mat(b1.getHeight(),b1.getWidth(),CvType.CV_8UC3);
myPic.put(0, 0, pixels);
Or
OpenCV imread()
Mat myPic = Highgui.imread(url);
// OpenCV 3.x
Mat mat = Imgcodecs.imdecode(new MatOfByte(bytes), Imgcodecs.CV_LOAD_IMAGE_UNCHANGED);
// OpenCV 2.x
Mat mat = Highgui.imdecode(new MatOfByte(bytes), Highgui.CV_LOAD_IMAGE_UNCHANGED);
I've tried this kind of solution.
static Mat ba2Mat(byte[] ba)throws Exception{
// String base64String=Base64.getEncoder().encodeToString(ba);
// byte[] bytearray = Base64.getDecoder().decode(base64String);
Mat mat = Imgcodecs.imdecode(new MatOfByte(ba),
Imgcodecs.CV_LOAD_IMAGE_UNCHANGED);
return mat;
}

Convert BufferedImage TYPE_INT_RGB to OpenCV Mat Object

I am storing BufferedImages inside a MySQL database and retrieve them to a java application.
The BufferedImages are of type TYPE_INT_RGB.
How can i convert that image to a OpenCV Mat object?
I do always get a
java.lang.UnsupportedOperationException: Mat data type is not compatible:
Exception.
Can somebody help?
Got it on my own.
int[] data = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();
ByteBuffer byteBuffer = ByteBuffer.allocate(data.length * 4);
IntBuffer intBuffer = byteBuffer.asIntBuffer();
intBuffer.put(data);
Mat mat = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC3);
mat.put(0, 0, byteBuffer.array());
return mat;
image is the BufferedImage, you want to convert to a Mat-Object.
A much more simplified version of tellob's orignal anwser.
public static Mat mat2(BufferedImage image)
{
byte[] data = ((DataBufferByte)image.getRaster().getDataBuffer()).getData();
Mat mat = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC3);
mat.put(0, 0, data);
return mat;
}

BufferedImage Raster Data to BufferedImage

here's my code:
byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
BufferedImage newImage = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
WritableRaster raster = newImage.getRaster();
raster.setDataElements(0, 0, image.getWidth(), image.getHeight(), pixels);
newImage.setData(raster);
ImageIO.write(newImage, "jpg", new File("newimage.jpg"));
This code looks right to me and should do what I want. It gets the image's pixel data, then uses it to create a new image which should look exactly the same as the original image. However, the image that is saved has different colors than the original. Why?
Eventually, I'll need to manipulate the pixel bytes but for now, I don't know why it's giving me a different image.
This post may be of help java buffered image created with red mask
It seems to be a common problem with ImageIO so its best to use Toolkit instead.

Categories

Resources