当前位置:首页 > 开发教程 > java教程 >

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

时间:2022-04-21 17:31 来源:未知 作者:等迩宛在水中央 收藏

这篇文章主要为大家详细介绍了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;
  }

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

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


java教程阅读排行

最新文章