opencv结合微信二维码识别功能实现图片二维码识别

本文介绍了如何在Java中利用OpenCV结合微信的二维码识别算法进行高精度的二维码识别。通过编译OpenCV源码并引入必要的库文件,如dll和so,实现了在Windows上运行的代码。虽然在Linux环境下部署较为复杂,但作者指出微信的识别功能对于复杂背景的二维码识别表现出色,优于传统方法。
摘要由CSDN通过智能技术生成

    opencv本身有二维码识别功能,但是识别效果不是很好,它对二维码图片要求较高,虽然可以有图片处理,甚至抠出二维码区域,但是整体识别与微信二维码识别功能还是有差距的。

    微信二维码识别,采用了机器学习算法,加入了CNN模型的概念,它作为三方库,开源给了opencv,而且支持java语言,不过要使用,需要结合操作系统做编译,需要下载opencv源码,还需要下载opencv_contrib代码,这里面就是一些三方库,微信二维码就在这里面。

    源码编译需要生成opencv_java45x.dll,opencv-java45x.so,opencv_java45x.jar等文件,不仅需要动态库,还需要jar包。

    在windows系统下,动态库是dll类型,在linux下动态库就是so类型。如果你能下载到opencv-4.x版本的jar,dll,so文件,可以直接使用,如果没有,就需要手动编译(编译过程非常复杂,建议不要轻易尝试)。

    有了jar,动态库,就很方便了,无需很复杂的设置,做过java开发的肯定知道jar需要加入类路径下,动态库只需要指定一个位置,java能像读文件一样加载到就可以了。

    这里以windows系统为例,所需的文件就是opencv-453.jar和opencv_java453.dll动态库,如果是maven项目,我们可以将opencv-453.jar作为本地jar加入项目中。

<dependency>
      <groupId>org</groupId>
      <artifactId>opencv</artifactId>
      <version>453</version>
      <scope>system</scope>
      <systemPath>${project.basedir}\src\main\resources\opencvlib\opencv-453.jar</systemPath>
    </dependency>

   java代码如下:

package org.example;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.wechat_qrcode.WeChatQRCode;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.File;
import java.net.URL;
import java.util.List;

public class WeChatQRCodeTool {

    private static volatile  WeChatQRCodeTool instance;
    private static volatile WeChatQRCode detector;

    private WeChatQRCodeTool(){
        System.setProperty("java.awt.headless","true");
        URL url = null;
        String os = System.getProperty("os.name");
        if(os.startsWith("Linux")){
            url = ClassLoader.getSystemResource("opencvlib/libopencv_java452.so");
            System.load(url.getPath());
            detector = new org.opencv.wechat_qrcode.WeChatQRCode();
        }else{
            url = ClassLoader.getSystemResource("opencvlib/opencv_java452.dll");
            System.load(url.getPath());
            ClassLoader cl = WeChatQRCodeTool.class.getClassLoader();
            URL detectprototxt = cl.getResource("opencvlib/detect.prototxt");
            URL detectcaffemodel =cl.getResource("opencvlib/detect.caffemodel");
            URL srprototxt=cl.getResource("opencvlib/sr.prototxt");
            URL srcaffemodel =cl.getResource("opencvlib/sr.caffemodel");
            detector = new org.opencv.wechat_qrcode.WeChatQRCode(
                    detectprototxt.getPath().substring(1),
                    detectcaffemodel.getPath().substring(1),
                    srprototxt.getPath().substring(1),
                    srcaffemodel.getPath().substring(1));
        }
    }

    public static WeChatQRCodeTool getInstance(){
        if(instance==null){
            synchronized (WeChatQRCodeTool.class){
                if(instance==null){
                    instance = new WeChatQRCodeTool();
                }
            }
        }
        return instance;
    }

    public static Mat bufImg2Mat(BufferedImage original, int imgType, int matType) {
        if (original == null) {
            throw new IllegalArgumentException("original == null");
        }
        byte[] pixels = null;
        // Don't convert if it already has correct type
        if (original.getType() != imgType) {

            // Create a buffered image
            BufferedImage image = new BufferedImage(original.getWidth(), original.getHeight(), imgType);

            // Draw the image onto the new buffer
            Graphics2D g = image.createGraphics();
            try {
                g.setComposite(AlphaComposite.Src);
                g.drawImage(original, 0, 0, null);
                pixels = ((DataBufferByte)image.getRaster().getDataBuffer()).getData();
            } finally {
                g.dispose();
            }
        } else {
            pixels = ((DataBufferByte) original.getRaster().getDataBuffer()).getData();
        }
        Mat mat = Mat.eye(original.getHeight(), original.getWidth(), matType);
        mat.put(0, 0, pixels);
        return mat;
    }

