Reputation: 847
I have a java application which requires to read bar-code from an image to java program. I was very impressed with zxing library which is able to retrieve bar-codes, But not for all the images(I mean if the image quality is slightly poor.).
My question is, What is the most preferable image format to read bar-codes? JPEG or PNG? I'm currently trying JPEG images.
And another question, What is the most reliable java API/SDK to retrieve bar-codes from images. I already tried, Accusoft, DataSymbol, AtalaSoft, j4l which are paid versions. And have gone through few open sources like Ron Cemer JavaBar. But still I'm looking for a JAVA API/SDK which gives accurate results in bar-code reading.
Your information regarding Barcode Reader JAVA APIs/SDKs would be really helpful for me.
Upvotes: 12
Views: 31321
Reputation: 837
I recently had the same problem: using the ZXing library in a Java application I was decoding QR codes but we often had to process scans of prints with low quality and the rate of recognition of the QR codes needed to be improved. I am adding my findings here in the hope it will help somebody who faces the same problem.
I used the ImageJ image processing library. It is quite extensive and actually a complete program with a GUI and many plugins. I only used the api:
<dependency>
<groupId>net.imagej</groupId>
<artifactId>ij</artifactId>
<version>1.52g</version>
</dependency>
The documentation is not so useful, these tutorials were more interesting.
I had to hunt for the javadocs of the API, you can find them here
So I tried a bunch of image optimization and enhancing, but nothing really seemed to have a positive effect. Cutting out a subimage where the QR code was placed on the scan sped up the process a lot though.
Then I tried the suggestions of user @kevto in another comment here (thanks!)
Convert to the image to grayscale. Resize barcode up to 4 times in height and 8 times in width. Apply gaussian blur with the size of 17x17 pixels. Apply binary threshold with the threshold value of 225 and maximum value of 255.
The image was already grayscale so that did not effect the recognition rate of the QR codes. The last suggestion did not seem to do much either. The second one is a bit strange : resizing with different parameters for width and height stretched out the image and resulted in unrecognizable QR codes. The third suggestion was what I was searching for : adding gaussian blur dramatically increased the recognition rate of QR codes when working with lower quality scans. Adding blur to QR codes of high quality scans lowered the recognition rate, so take care.
Resulted in this code:
public BufferedImage preProcessBufferedImage (BufferedImage bufferedImage)throws IOException{
//get subimage that cuts out the QR code, speeds up the QR recognition process
BufferedImage subImage = bufferedImage.getSubimage(x, y,width,height);
//gaussian blur the result , leads to better QR code recognition
ImagePlus imagePlus = new ImagePlus("process-qr-code", subImage);
imagePlus.getProcessor().blurGaussian(2);
return imagePlus.getBufferedImage();
}
I tried a lot of values for the sigma of the blur function. Values between 1.5 and 2.5 gave the best results.
So I perform two passes at recognizing the QR code : once like I did before (gets the high quality images) and then once with the extra processing (for the lower quality images)
Upvotes: 2
Reputation: 6460
Java Apache Camel Barcode based on the zxing library works great:
<!-- https://mvnrepository.com/artifact/org.apache.camel/camel-barcode -->
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-barcode</artifactId>
<version>2.21.1</version>
</dependency>
import com.google.zxing.BinaryBitmap;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.Reader;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import lombok.Getter;
import javax.imageio.ImageIO;
import java.io.IOException;
import java.io.InputStream;
public class BarcodeImageDecoder {
public BarcodeInfo decodeImage(InputStream inputStream) throws BarcodeDecodingException {
try {
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(
new BufferedImageLuminanceSource(ImageIO.read(inputStream))));
if (bitmap.getWidth() < bitmap.getHeight()) {
if (bitmap.isRotateSupported()) {
bitmap = bitmap.rotateCounterClockwise();
}
}
return decode(bitmap);
} catch (IOException e) {
throw new BarcodeDecodingException(e);
}
}
private BarcodeInfo decode(BinaryBitmap bitmap) throws BarcodeDecodingException {
Reader reader = new MultiFormatReader();
try {
Result result = reader.decode(bitmap);
return new BarcodeInfo(result.getText(), result.getBarcodeFormat().toString());
} catch (Exception e) {
throw new BarcodeDecodingException(e);
}
}
public static class BarcodeInfo {
@Getter
private final String text;
@Getter
private final String format;
BarcodeInfo(String text, String format) {
this.text = text;
this.format = format;
}
}
public static class BarcodeDecodingException extends Exception {
BarcodeDecodingException(Throwable cause) {
super(cause);
}
}
}
Upvotes: 4
Reputation: 549
@Tom Setzer's solution is great if you don't mind paying a little extra for your project. However, if you don't have the budget to get such software, I'd still recommend to listen to Tom's answer.
One option for improving results is some image processing prior to sending into the engine. Try to scale the image up prior to going from Gray/Color to Black and White. A better binarization (gray to b&w) than what is provided in the engine can also help.
He's right but I'm still using ZXing. It works great only if you do some image processing before you attempt to read the barcode.
I'm using OpenCV for image processing. A great native library that works both for Linux and Windows and probably some other platforms as well (haven't looked into that).
This is the way I do it.
After following these steps, you'd be getting better results.
Resources:
Upvotes: 7
Reputation: 11
JPEG is a lossy compression and, depending on the level of compression, the resolution of the image and the quality of the image (lighting, contrast, etc) the artifacts introduced by JPEG compression could interfere with the reading of the barcode.
PNG is lossless. It will result in a larger file, but won't add additional challenges (artifacts) for the barcode engine to read.
For accuracy of the barcode engines, this varies widely. Certain engines perform better on certain types of barcodes (e.g. Code 128 vs QR code) and on the image quality issues (low resolution vs poor contrast). If you have a wide variety of image quality problems because you can't control the source of the images, you will likely need to go with a commercial engine in order to achieve highest results.
One option for improving results is some image processing prior to sending into the engine. Try to scale the image up prior to going from Gray/Color to Black and White. A better binarization (gray to b&w) than what is provided in the engine can also help.
Full disclosure, I work for Accusoft, a barcode SDK provider.
Upvotes: 1
Reputation: 847
Recently, I found this software zbar which gave promising results in reading bar-codes. It has an option of decoding the bar-code from command prompt. Since, it's not an SDK or API. So, I did a trick to read barcodes from an image by java program.
import java.io.*;
public class BarCodeReader {
public static void main(String args[])
{
try
{
Process p=Runtime.getRuntime().exec("C:/Program Files/ZBar/bin/zbarimg D:/jpeg/006.jpg");
p.waitFor();
BufferedReader reader=new BufferedReader(
new InputStreamReader(p.getInputStream())
);
String line=reader.readLine();
while(line!=null)
{
System.out.println(line);
line=reader.readLine();
}
}
catch(IOException e1) {}
catch(InterruptedException e2) {}
System.out.println("Done");
}
}
Hope, this might be helpful for anyone who's trying to read barcode from an image in JAVA.
Note: it also works for Linux. I tested it. For linux environment, all you need to do is, run this command.
sudo apt-get install zbar-tools
and in Java program, change your code like this,
Process p=Runtime.getRuntime().exec("zbarimg /opt/images/006.jpg");// your file path.
And it works very fine.
If you guys come across any other barcode reading SDKs or APIs or Softwares which can run on command line, Please leave an answer.
Upvotes: 4
Reputation: 5247
JavaBar is one more thing you can consider it is open source and has good reviews
Upvotes: 0