java实现识别二维码图片功能

本文实例为大家分享了java实现识别二维码图片功能,供大家参考,具体内容如下

所需maven依赖

<dependency>
   <groupId>com.google.zxing</groupId>
   <artifactId>javase</artifactId>
   <version>3.2.1</version>
</dependency>
<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>core</artifactId>
    <version>3.3.3</version>
</dependency>

实现的java类

import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import sun.misc.BASE64Decoder;
 
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
 * 作用:二维码识别(图片)
 * 类名:QRCodeUtils
 **/
public class QRCodeUtils {
    /**
     * 解析二维码,此方法解析一个路径的二维码图片
     * path:图片路径
     */
    public static String deEncodeByPath(String path) {
        String content = null;
        BufferedImage image;
        try {
            image = ImageIO.read(new File(path));
            LuminanceSource source = new BufferedImageLuminanceSource(image);
            Binarizer binarizer = new HybridBinarizer(source);
            BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
            Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();
            hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
            Result result = new MultiFormatReader().decode(binaryBitmap, hints);//解码
            System.out.println("图片中内容:  ");
            System.out.println("content: " + result.getText());
            content = result.getText();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NotFoundException e) {
            //这里判断如果识别不了带LOGO的图片,重新添加上一个属性
            try {
                image = ImageIO.read(new File(path));
                LuminanceSource source = new BufferedImageLuminanceSource(image);
                Binarizer binarizer = new HybridBinarizer(source);
                BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
                Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();
                //设置编码格式
                hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
                //设置优化精度
                hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
                //设置复杂模式开启(我使用这种方式就可以识别微信的二维码了)
                hints.put(DecodeHintType.PURE_BARCODE,Boolean.TYPE);
                Result result = new MultiFormatReader().decode(binaryBitmap, hints);//解码
                System.out.println("图片中内容:  ");
                System.out.println("content: " + result.getText());
                content = result.getText();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (NotFoundException e) {
                e.printStackTrace();
            }
        }
        return content;
    }
}

测试

public static void main(String [] args){
    deEncodeByPath("D:\\Users/admin/Desktop/erweima/timg (5).jpg");//二维码图片路径
}

输出结果:

图片中内容:
content: http://qrcode.online

如果上述不能识别的话,那么就需要对图片处理一次,然后再进行识别,这里是个调优图片的工具类。

package com.face.ele.common.utils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

/**
 * @author weijianxing
 * @description: TODO
 * @date 2020/11/26 9:28
 */
public class ImageOptimizationUtil {

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