    public String decode(BufferedImage srcImage) {

        int cvtype = CvType.CV_8UC3;
        if(srcImage.getType() == BufferedImage.TYPE_BYTE_GRAY) {
            cvtype = CvType.CV_8UC1;
        }
        Mat image = bufImg2Mat(srcImage, srcImage.getType(), cvtype);
        List<String> result2 = detector.detectAndDecode(image);
        if (result2 != null && result2.size() > 0) {
            return result2.get(0);
        }
        return null;
    }

    public String decodeQRCodeByPath(String qrCodePath){
        String qrCodeText = null;
        try {
            BufferedImage image = ImageIO.read(new File(qrCodePath));
            qrCodeText = decode(image);
        }catch (Exception e){
            e.printStackTrace();
        }
        return qrCodeText;
    }


    public static void main(String[] args) {
        String img = "C:\\Users\\86159\\Pictures\\qr-3.jpg";
        String result = getInstance().decodeQRCodeByPath(img);
        System.out.println(result);
    }
}

    示例图片如下:

    这个二维码图片,在一个大图中,人眼可以看,但是普通的二维码识别基本不可能识别,但是使用微信二维码识别,没有任何问题。识别结果如下所示:

    本人尝试过很多二维码图片,使用微信识别,基本一试一个准,果断放弃com.google.zxing提供的二维码识别功能。

    不得不佩服微信二维码识别功能的强大,再回过头来想想,这里面使用了深度学习的内容,比如CNN模型,虽然不懂,感觉已经很厉害了。

    本人在尝试过程中,发现,很多文章提到,Java使用微信二维码识别功能,需要下载模型文件,也就是代码中提到的:detect.prototxt,detect.caffemodel,sr.prototxt,sr.caffemodel文件,其实,不用这几个文件,也是可以的。

URL detectprototxt = cl.getResource("opencvlib/detect.prototxt");
URL detectcaffemodel =cl.getResource("opencvlib/detect.caffemodel");
URL srprototxt=cl.getResource("opencvlib/sr.prototxt");
URL srcaffemodel =cl.getResource("opencvlib/sr.caffemodel");
/*
detector = new org.opencv.wechat_qrcode.WeChatQRCode(
		detectprototxt.getPath().substring(1),
		detectcaffemodel.getPath().substring(1),
		srprototxt.getPath().substring(1),
		srcaffemodel.getPath().substring(1));*/
detector = new org.opencv.wechat_qrcode.WeChatQRCode();

    本文写到这里,其实也差不多了,但是这种识别只能在windows下,java开发,尤其是服务端,最后的代码99%都是部署在linux服务器下的,那么,本文介绍的办法无需改动,但是linux环境要求比较特殊。不仅需要opencv-453.jar,opencv_java453.so 文件,动态库在调用的时候,还需要一些其他的opencv依赖,这么一来,还是需要编译opencv+opencv_contrib。

   我在尝试部署到linux下发现,如果一个机器编译了so文件,可以复制到其他机器使用,其他机器就不需要编译了,但是这些动态库太多了,还是很麻烦的。

    本文代码以及所需资源都在这里:opencvtest: opencv结合微信二维码识别 (gitee.com)

OpenCvSharp微信二维码引擎Demo是一个基于OpenCvSharp库开发的针对微信二维码识别的示例程序。微信二维码引擎是指能够识别微信扫一扫功能中的二维码的引擎。下面我将对这个Demo进行简要介绍。 首先,这个Demo使用了OpenCvSharp库,该库是OpenCV的C#封装,能够方便地在C#中使用OpenCV功能。由于微信二维码引擎是基于图像识别的,OpenCV提供了强大的图像处理和计算机视觉功能,因此选择OpenCvSharp作为开发工具十分合适。 这个Demo主要实现微信二维码识别功能。在使用之前,首先需要安装OpenCvSharp库,并完成相关的配置。然后,我们可以通过该Demo将微信二维码图片加载进来,使用OpenCvSharp库提供的图像处理方法进行处理和分析。 在识别过程中,Demo会利用OpenCvSharp库中的二维码识别算法来检测和解码图像中的二维码。通过对二维码的解码,我们可以获取到其中存储的信息,比如链接、文本等。 最后,Demo会将识别出的二维码信息以文本的形式输出,方便用户查看和使用。此外,我们还可以根据需要进行二维码的进一步处理,比如裁剪、旋转等。 总之,OpenCvSharp微信二维码引擎Demo是一个基于OpenCvSharp库开发的示例程序,能够实现微信二维码识别功能。通过使用这个Demo,我们可以了解和学习如何使用OpenCvSharp库进行微信二维码识别,从而为后续的二维码应用开发提供了基础。
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luffy5459

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值