java实现识别二维码图片功能(java识别图片中的二维码)

网友投稿 1327 2022-08-03


java实现识别二维码图片功能(java识别图片中的二维码)

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

所需maven依赖

com.google.zxing

javase

3.2.1

com.google.zxing

core

3.3.3

实现的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 deEnchttp://odeByPath(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 hints = new HashMap();

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.allhwqVZread(new File(path));

LuminanceSource source = new BufferedImageLuminanceSource(image);

Binarizer binarizer = new HybridBinarizer(source);

BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);

Map hints = new HashMap();

//设置编码格式

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;

}

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


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:elasticsearch节点间通信的基础transport启动过程
下一篇:elasticsearch节点的transport请求发送处理分析
相关文章

 发表评论

暂时没有评论,来抢沙发吧~