关于二维码识别报错com.google.zxing.NotFoundException的解决方案

关于二维码识别报错com.google.zxing.NotFoundException的解决方案


刚使用ZXing用来解析 拍照上传的二维码内容时,最容易出现 com.google.zxing.NotFoundException这个报错。
这个问题根源大概是zxing在定位二维码锚点时,因为图片 (不清晰 / 含有logo / 内容干扰元素较多 / 二维码占图片的比例较小)导致的。一般解决方法为: 将图片二值化,灰度处理,然后进行开运算。这样处理后,绝大多数拍照上传的二维码均能有效地识别。图片处理代码如下:

public class ImageOptimizationUtil {

    // 阈值0-255
    public static int YZ = 200;

    /**
     * 图像二值化处理
     *
     * @param filePath 要处理的图片路径
     * @param fileOutputPath 处理后的图片输出路径
     */
    public static void binarization(String filePath, String fileOutputPath) throws IOException {
        File file = new File(filePath);
        BufferedImage bi = ImageIO.read(file);
        // 获取当前图片的高,宽,ARGB
        int h = bi.getHeight();
        int w = bi.getWidth();
        int arr[][] = new int[w][h];

        // 获取图片每一像素点的灰度值
        for (int i = 0; i < w; i++) {
            for (int j = 0; j < h; j++) {
                // getRGB()返回默认的RGB颜色模型(十进制)
                arr[i][j] = getImageGray(bi.getRGB(i, j));// 该点的灰度值
            }
        }

        // 构造一个类型为预定义图像类型,BufferedImage
        BufferedImage bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_BINARY);