    /**
     * 图像二值化处理
     *
     * @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, "jpg", new File(fileOutputPath));
    }

    public static void main(String[] args) {
        String fullPath="E:\\weijianxing\\img\\微信图片_20201202160240.jpg";
        String newPath="E:\\weijianxing\\img\\1new_微信图片_20201202160240.jpg";
        try {
            ImageOptimizationUtil.binarization(fullPath,newPath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

可以手动测试,然后对改代码的部分进行调正对应的参数-- gray变量里的计算进行灰度调整

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;
    }

等调整之后,在对图片进行识别即可。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 不到十行实现javaCV图片OCR文字识别

    spring boot项目pom文件中添加以下依赖 <!-- https://mvnrepository.com/artifact/org.bytedeco/javacv-platform --> <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv-platform</artifactId> <version>1.5.5</version&g

  • java图片识别文字的方法

    java文字识别程序的关键是寻找一个可以调用的OCR引擎.tesseract-ocr就是一个这样的OCR引擎,在1985年到1995年由HP实验室开发,现在在Google.tesseract-ocr 3.0发布,支持中文.不过tesseract-ocr 3.0不是图形化界面的客户端,别人写的FreeOCR图形化客户端还不支持导入新的 3.0 traineddata.但这标志着,现在有自由的中文OCR软件了. java中使用tesseract-ocr3.01的步骤如下: 1.下载安装tessera

  • Java创建、识别条形码和二维码方法示例

    前言 条形码(Barcode)是将宽度不等的多个黑条和空白,按照一定的编码规则排列,用以表达一组信息的图形标识符.常用于标示物品的生产国.制造厂家.商品名称.生产日期.图书分类号.邮件起止地点.类别.日期等信息,广泛应用于各个领域.常见的包括一维条码(条码).二维条码(二维码).彩色条码,在具体码制上可分为多种不同类型的条码,如UPC(统一产品代码,只能以数字表示).Code 3(能表示字母.数字和其它一些符号共43个字符).Code 128(表示高密度数据,字符串可变长,符号内含校验码).Co

  • java实现腾讯ocr图片识别接口调用

    最近开发了一个拍车牌识别车牌号的功能,主要调用了腾讯的ocr车牌识别接口,直接上代码: 首先生成签名以及读取配置的工具类: package com.weaver.formmodel.integration.ocr; import java.util.Random; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import weaver.general.Base64; public class SignUtil

  • Windows下Java调用OCR进行图片识别

    使用Java语言,通过Tesseract-OCR对图片进行识别. 1.Tesseract-OCR 下载windows版本并安装. 2.程序如下: a.ImageIOHelper类 package OCR; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.Iterator; import java.util.Locale; import ja

  • Java使用opencv识别二维码的完整步骤

    目录 前言 OpenCV的安装 开发环境配置 识别二维码 总结 前言 OpenCV的全称是Open Source Computer Vision Library,它是一个跨平台的计算机视觉库,由英特尔公司发起并参与开发,以BSD许可证授权发行,可以在商业和研究领域中免费使用.OpenCV本身由C++语言开发,但也具有各种其他语言的接口,并支持windows.linux.ios.android等各种操作系统.本文将介绍如何使用OpenCV与Java语言进行二维码识别. OpenCV的安装 目前Op

  • java实现图片文字识别ocr

    最近在开发的时候需要识别图片中的一些文字,网上找了相关资料之后,发现google有一个离线的工具,以下为java使用的demo 在此之前,使用这个工具需要在本地安装OCR工具: 下面一个是一定要安装的离线包,建议默认安装 上面一个是中文的语言包,如果网络可以FQ的童鞋可以在安装的时候就选择语言包在线安装,有多种语言可供选择,默认只有英文的 exe安装好之后,把上面一个文件拷到安装目录下tessdata文件夹下 如C:\Program Files (x86)\Tesseract-OCR\tessd

  • java使用电脑摄像头识别二维码

    本文实例为大家分享了java使用电脑摄像头识别二维码的具体代码,供大家参考,具体内容如下 要想摄像头识别二维码,需要两个基本功能: 1.从摄像头获取图像,2.根据图片解析出二维码信息. 在上一篇java摄像头截图已经实现了摄像头截图,只要再加上zxing(或其它能从图片中解析二维码的组件),就能从图像中解析出二维码,实现代码如下: package com.pengo.capture; import javax.swing.JFrame; import java.awt.BorderLayout;

  • Java基于直方图应用的相似图片识别实例

    本文实例讲述了Java实现基于直方图应用的相似图片识别,是非常实用的技巧.分享给大家供大家参考.具体分析如下: 一.算法概述: 首先对源图像与要筛选的图像进行直方图数据采集,对采集的各自图像直方图进行归一化再使用巴氏系数算法对直方图数据进行计算,最终得出图像相似度值,其值范围在[0, 1]之间 0表示极其不同,1表示极其相似(相同). 二.算法步骤详解: 大致可以分为两步,根据源图像与候选图像的像素数据,生成各自直方图数据.第二步:使用第一步输出的直方图结果,运用巴氏系数(Bhattachary

  • java指纹识别以及谷歌图片识别技术源码

    本文实例为大家分享了java指纹识别和图片识别源代码,供大家参考,具体内容如下 主类: import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.List; public class SimilarImageSearch { /** * @param args */ public static void main(String[] args) { List<String> hashCode

随机推荐