阅读 DataMatrix/QR 代码 zxing java
Reading DataMatrix/QR code zxing java
使用 Barcode Scanner、zxing 移动应用程序可以很好地读取以下数据矩阵。但是,zxing java 库没有读取相同的内容。
我评论了一些图像转换代码。即使变换图像、旋转或缩放也无济于事。
理想情况下,我想以编程方式执行所有可能的图像预处理,直到解码。
移动应用程序使用的逻辑是什么,因为我从计算机屏幕上扫描相同的图像并且它正在运行。
请在下面找到,代码正在用于解码。
public class BarcodeReader {
private static Map<DecodeHintType,Object> hintsMap;
public static void main(String...args){
BufferedImage before = null;
hintsMap = new EnumMap<DecodeHintType, Object>(DecodeHintType.class);
hintsMap.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
hintsMap.put(DecodeHintType.POSSIBLE_FORMATS, EnumSet.allOf(BarcodeFormat.class));
//hintsMap.put(DecodeHintType.PURE_BARCODE, Boolean.FALSE);
try
{
before = ImageIO.read(new File("C:/ocr.jpg"));
decode(before);
/* for(int i=1; i < 1000;i++){
AffineTransform transform = new AffineTransform();
double rad = (double)i/100;
double scale = (double)i/100;
System.out.println("rad "+scale);
//transform.rotate(rad, before.getWidth()/2, before.getHeight()/2);
transform.scale(scale, scale);
BufferedImage after = new BufferedImage(before.getWidth(), before.getHeight(), BufferedImage.TYPE_INT_ARGB);
AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
after = op.filter(before, after);
decode(after);
}*/
//tmpBfrImage = tmpBfrImage.getSubimage(200, 100, 800, 800);
}
catch (IOException tmpIoe)
{
tmpIoe.printStackTrace();
}
}
public static void decode(BufferedImage tmpBfrImage){
if (tmpBfrImage == null)
throw new IllegalArgumentException("Could not decode image.");
LuminanceSource tmpSource = new BufferedImageLuminanceSource(tmpBfrImage);
BinaryBitmap tmpBitmap = new BinaryBitmap(new HybridBinarizer(tmpSource));
MultiFormatReader tmpBarcodeReader = new MultiFormatReader();
Result tmpResult;
String tmpFinalResult;
try
{
if (hintsMap != null && ! hintsMap.isEmpty())
tmpResult = tmpBarcodeReader.decode(tmpBitmap, hintsMap);
else
tmpResult = tmpBarcodeReader.decode(tmpBitmap);
// setting results.
tmpFinalResult = String.valueOf(tmpResult.getText());
System.out.println(tmpFinalResult);
System.exit(0);;
}
catch (Exception tmpExcpt)
{
tmpExcpt.printStackTrace();
}
}
}
我在多个层面都遇到了问题。我从github下载了zxing源码并调试了它。
第一个问题是添加以下行,因为提示搞砸了识别 hintsMap.put(DecodeHintType.PURE_BARCODE, Boolean.FALSE);
查看他们的 DataMatrixReader 源代码,有一行这样做
if (hints != null && hints.containsKey(DecodeHintType.PURE_BARCODE))
所以,无论PURE_BARCODE设置为true还是false,它都认为是true。理想情况下提示不应包含密钥。
第二个问题是 DataMatrix 检测器的工作方式。
检测器通过查看每个顶点的黑白转换数来识别 'L'。理想情况下,从左上角到左下角和从左下角到右下角的过渡应该有 0
个过渡。
但是,由于线被拉得更靠近框的外边缘,因此过渡没有变成 0
。我进行了更改以将其移近左侧和底部黑线的中心。这意味着将垂直红线向右移动,将底部红线向上移动一点。我添加了一种新方法 Correct Points,可以进行必要的更正。这个修正对我有用,理想情况下应该让修正更智能一点。
ResultPoint pointA = correctPoints(cornerPoints[0], Vertices.TOPLEFT);
ResultPoint pointB = correctPoints(cornerPoints[1], Vertices.BOTTOMLEFT);
ResultPoint pointC = correctPoints(cornerPoints[2], Vertices.TOPRIGHT);
ResultPoint pointD = correctPoints(cornerPoints[3], Vertices.BOTTOMRIGHT);
---
---
private ResultPoint correctPoints(ResultPoint point, Vertices vertice){
if(vertice.equals(Vertices.TOPLEFT))
return new ResultPoint(point.getX()+10, point.getY()+5);
else if(vertice.equals(Vertices.BOTTOMLEFT)){
return new ResultPoint(point.getX()+10, point.getY()-5);
}else if(vertice.equals(Vertices.TOPRIGHT)){
return new ResultPoint(point.getX(), point.getY()+10);
}else{
return new ResultPoint(point.getX()-10, point.getY()-5);
}
}
进行这些更改后,数据矩阵检测适用于与这些一样糟糕甚至更差的图像。
我在使用 ZXing 解码 DataMatrix 条形码时遇到了类似的问题。据我所知,ZXing 不会遍历您发送的整个图像,而是从中间开始向外扩展,直到找到条形码。因此,如果 DataMatrix 条码不在图像的中心,ZXing 将无法可靠地找到它。我实施了(一个相当慢的)解决方法来解决这个问题,方法是创建不同的图像裁剪版本:
我的核心decode方法和原来的类似post。我的图片遍历逻辑如下:
// Read the original image
final BufferedImage image = ImageIO.read(...);
final int width = image.getWidth();
final int height = image.getHeight();
// Try detect codes using different sections of the image.
//
// +------+------+
// | ##|## |
// | ##|## |
// | ##|## |
// +------+------+
// | | |
// | | |
// | | |
// +------+------+
//
// We create 9 cropped versions of the image, with each cropped
// version being 1/4 of the original image. We traverse the
// original image from left-to-right, top-to-bottom, and create
// 9 sub-images that we try to decode in turn.
for (int i=0; i<3; i++) {
for (int j=0; j<3; j++) {
final int x = i * width / 4;
final int y = j * height / 4;
final BufferedImage crop = image.getSubimage(x, y, width / 2, height / 2);
decoded(crop);
}
}
使用 Barcode Scanner、zxing 移动应用程序可以很好地读取以下数据矩阵。但是,zxing java 库没有读取相同的内容。
我评论了一些图像转换代码。即使变换图像、旋转或缩放也无济于事。
理想情况下,我想以编程方式执行所有可能的图像预处理,直到解码。
移动应用程序使用的逻辑是什么,因为我从计算机屏幕上扫描相同的图像并且它正在运行。
请在下面找到,代码正在用于解码。
public class BarcodeReader {
private static Map<DecodeHintType,Object> hintsMap;
public static void main(String...args){
BufferedImage before = null;
hintsMap = new EnumMap<DecodeHintType, Object>(DecodeHintType.class);
hintsMap.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
hintsMap.put(DecodeHintType.POSSIBLE_FORMATS, EnumSet.allOf(BarcodeFormat.class));
//hintsMap.put(DecodeHintType.PURE_BARCODE, Boolean.FALSE);
try
{
before = ImageIO.read(new File("C:/ocr.jpg"));
decode(before);
/* for(int i=1; i < 1000;i++){
AffineTransform transform = new AffineTransform();
double rad = (double)i/100;
double scale = (double)i/100;
System.out.println("rad "+scale);
//transform.rotate(rad, before.getWidth()/2, before.getHeight()/2);
transform.scale(scale, scale);
BufferedImage after = new BufferedImage(before.getWidth(), before.getHeight(), BufferedImage.TYPE_INT_ARGB);
AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
after = op.filter(before, after);
decode(after);
}*/
//tmpBfrImage = tmpBfrImage.getSubimage(200, 100, 800, 800);
}
catch (IOException tmpIoe)
{
tmpIoe.printStackTrace();
}
}
public static void decode(BufferedImage tmpBfrImage){
if (tmpBfrImage == null)
throw new IllegalArgumentException("Could not decode image.");
LuminanceSource tmpSource = new BufferedImageLuminanceSource(tmpBfrImage);
BinaryBitmap tmpBitmap = new BinaryBitmap(new HybridBinarizer(tmpSource));
MultiFormatReader tmpBarcodeReader = new MultiFormatReader();
Result tmpResult;
String tmpFinalResult;
try
{
if (hintsMap != null && ! hintsMap.isEmpty())
tmpResult = tmpBarcodeReader.decode(tmpBitmap, hintsMap);
else
tmpResult = tmpBarcodeReader.decode(tmpBitmap);
// setting results.
tmpFinalResult = String.valueOf(tmpResult.getText());
System.out.println(tmpFinalResult);
System.exit(0);;
}
catch (Exception tmpExcpt)
{
tmpExcpt.printStackTrace();
}
}
}
我在多个层面都遇到了问题。我从github下载了zxing源码并调试了它。
第一个问题是添加以下行,因为提示搞砸了识别
hintsMap.put(DecodeHintType.PURE_BARCODE, Boolean.FALSE);
查看他们的 DataMatrixReader 源代码,有一行这样做
if (hints != null && hints.containsKey(DecodeHintType.PURE_BARCODE))
所以,无论PURE_BARCODE设置为true还是false,它都认为是true。理想情况下提示不应包含密钥。
第二个问题是 DataMatrix 检测器的工作方式。
检测器通过查看每个顶点的黑白转换数来识别 'L'。理想情况下,从左上角到左下角和从左下角到右下角的过渡应该有
0
个过渡。但是,由于线被拉得更靠近框的外边缘,因此过渡没有变成
0
。我进行了更改以将其移近左侧和底部黑线的中心。这意味着将垂直红线向右移动,将底部红线向上移动一点。我添加了一种新方法 Correct Points,可以进行必要的更正。这个修正对我有用,理想情况下应该让修正更智能一点。ResultPoint pointA = correctPoints(cornerPoints[0], Vertices.TOPLEFT); ResultPoint pointB = correctPoints(cornerPoints[1], Vertices.BOTTOMLEFT); ResultPoint pointC = correctPoints(cornerPoints[2], Vertices.TOPRIGHT); ResultPoint pointD = correctPoints(cornerPoints[3], Vertices.BOTTOMRIGHT); --- --- private ResultPoint correctPoints(ResultPoint point, Vertices vertice){ if(vertice.equals(Vertices.TOPLEFT)) return new ResultPoint(point.getX()+10, point.getY()+5); else if(vertice.equals(Vertices.BOTTOMLEFT)){ return new ResultPoint(point.getX()+10, point.getY()-5); }else if(vertice.equals(Vertices.TOPRIGHT)){ return new ResultPoint(point.getX(), point.getY()+10); }else{ return new ResultPoint(point.getX()-10, point.getY()-5); } }
进行这些更改后,数据矩阵检测适用于与这些一样糟糕甚至更差的图像。
我在使用 ZXing 解码 DataMatrix 条形码时遇到了类似的问题。据我所知,ZXing 不会遍历您发送的整个图像,而是从中间开始向外扩展,直到找到条形码。因此,如果 DataMatrix 条码不在图像的中心,ZXing 将无法可靠地找到它。我实施了(一个相当慢的)解决方法来解决这个问题,方法是创建不同的图像裁剪版本:
我的核心decode方法和原来的类似post。我的图片遍历逻辑如下:
// Read the original image
final BufferedImage image = ImageIO.read(...);
final int width = image.getWidth();
final int height = image.getHeight();
// Try detect codes using different sections of the image.
//
// +------+------+
// | ##|## |
// | ##|## |
// | ##|## |
// +------+------+
// | | |
// | | |
// | | |
// +------+------+
//
// We create 9 cropped versions of the image, with each cropped
// version being 1/4 of the original image. We traverse the
// original image from left-to-right, top-to-bottom, and create
// 9 sub-images that we try to decode in turn.
for (int i=0; i<3; i++) {
for (int j=0; j<3; j++) {
final int x = i * width / 4;
final int y = j * height / 4;
final BufferedImage crop = image.getSubimage(x, y, width / 2, height / 2);
decoded(crop);
}
}