        // 和预先设置的阈值大小进行比较,大的就显示为255即白色,小的就显示为0即黑色
        for (int i = 0; i < w; i++) {
            for (int j = 0; j < h; j++) {
                if (getGray(arr, i, j, w, h) > YZ) {
                    int white = new Color(255, 255, 255).getRGB();
                    bufferedImage.setRGB(i, j, white);
                } else {
                    int black = new Color(0, 0, 0).getRGB();
                    bufferedImage.setRGB(i, j, black);
                }
            }

        }
        ImageIO.write(bufferedImage, "jpg", new File(fileOutputPath));
    }

    /**
     * 图像的灰度处理
     * 利用浮点算法:Gray = R*0.3 + G*0.59 + B*0.11;
     *
     * @param rgb 该点的RGB值
     * @return 返回处理后的灰度值
     */
    private static int getImageGray(int rgb) {
        String argb = Integer.toHexString(rgb);// 将十进制的颜色值转为十六进制
        // argb分别代表透明,红,绿,蓝 分别占16进制2位
        int r = Integer.parseInt(argb.substring(2, 4), 16);// 后面参数为使用进制
        int g = Integer.parseInt(argb.substring(4, 6), 16);
        int b = Integer.parseInt(argb.substring(6, 8), 16);
        int gray = (int) (r*0.28 + g*0.95 + b*0.11);
        return gray;
    }

    /**
     * 自己加周围8个灰度值再除以9,算出其相对灰度值
     *
     * @param gray
     * @param x 要计算灰度的点的横坐标
     * @param y 要计算灰度的点的纵坐标
     * @param w 图像的宽度
     * @param h 图像的高度
     * @return
     */
    public static int getGray(int gray[][], int x, int y, int w, int h) {
        int rs = gray[x][y] + (x == 0 ? 255 : gray[x - 1][y]) + (x == 0 || y == 0 ? 255 : gray[x - 1][y - 1])
                + (x == 0 || y == h - 1 ? 255 : gray[x - 1][y + 1]) + (y == 0 ? 255 : gray[x][y - 1])
                + (y == h - 1 ? 255 : gray[x][y + 1]) + (x == w - 1 ? 255 : gray[x + 1][y])
                + (x == w - 1 || y == 0 ? 255 : gray[x + 1][y - 1])
                + (x == w - 1 || y == h - 1 ? 255 : gray[x + 1][y + 1]);
        return rs / 9;
    }

    /**
     * 二值化后的图像的开运算:先腐蚀再膨胀(用于去除图像的小黑点)
     *
     * @param filePath 要处理的图片路径
     * @param fileOutputPath 处理后的图片输出路径
     * @throws IOException
     */
    public static void opening(String filePath, String fileOutputPath) throws IOException {
        File file = new File(filePath);
        BufferedImage bi = ImageIO.read(file);
        // 获取当前图片的高,宽,ARGB
        int h = bi.getHeight();
        int w = bi.getWidth();
        int arr[][] = new int[w][h];
        // 获取图片每一像素点的灰度值
        for (int i = 0; i < w; i++) {
            for (int j = 0; j < h; j++) {
                // getRGB()返回默认的RGB颜色模型(十进制)
                arr[i][j] = getImageGray(bi.getRGB(i, j));// 该点的灰度值
            }
        }

        int black = new Color(0, 0, 0).getRGB();
        int white = new Color(255, 255, 255).getRGB();
        BufferedImage bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_BINARY);
        // 临时存储腐蚀后的各个点的亮度
        int temp[][] = new int[w][h];
        // 1.先进行腐蚀操作
        for (int i = 0; i < w; i++) {
            for (int j = 0; j < h; j++) {
                /*
                 * 为0表示改点和周围8个点都是黑,则该点腐蚀操作后为黑
                 * 由于公司图片态模糊,完全达到9个点全为黑的点太少,最后效果很差,故改为了小于30
                 * (写30的原因是,当只有一个点为白,即总共255,调用getGray方法后得到255/9 = 28)
                 */
                if (getGray(arr, i, j, w, h) < 30) {
                    temp[i][j] = 0;
                } else{
                    temp[i][j] = 255;
                }
            }
        }

        // 2.再进行膨胀操作
        for (int i = 0; i < w; i++) {
            for (int j = 0; j < h; j++) {
                bufferedImage.setRGB(i, j, white);
            }
        }
        for (int i = 0; i < w; i++) {
            for (int j = 0; j < h; j++) {
                // 为0表示改点和周围8个点都是黑,则该点腐蚀操作后为黑
                if (temp[i][j] == 0) {
                    bufferedImage.setRGB(i, j, black);
                    if(i > 0) {
                        bufferedImage.setRGB(i-1, j, black);
                    }
                    if (j > 0) {
                        bufferedImage.setRGB(i, j-1, black);
                    }
                    if (i > 0 && j > 0) {
                        bufferedImage.setRGB(i-1, j-1, black);
                    }
                    if (j < h-1) {
                        bufferedImage.setRGB(i, j+1, black);
                    }
                    if (i < w-1) {
                        bufferedImage.setRGB(i+1, j, black);
                    }
                    if (i < w-1 && j > 0) {
                        bufferedImage.setRGB(i+1, j-1, black);
                    }
                    if (i < w-1 && j < h-1) {
                        bufferedImage.setRGB(i+1, j+1, black);
                    }
                    if (i > 0 && j < h-1) {
                        bufferedImage.setRGB(i-1, j+1, black);
                    }
                }
            }
        }

        ImageIO.write(bufferedImage, "jpeg", new File(fileOutputPath));
    }

    public static void main(String[] args) {
        String fullPath="code.jpeg";
        String newPath="code2.jpeg";
        try {
            ImageOptimizationUtil.binarization(fullPath,newPath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
`com.google.zxing.NotFoundException` 是一个异常类,表示在使用 ZXing 库进行二维码识别时未能找到有效的二维码。通常出现这种情况是因为图片中不存在二维码二维码不清晰或者损坏等原因。 要解决这个问题,可以尝试以下几种方法: 1. 确保图片中存在二维码:使用图片编辑软件查看图片中是否存在二维码,或者使用其他二维码识别工具验证图片中是否存在二维码。 2. 确保二维码清晰:使用高清晰度的图片进行识别,或者尝试调整图片的对比度和亮度。 3. 使用多个二维码识别算法:ZXing 库提供了多个二维码识别算法,可以尝试使用不同的算法进行识别。 以下是一个使用 ZXing 库进行二维码识别的示例代码: ```java import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import com.google.zxing.BinaryBitmap; import com.google.zxing.MultiFormatReader; import com.google.zxing.NotFoundException; import com.google.zxing.Result; import com.google.zxing.client.j2se.BufferedImageLuminanceSource; import com.google.zxing.common.HybridBinarizer; public class QRCodeReader { public static void main(String[] args) { try { File file = new File("qrcode.png"); BufferedImage image = ImageIO.read(file); BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(image))); Result result = new MultiFormatReader().decode(bitmap); System.out.println(result.getText()); } catch (IOException e) { e.printStackTrace(); } catch (NotFoundException e) { e.printStackTrace(); } } } ``` 在上面的示例代码中,我们使用 `MultiFormatReader` 类进行二维码识别。如果识别失败,则会抛出 `NotFoundException` 异常,可以根据异常信息进行排查。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值