这种自己琢磨的真的识别率很低啊,还不如去找个百度api,按次数花钱0.003一次识别。
(以jdk1.8为例)
zxing 包下载地址
地址: https://repo1.maven.org/maven2/com/google/zxing/ 版本选择:jdk1.6 core2.2 下载可用 jdk1.8 core 3.3.3下载可用
(下载的时候只要下载 core 3.3.3.jar 文件添加到项目依赖里面去就行,但是我还是推荐下载core-3.3.3-javadoc.jar 文件,可以看官方的注释, core-3.3.3-javadoc.jar 查看方法,直接用解压文件解压到文件夹之后,点开index.html就可以查看了,至于源码什么的就根据自己的需求看是否下载了)
解析清晰二维码
根据index.htm里面的介绍找到QRCodeReader这个类,明显就是我们需要的用来解析二维码的类,于是翻看文档,我们得出了几个重要的方法如下所示。
Binarizer binarizer = new HybridBinarizer(source);
BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
QRCodeReader reader=new QRCodeReader();
Result result = reader.decode(binaryBitmap, null);
String text=result.getText();
ImageLuminanceSource实现
所以接下来我们要去创建一个类ImageLuminanceSource 去继承LuminanceSource
package test;
import java.awt.image.BufferedImage;
import com.google.zxing.LuminanceSource;
public class ImageLuminanceSource extends LuminanceSource{
private final BufferedImage image;
public ImageLuminanceSource(BufferedImage image, int width,int height){
super(width, height);
this.image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
this.image.getGraphics().drawImage(image, 0, 0, null);
}
@Override
public byte[] getMatrix() {
int width = getWidth();
int height = getHeight();
int area = width * height;
byte[] matrix = new byte[area];
image.getRaster().getDataElements(0, 0, width, height, matrix);
return matrix;
}
@Override
public byte[] getRow(int y, byte[] row) {
if (y < 0 || y >= getHeight()) {
throw new IllegalArgumentException("不在图片的高度范围之内: " + y);
}
int width = getWidth();
if (row == null || row.length < width) {
row = new byte[width];
}
image.getRaster().getDataElements(0,0+y, width, 1, row);
return row;
}
}
完整的调用方法
public class testBarCode {
public static void main(String[] args) {
QRReader();
}
public static void QRReader() {
try {
File file = new File("D:\\test\\4.png");
BufferedImage image = ImageIO.read(file);
ImageLuminanceSource source=new ImageLuminanceSource(image,image.getWidth(),image.getHeight());
Binarizer binarizer = new HybridBinarizer(source);
BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
QRCodeReader reader=new QRCodeReader();
Map<DecodeHintType,Object> hints = new LinkedHashMap<DecodeHintType,Object>();
hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
Result result = reader.decode(binaryBitmap, null);
String text=result.getText();
System.out.println("解析的结果: " + result.getText());
} catch (IOException e1) {
e1.printStackTrace();
}catch(NotFoundException e) {
System.out.println("二维码没找到");
}catch (FormatException e)
{ System.out.println("二维码无法解析");
}catch(ChecksumException e) {
System.out.println("二维码纠错失败");
System.out.println(e.toString());
}
}
}
代码运行结果 解析的结果: http://www.baidu.com
稍微模糊的二维码
上面的示例,针对的是非常清晰的二维码,但是通常情况下,我们要识别的是纸上拍出来的二维码,如图,这个图是手机拍照的,然后又在电脑上进行缩放之后的截图,这种就比较困难了
新增ORCodeImageUtil
用上面的代码测试,就会发现连二维码都找不到了,这时候就要对传入的图像做一些处理,新增ORCodeImageUtil方法,根据自定义的颜色,以这个颜色作为分界线,比这个白就是白,比这个黑就是黑。
public class ORCodeImageUtil {
static int splitColor = 0xFF7f7f7f;
public static BufferedImage blackAndWhite(BufferedImage image) {
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
if (image.getRGB(x, y) >splitColor) {
image.setRGB(x, y, 0xFFFFFFFF);
}else {
image.setRGB(x, y, 0xFF000000);
}
}
}
return image;
}
}
完整的调用
public class testBarCode {
public static void main(String[] args) {
QRReader();
}
public static void QRReader() {
try {
File file = new File("D:\\test\\4.png");
BufferedImage image = ImageIO.read(file);
ImageLuminanceSource source=new ImageLuminanceSource(ORCodeImageUtil.blackAndWhite(image),image.getWidth(),image.getHeight());
Binarizer binarizer = new HybridBinarizer(source);
BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
QRCodeReader reader=new QRCodeReader();
Map<DecodeHintType,Object> hints = new LinkedHashMap<DecodeHintType,Object>();
hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
Result result = reader.decode(binaryBitmap, null);
String text=result.getText();
System.out.println("解析的结果: " + result.getText());
} catch (IOException e1) {
e1.printStackTrace();
}catch(NotFoundException e) {
System.out.println("二维码没找到");
}catch (FormatException e)
{ System.out.println("二维码无法解析");
}catch(ChecksumException e) {
System.out.println("二维码纠错失败");
System.out.println(e.toString());
}
}
}
处理后的结果图: 然后程序可以识别了 解析的结果: 20220128001
另一种:手机直接拍照出来的图
可以识别
还不行的
借鉴 增加了腐蚀和膨胀 https://blog.csdn.net/StrangeSir/article/details/88384585
ORCodeImageUtil 新增腐蚀和膨胀
package test;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.IOException;
public class ORCodeImageUtil {
static int splitColor = 0xFF7f7f7f;
public static BufferedImage blackAndWhite(BufferedImage image) {
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
if (image.getRGB(x, y) >splitColor) {
image.setRGB(x, y, 0xFFFFFFFF);
}else {
image.setRGB(x, y, 0xFF000000);
}
}
}
return image;
}
public static BufferedImage opening(BufferedImage bi) throws IOException {
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++) {
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];
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
if (getGray(arr, i, j, w, h) ==0) {
temp[i][j] = 0;
} else{
temp[i][j] = 255;
}
}
}
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++) {
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);
}
}
}
}
return bufferedImage;
}
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;
}
private static int getImageGray(int rgb) {
String argb = Integer.toHexString(rgb);
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.3 + g*0.59 + b*0.11);
return gray;
}
}
调用
public class testBarCode {
public static void main(String[] args) {
QRReader();
}
public static void QRReader() {
try {
File file = new File("D:\\test\\113.jpg");
BufferedImage image = ImageIO.read(file);
image= ORCodeImageUtil.blackAndWhite(image);
image= ORCodeImageUtil.opening(image);
ImageLuminanceSource source=new ImageLuminanceSource(image,image.getWidth(),image.getHeight());
Binarizer binarizer = new HybridBinarizer(source);
BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
QRCodeReader reader=new QRCodeReader();
Map<DecodeHintType,Object> hints = new LinkedHashMap<DecodeHintType,Object>();
hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
Result result = reader.decode(binaryBitmap, null);
String text=result.getText();
System.out.println("解析的结果: " + result.getText());
} catch (IOException e1) {
e1.printStackTrace();
}catch(NotFoundException e) {
System.out.println("二维码没找到");
}catch (FormatException e)
{ System.out.println("二维码无法解析");
}catch(ChecksumException e) {
System.out.println("二维码纠错失败");
System.out.println(e.toString());
}
}
public static void QRReaderWithResize() {
try {
File file = new File("D:\\test\\5.png");
BufferedImage image = ImageIO.read(file);
String str= QRCodeUtil.readToString(image);
System.out.println("输出"+str);
} catch (IOException e1) {
e1.printStackTrace();
}
}
public static BufferedImage getSubImage(BufferedImage image) {
int x=0;
int y=220;
int w=400;
int h=500;
if(x>image.getWidth()) {
x=image.getWidth();
}
if(y>image.getHeight()) {
y=image.getHeight();
}
if(w>image.getWidth()-x) {
w=image.getWidth()-x;
}
if(h>image.getHeight()-y) {
h=image.getHeight()-y;
}
return image.getSubimage(x,y,w,h);
}
}
但是说真的 还是不太行的样子
|