Image data stored in hbase and retrieved as byte array using below code.
byte[] image_data = result.getValue(Bytes.toBytes("Data"), Bytes.toBytes("data"));
I need to convert into Opencv Mat for processing. While using below code I got invalid image.
Mat mat = new Mat();
mat.put(0, 0, image_data);
Tried How to convert an byte array to Opencv Mat?
Use image decode in Opencv for creating Mat from byte array
Mat mat = Highgui.imdecode(new MatOfByte(image_data), Highgui.CV_LOAD_IMAGE_UNCHANGED);
Related
I'm working with ImageIO and JAI and want to read a byte array into a BufferedImage. The byte[] contains data for a JP2000 encoded image, and it's fairly large, around 100MB. I'm currently doing something like:
byte[] imageDataBytes = ...
InputStream imageStream = new ByteArrayInputStream(imageDataBytes);
BufferedImage imageData = ImageIO.read(imageStream);
It seems that ImageIO is creating a new BufferedImage each time read() is called.
Question:
Is there a way to tell ImageIO to read and decode the image byte data into a pre-allocated mutable BufferedImage?
I did some searching through the Javadocs and found that the BufferedImage stores its data in a Raster object, which stores its data in a DataBuffer object. So I'm aware any solution that exists will technically not be writing to the BufferedImage, but instead will be directly writing to the DataBuffer.
It may help to know that all images are the same size: roughly 10,000 x 10,000, so there shouldn't be any problems with the read image not aligning with the buffered image. Ultimately, I would like to have an object pool of buffered images, or rasters, or data buffers, and borrow from the pool every time I read using ImageIO. Something like this pseudocode:
InputStream imageStream = new ByteArrayInputStream(imageDataBytes);
WritableRaster raster = ObjectPool.getAvailableRaster();
ImageIO.readToRaster(imageStream, raster);
BufferedImage imageData = new BufferedImage(raster);
I'm sure there's a simple solution out there. Any help would be appreciated!
Yes, you can set the destination image of an ImageReadParam object. However, there is a caveat: the BufferedImage must have a ColorModel and SampleModel that match the image being loaded.
I’m not sure about JPEG2000 images, but regular JPEGs are usually RGB images, so an image of TYPE_INT_RGB should suffice:
BufferedImage image = new BufferedImage(10000, 10000,
BufferedImage.TYPE_INT_RGB);
while (bytesAvailable) {
byte[] imageDataBytes = getImageBytes();
try (InputStream in = new ByteArrayInputStream(imageDataBytes);
ImageInputStream stream = ImageIO.createImageInputStream(in)) {
ImageReader reader = ImageIO.getImageReaders(stream).next();
reader.setInput(stream);
ImageReadParam param = reader.getDefaultReadParam();
param.setDestination(image);
reader.read(0, param);
}
}
For those who find themselves in this situation, the answer by VGR works well. I like to add that specifically for JPEG-2000 images that contain metadata, use
reader.setInput(stream, true, true);
instead of
reader.setInput(stream);
This avoids a NullPointer exception. you can read more about it here:
https://issues.apache.org/jira/browse/PDFBOX-2103
My goal here is to read in a CMYK Tiff image, mess with the pixels and then write out a new CMYK Tiff image. I am having a tough time finding any kind of example for this and any help would be greatly appreciated. Originally, I was doing this with RGB JPEG images without a problem using code like this:
// read input image
BufferedImage in = ImageIO.read(inputJPGAsFile);
// made output image that is same size as input image
FinalImage = new BufferedImage(in.getWidth(), in.getHeight(), BufferedImage.TYPE_INT_ARGB);
// mess with pixels in output image
// write as JPG
ImageIO.write(FinalImage, "JPEG", outputJPGAsFile);
However, now I am trying to figure out how to change this to work with CMYK Tiffs. It doesn't seem like there is a type for BufferedImage that would be anything like "TYPE_INT_CMYK". So then I was trying to use the ColorModel of the input image, but this crashes with the following error Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: Unknown color space. Any help on this would be greatly appreciated.
// read input image
BufferedImage in = ImageIO.read(inputTiffAsFile);
// get the CMYK color space of input image
ColorModel colorModel = in.getColorModel();
BufferedImage FinalImage = new BufferedImage(colorModel, colorModel.createCompatibleWritableRaster(100, 100), colorModel.isAlphaPremultiplied(), null);
// Copy in to FinalImage with some pixel manipulation
// write final image
ImageIO.write(FinalImage, "TIFF", outputTiffAsFile);
Also, I put java 9 because that is what I have been using, but I can upgrade to a newer version if that makes things easier. Thanks!
In Java:
I am reading an image using JAI:
BufferedImage image = javax.imageio.ImageIO.read(new File("path to JPG image"));
Then, I look at the rgb value of the pixel (0,2):
System.out.println("pixel[0][2]="+(new Color(image.getRGB(2, 0))));
In C++ OpenCV:
Mat image = imread("path to the same JPG image");
image.convertTo(image, CV_32S);
cout <<" r value of pixel[0][2] "<< image.at<Vec3i>(0, 2)[2] << "\n";
The values are different: r value in Java is 156 and in C++ is 155. Why?
I think this has to do with the format of the image, not with Java or OpenCV. JPEG is lossy compression, so when decoding the data you may get different outputs for the same image. That will depend on the decoder you are using to read the image information. The issue you are experimenting is similar to the one described in the below question.
Reading jpg file in OpenCV vs C# Bitmap
I am using Android Camera2 API to acquire frames from the camera. I can get an ImageReader that reads Image objects with the acquireLatestImage() method.
Since I need to process the acquired frames, I have to convert each Image object into a Mat object. I suppose this is a quite common problem, so I expected to find a convenient OpenCV method to do that. However I didn't find any.
Do you have an idea on how to get Mat objects from the camera frames with Android Camera2?
Thanks
This depends on what ImageFormat you set for your ImageReader class. This code below assumes that it's using the JPEG format.
Image image = reader.acquireLatestImage();
Mat buf = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC1);
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
buf.put(0, 0, bytes);
// Do note that Highgui has been replaced by Imgcodecs for OpenCV 3.0 and above
Mat mat = Highgui.imdecode(buf, IMREAD_COLOR);
image.close();
Do note that imdecode is quite slow. I'm not entirely sure but I think YUV_420_888 would be faster to convert to a Mat object, but I haven't figured out how to do it myself. I saw this post attempt the YUV conversion to a Mat,
I have image data coming in from over a socket connection as a byte[]. All examples I have seen using cvLoadImage() is passed a file name. Do I have to save every image to file and re-open it to do the processing? This seems to have a lot of overhead for what needs to happen, is it possible to load the image from the byte[] data?
Simple solution in the end, you can use the following method to create an Image from a BufferedImage which solved my problem:
IplImage src = IplImage.createFrom(buffered);
Assuming the data is encoded in some standard format like JPG or PNG, and assuming you are using JavaCV, for a byte array b, this works as well:
IplImage image = cvDecodeImage(cvMat(1, b.length, CV_8UC1, new BytePointer(b)));