I got a function where i process different arrays[][] and I need to use a Mat because I'm working with images, so I need the pixels of that image.
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat img = Imgcodecs.imread(imagelocation);
I need a way to get the pixels values of that Mat.
But I was wondering if I can convert an array[][] into a Mat.
I hope you understand and help me.
To get the pixel values of the Mat you can use: reference
Mat m;
int bufferSize = m.channels()*m.cols()*m.rows();
byte [] b = new byte[bufferSize];
m.get(0,0,b); // get all the pixels
double pixelValue = m.get(0, 0) // get pixel at row 0, column 0
To convert an array to Mat:
byte[] raw_data = ...;
Mat mat = new Mat();
mat.put(0, 0, raw_data);
Related
In my program I am reading an image using java, taking its byte array and applying modifications to it by applying random functions. Now during the entire process the size of array is maintained but when I am trying to construct an image using the byte array an empty image is obtained. I have tried using both java and opencv to reconstruct the image (the image is grayscale image of 440*442 size .png type).
opencv code:
byte[] bytesArrayForImage=new byte[array.length];
for (int i=0; i<array.length; i++) {
bytesArrayForImage[i] = (byte) Integer.parseInt(array[i]);
}
Mat mat = new Mat(440,442, CvType.CV_8UC1);
mat.put(0,0, bytesArrayForImage);
String filename111 = Path;
Highgui.imwrite(filename111, mat);
java code:
BufferedImage image=ImageIO.read(new ByteArrayInputStream(bytearray));
ImageIO.write(image, "png", new File(C:\\Users\\domin\\Desktop\\Sop\\,"modified.png"));
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;
}
I am trying to create a helper function using OpenCV Java API that would process an input image and return the output byte array. The input image is a jpg file saved in the computer. The input and output image are displayed in the Java UI using Swing.
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// Load image from file
Mat rgba = Highgui.imread(filePath);
Imgproc.cvtColor(rgba, rgba, Imgproc.COLOR_RGB2GRAY, 0);
// Convert back to byte[] and return
byte[] return_buff = new byte[(int) (rgba.total() * rgba.channels())];
rgba.get(0, 0, return_buff);
return return_buff;
When the return_buff is returned and converted to BufferedImage I get NULL back. When I comment out the Imgproc.cvtColor function, the return_buff is properly converted to a BufferedImage that I can display. It seems like the Imgproc.cvtColor is returning a Mat object that I couldn't display in Java.
Here's my code to convert from byte[] to BufferedImage:
InputStream in = new ByteArrayInputStream(inputByteArray);
BufferedImage outputImage = ImageIO.read(in);
In above code, outputImage is NULL
Does anybody have any suggestions or ideas?
ImageIO.read(...) (and the javax.imageio package in general) is for reading/writing images from/to file formats. What you have is an array containing "raw" pixels. It's impossible for ImageIO to determine file format from this byte array. Because of this, it will return null.
Instead, you should create a BufferedImage from the bytes directly. I don't know OpenCV that well, but I'm assuming that the result of Imgproc.cvtColor(rgba, rgba, Imgproc.COLOR_RGB2GRAY, 0) will be an image in grayscale (8 bits/sample, 1 sample/pixel). This is the same format as BufferedImage.TYPE_BYTE_GRAY. If this assumption is correct, you should be able to do:
// Read image to Mat as before
Mat rgba = ...;
Imgproc.cvtColor(rgba, rgba, Imgproc.COLOR_RGB2GRAY, 0);
// Create an empty image in matching format
BufferedImage gray = new BufferedImage(rgba.width(), rgba.height(), BufferedImage.TYPE_BYTE_GRAY);
// Get the BufferedImage's backing array and copy the pixels directly into it
byte[] data = ((DataBufferByte) gray.getRaster().getDataBuffer()).getData();
rgba.get(0, 0, data);
Doing it this way, saves you one large byte array allocation and one byte array copy as a bonus. :-)
I used this kind of code to convert Mat object to Buffered Image.
static BufferedImage Mat2BufferedImage(Mat matrix)throws Exception {
MatOfByte mob=new MatOfByte();
Imgcodecs.imencode(".jpg", matrix, mob);
byte ba[]=mob.toArray();
BufferedImage bi=ImageIO.read(new ByteArrayInputStream(ba));
return bi;
}
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;
}
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.