Im working on an Application were I get an image in Opencv Mat format from a Webcam in a Java Client and have to process this image on a python server.
Therefore I`m sending a bytearray to the python server. I´m encoding the Image in Java like this:
private VideoCapture capture = new VideoCapture();
...
this.capture.read(frame);
if (!frame.empty()) {
byte[] return_buff = new byte[(int) (frame.total() *
frame.channels())];
frame.get(0, 0, return_buff);
...
After that I send it through a Socket using a DataOutputStream. When I echo it back to the Java Client the bytedata seems to have been transferred correctly and entirely. In Python I then tried to decode it with PIL
img = Image.open(BytesIO(data))
And yes I already import PIL like suggested here: PIL: Convert Bytearray to Image
But Im still getting this Error:
img = Image.open(BytesIO(data))
File "/root/.local/lib/python2.7/site-packages/PIL/Image.py", line 2590, in
open % (filename if filename else fp))
IOError: cannot identify image file
Do I have to change the way I assembled my bytearra or do I have to encode it in a different way?
Solved it! The thing is that Image.open(BytesIO(data)) apparently expects the data to have some kind of header to describe the image type and was therefore unfitting for a mat converted to bytes because a Mat appears to have no kind of header integrated, just the plain image data. In python an Image from a Mat bytearray can be derived using the following:
img = cv2.imdecode(bytearray, flag)
with flag being a number representing the cvtype of the image.
Related
I have a EBCDIC file from which i extracted images. However, there is some data on the images which is key source in identifying my transactions.
Assume that i have an image as "stackoverflow logo" stored under name "img1.jpg" on my desktop and when i read it using the following code, it works
String inputImage = "C:\\Desktop\\img1.jpg";
File imageFile = new File(inputImage);
BufferedImage image1 = ImageIO.read(imageFile);
System.out.println(image1);
However, when i attempt the same with an image decoded from EBCDIC conversion, it returns null.
The difference i observed is that there is no color associated in the decoded image. Is there any way to read these images and retrieve the text on the image. Following is not the exact image which i am working on, but just to give an idea i am sharing a sample from internet.
Note: The image am working on looks like a Scanned image (Grayscale)
Example:
Also, I observed that if i open the decode file and do a screen capture via snipping tool and store it as jpg file (which already is jpg) and read it, system is reading that file. not sure where is the issue, is it compression or color coding or format.
Thank you everyone.
I used Tess4j to decode the TIFF image. Unfortunately the information i was looking for isn't available in the decoded text. But, done with the POC.
used the following library and added eng.traineddata in the folder where images exist
import net.sourceforge.tess4j.*;
String inputImage = "C:\\Desktop\\img1.tiff";
File imageFile = new File(inputImage);
ITesseract imageRead = new Tesseract();
imageRead.setDataPath("C:\\Desktop\\");
imageRead.setLanguage("eng");
String imageText = imageRead.doOCR(imageFile);
System.out.println(imageText);
I got a strange issue with a GIF image in Java. The image is provided by an XML API as Base64 encoded string. To decode the Base64, I use the commons-codec library in version 1.13.
When I just decode the Base64 string and write the bytes out to a file, the image shows properly in browsers and MS Paint (nothing else to test here).
final String base64Gif = "[Base64 as provided by API]";
final byte[] sigImg = Base64.decodeBase64(base64Gif);
File sigGif = new File("C:/Temp/pod_1Z12345E5991872040.org.gif");
try (FileOutputStream fos = new FileOutputStream()) {
fos.write(sigImg);
fos.flush();
}
The resulting file opened in MS Paint:
But when I now start consuming this file using Java (for example creating a PDF document from HTML using the openhtmltopdf library), it is corrupted and does not show properly.
final String htmlLetterStr = "[HTML as provided by API]";
final Document doc = Jsoup.parse(htmlLetterStr);
try (FileOutputStream fos = new FileOutputStream(new File("C:/Temp/letter_1Z12345E5991872040.pdf"))) {
PdfRendererBuilder builder = new PdfRendererBuilder();
builder.useFastMode();
builder.withW3cDocument(new W3CDom().fromJsoup(doc), "file:///C:/Temp/");
builder.toStream(fos);
builder.useDefaultPageSize(210, 297, BaseRendererBuilder.PageSizeUnits.MM);
builder.run();
fos.flush();
}
When I now open the resulting PDF, the image created above looks like this. It seems that only the first pixel lines are printed, some layer is missing, or something like that.
The same happens, if I read the image again with ImageIO and try to convert it into PNG. The resulting PNG looks exactly the same as the image printed in the PDF document.
How can I get the image to display properly in the PDF document?
Edit:
Link to original GIF Base64 as provided by API: https://pastebin.com/sYJv6j0h
As #haraldK pointed out in the comments, the GIF file provided via the XML API does not conform to the GIF standard and thus cannot be parsed by Java's ImageIO API.
Since there does not seem to exist a pure Java tool to repair the file, the workaround I came up with now is to use ImageMagick via Java's Process API. Calling the convert command with the -coalesce option will parse the broken GIF and create a new one that does conform to the GIF standard.
// Decode broken GIF image and write to disk
final String base64Gif = "[Base64 as provided by API]";
final byte[] sigImg = Base64.decodeBase64(base64Gif);
Path gifPath = Paths.get("C:/Temp/pod_1Z12345E5991872040.tmp.gif");
if (!Files.exists(gifPath)) {
Files.createFile(gifPath);
}
Files.write(gifPath, sigImg, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);
// Use the Java Process API to call ImageMagick (on Linux you would use the 'convert' binary)
ProcessBuilder procBuild = new ProcessBuilder();
procBuild.command("C:\\Program Files\\ImageMagick-7.0.9-Q16\\magick.exe", "C:\\Temp\\pod_1Z12345E5991872040.tmp.gif", "-coalesce", "C:\\Temp\\pod_1Z12345E5991872040.gif");
Process proc = procBuild.start();
// Wait for ImageMagick to complete its work
proc.waitFor();
The newly created file can be read by Java's ImageIO API and be used as expected.
I'm working on a project in which I have to get image from camera (cmucam4) which is connected to my computer with Xbee.
The probleme is that I can get the image data over the serial port, but when I save it as a file, the file can't be openned as image.
I noticed that when I open the file with notepad++, the file does not have a header like other images (the camera send bmp image).
I tried to save the Image using ImageIO, but I dont know how to pass the data recived to the image!!
BufferedImage img = new BufferedImage(640, 480,BufferedImage.TYPE_INT_RGB);
ImageIO.write(img, "BMP", new File("img/tmp.bmp"));
If the camera truly sends BMP format, you could just write the data to disk. However, more likely (and this seems to be the case, reading the specs from your link), the cards sends a raw bitmap, which is not the same.
Using this info from the card spec PDF:
Raw image dumps over serial or to flash card
(640:320:160:80)x(480:240:120:60) image resolution
RGB565/YUV655 color space
The RGB565 pixel layout mentioned above should match perfectly with the BufferedImage.TYPE_USHORT_565_RGB, so that should be the easiest to use.
byte[] bytes = ... // read from serial port
ShortBuffer buffer = ByteBuffer.wrap(bytes)
.order(ByteOrder.BIG_ENDIAN) // Or LITTLE_ENDIAN depending on the spec of the card
.asShortBuffer(); // Our data will be 16 bit unsigned shorts
// Create an image matching the pixel layout from the card
BufferedImage img = new BufferedImage(640, 480, BufferedImage.TYPE_USHORT_565_RGB);
// Get the pixel data from the image, and copy the data from the card into it
// (the cast here is safe, as we know this will be the case for TYPE_USHORT_565_RGB)
short[] data = ((DataBufferUShort) img.getRaster().getDataBuffer()).getData();
buffer.get(data);
// Finally, write it out as a proper BMP file
ImageIO.write(img, "BMP", new File("temp.bmp"));
PS: The above code works for me, using a byte array of length 640 * 480 * 2, initialised with random data (as I obviously don't have such a card).
I have developed an Android app that connects with a laptop running Matlab over Bluetooth SPP. I am able to send strings back and forth easily and I am now interested in sending an image from Matlab to display on tablet (48x64 grayscale would be sufficient). I am unsure how to package an image and send it over at Matlab serial port. I am guessing you cannot just use fprintf or fwrite.
This is what I think the Android side might look like
public void drawImage(byte[] buffer){
ImageView camView = (ImageView)findViewById(R.id.camView);
Bitmap myBitmap = BitmapFactory.decodeByteArray(buffer, 0, buffer.length);
Log.d(TAG,"decoded image");
if(myBitmap != null){
camView.setImageBitmap(myBitmap);
Log.d(TAG,"Trying to display...");
}
else{
Log.d(TAG, "Bitmap = null");
}
}// end drawImage
Any advice on either the Andriod or Matlab side would be greatly appreciated. Thanks!
Are you just trying to receive serial data from Matlab? Why not treat it like any other serial data.
I would debug through an Android console application first to make sure it’s transmitting at all, and also to be sure that the data is transmitting the way you want it to transmit.
So I got it working. Basically the issue was that I was not sending the image with the proper compression (either .jpg or .png). I found that if you have a Matlab image which Matlab represents simply as a matrix of pixel values regardless of compression you need to create a java BufferedImage in order to properly construct the byte array so you can decode it on the Android side.
The Matlab side
import java.awt.*;
import java.io.*;
import java.util.*;
import javax.imageio.*;
serCam = InitUSBcamera; % initialize USB camera as a serial port
type = java.lang.String('jpg'); % translating matlab to java
outputStream = ByteArrayOutputStream; % create java output stream
im = getsnapshot(serCam); % get an image from the camera
im2 = imresize(im, [96,128],'nearest'); % reduce the size
im3 = im2java2d(im2); % create java Buffered Image
ImageIO.write(im3, type, outputStream);
bytes = outputStream.toByteArray();
fwrite(serTablet, bytes, 'int8') % send the image // changed to async
I need to send image from android app to java app. Basically, I need a byte array from the image to send to rf module which transmits.Another rf module receives and sends the byte array to java app which must make the image .
Android code:
FileInputStream fis = new FileInputStream(myFile);
byte[] b=new byte[(int)myFile.length()];
fis.read(b);server.send(b);
Java code:
FileOutputStream fwrite = new FileOutputStream(new File("my_xml"),true);
fwrite.write(bb);//bb is a byte from rf using input stream as soon as a byte comes it is read to file. This is necessary for some other reasons
fwrite.flush();
fwrite.close();
After getting full file:
FileInputStream fir=new FileInputStream("my_xml");
final BufferedImage bufferedImage = ImageIO.read(fir);
ImageIO.write(bufferedImage, "bmp", new File("image.bmp"));
fir.close();
I am getting error javax.imageio.IIOException: Bogus Huffman table definition
The rf is working fine because text file is being sent perfectly.Please help.Even without ImageIo code is not giving image even after changing extension to jpeg
The error means that the image file cant be read because the format is wrong.That is some bytes are missing or wrong or out of proper position and therefore file cant be decoded. My rf transfer does not have protocols like tcp/ip therefore some bytes are lost due to error in communication channel and hence the error.
You don't need to use ImageIO just to copy a file. Just read and write the bytes.
Your code has other problems:
You are assuming that read(byte[]) fills the buffer. It doesn't. Check the Javadoc.
You are also assuming that the file length fits into an int. If it does, fine. If it doesn't, you are hosed.
You appear to be opening and closing the FileOutputStream on every byte received. This could not be more inefficient. Open it once, write everything, close it.
flush() before close() is redundant.
You are storing the image in a file called 'my_xml'. This is only going to cause confusion, if it hasn't already.
You don't even need the file. Just load the image directly from the input stream.