java實(shí)現(xiàn)識(shí)別二維碼圖片功能
本文實(shí)例為大家分享了java實(shí)現(xiàn)識(shí)別二維碼圖片功能,供大家參考,具體內(nèi)容如下
所需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>
實(shí)現(xiàn)的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; /** ?* 作用:二維碼識(shí)別(圖片) ?* 類名:QRCodeUtils ?**/ public class QRCodeUtils { ? ? /** ? ? ?* 解析二維碼,此方法解析一個(gè)路徑的二維碼圖片 ? ? ?* 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("圖片中內(nèi)容: ?"); ? ? ? ? ? ? System.out.println("content: " + result.getText()); ? ? ? ? ? ? content = result.getText(); ? ? ? ? } catch (IOException e) { ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } catch (NotFoundException e) { ?? ??? ??? ?//這里判斷如果識(shí)別不了帶LOGO的圖片,重新添加上一個(gè)屬性 ? ? ? ? ? ? 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>(); ?? ??? ??? ??? ?//設(shè)置編碼格式 ?? ??? ??? ??? ?hints.put(DecodeHintType.CHARACTER_SET, "UTF-8"); ?? ??? ??? ??? ?//設(shè)置優(yōu)化精度 ?? ??? ??? ??? ?hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE); ?? ??? ??? ??? ?//設(shè)置復(fù)雜模式開(kāi)啟(我使用這種方式就可以識(shí)別微信的二維碼了) ?? ??? ??? ??? ?hints.put(DecodeHintType.PURE_BARCODE,Boolean.TYPE); ?? ??? ??? ??? ?Result result = new MultiFormatReader().decode(binaryBitmap, hints);//解碼 ?? ??? ??? ??? ?System.out.println("圖片中內(nèi)容: ?"); ?? ??? ??? ??? ?System.out.println("content: " + result.getText()); ?? ??? ??? ??? ?content = result.getText(); ?? ??? ??? ?} catch (IOException e) { ?? ??? ??? ??? ?e.printStackTrace(); ?? ??? ??? ?} catch (NotFoundException e) { ?? ??? ??? ??? ?e.printStackTrace(); ?? ??? ??? ?} ? ? ? ? } ? ? ? ? return content; ? ? } }
測(cè)試
public static void main(String [] args){ ?? ?deEncodeByPath("D:\\Users/admin/Desktop/erweima/timg (5).jpg");//二維碼圖片路徑 }
輸出結(jié)果:
圖片中內(nèi)容:
content: http://qrcode.online
如果上述不能識(shí)別的話,那么就需要對(duì)圖片處理一次,然后再進(jìn)行識(shí)別,這里是個(gè)調(diào)優(yōu)圖片的工具類。
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); ? ? ? ? // 獲取當(dāng)前圖片的高,寬,ARGB ? ? ? ? int h = bi.getHeight(); ? ? ? ? int w = bi.getWidth(); ? ? ? ? int arr[][] = new int[w][h]; ? ? ? ? // 獲取圖片每一像素點(diǎn)的灰度值 ? ? ? ? for (int i = 0; i < w; i++) { ? ? ? ? ? ? for (int j = 0; j < h; j++) { ? ? ? ? ? ? ? ? // getRGB()返回默認(rèn)的RGB顏色模型(十進(jìn)制) ? ? ? ? ? ? ? ? arr[i][j] = getImageGray(bi.getRGB(i, j));// 該點(diǎn)的灰度值 ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? // 構(gòu)造一個(gè)類型為預(yù)定義圖像類型,BufferedImage ? ? ? ? BufferedImage bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_BINARY); ? ? ? ? // 和預(yù)先設(shè)置的閾值大小進(jìn)行比較,大的就顯示為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)); ? ? } ? ? /** ? ? ?* 圖像的灰度處理 ? ? ?* 利用浮點(diǎn)算法:Gray = R*0.3 + G*0.59 + B*0.11; ? ? ?* ? ? ?* @param rgb 該點(diǎn)的RGB值 ? ? ?* @return 返回處理后的灰度值 ? ? ?*/ ? ? private static int getImageGray(int rgb) { ? ? ? ? String argb = Integer.toHexString(rgb);// 將十進(jìn)制的顏色值轉(zhuǎn)為十六進(jìn)制 ? ? ? ? // argb分別代表透明,紅,綠,藍(lán) 分別占16進(jìn)制2位 ? ? ? ? int r = Integer.parseInt(argb.substring(2, 4), 16);// 后面參數(shù)為使用進(jìn)制 ? ? ? ? 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個(gè)灰度值再除以9,算出其相對(duì)灰度值 ? ? ?* ? ? ?* @param gray ? ? ?* @param x 要計(jì)算灰度的點(diǎn)的橫坐標(biāo) ? ? ?* @param y 要計(jì)算灰度的點(diǎn)的縱坐標(biāo) ? ? ?* @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; ? ? } ? ? /** ? ? ?* 二值化后的圖像的開(kāi)運(yùn)算:先腐蝕再膨脹(用于去除圖像的小黑點(diǎn)) ? ? ?* ? ? ?* @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); ? ? ? ? // 獲取當(dāng)前圖片的高,寬,ARGB ? ? ? ? int h = bi.getHeight(); ? ? ? ? int w = bi.getWidth(); ? ? ? ? int arr[][] = new int[w][h]; ? ? ? ? // 獲取圖片每一像素點(diǎn)的灰度值 ? ? ? ? for (int i = 0; i < w; i++) { ? ? ? ? ? ? for (int j = 0; j < h; j++) { ? ? ? ? ? ? ? ? // getRGB()返回默認(rèn)的RGB顏色模型(十進(jìn)制) ? ? ? ? ? ? ? ? arr[i][j] = getImageGray(bi.getRGB(i, j));// 該點(diǎn)的灰度值 ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? 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); ? ? ? ? // 臨時(shí)存儲(chǔ)腐蝕后的各個(gè)點(diǎn)的亮度 ? ? ? ? int temp[][] = new int[w][h]; ? ? ? ? // 1.先進(jìn)行腐蝕操作 ? ? ? ? for (int i = 0; i < w; i++) { ? ? ? ? ? ? for (int j = 0; j < h; j++) { ? ? ? ? ? ? ? ? /* ? ? ? ? ? ? ? ? ?* 為0表示改點(diǎn)和周圍8個(gè)點(diǎn)都是黑,則該點(diǎn)腐蝕操作后為黑 ? ? ? ? ? ? ? ? ?* 由于公司圖片態(tài)模糊,完全達(dá)到9個(gè)點(diǎn)全為黑的點(diǎn)太少,最后效果很差,故改為了小于30 ? ? ? ? ? ? ? ? ?* (寫30的原因是,當(dāng)只有一個(gè)點(diǎn)為白,即總共255,調(diào)用getGray方法后得到255/9 = 28) ? ? ? ? ? ? ? ? ?*/ ? ? ? ? ? ? ? ? if (getGray(arr, i, j, w, h) < 30) { ? ? ? ? ? ? ? ? ? ? temp[i][j] = 0; ? ? ? ? ? ? ? ? } else{ ? ? ? ? ? ? ? ? ? ? temp[i][j] = 255; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? // 2.再進(jìn)行膨脹操作 ? ? ? ? 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表示改點(diǎn)和周圍8個(gè)點(diǎn)都是黑,則該點(diǎn)腐蝕操作后為黑 ? ? ? ? ? ? ? ? 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(); ? ? ? ? } ? ? } }
可以手動(dòng)測(cè)試,然后對(duì)改代碼的部分進(jìn)行調(diào)正對(duì)應(yīng)的參數(shù)-- gray變量里的計(jì)算進(jìn)行灰度調(diào)整
private static int getImageGray(int rgb) { ? ? ? ? String argb = Integer.toHexString(rgb);// 將十進(jìn)制的顏色值轉(zhuǎn)為十六進(jìn)制 ? ? ? ? // argb分別代表透明,紅,綠,藍(lán) 分別占16進(jìn)制2位 ? ? ? ? int r = Integer.parseInt(argb.substring(2, 4), 16);// 后面參數(shù)為使用進(jìn)制 ? ? ? ? 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; ? ? }
等調(diào)整之后,在對(duì)圖片進(jìn)行識(shí)別即可。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
談?wù)剬?duì)Java多態(tài)性的一點(diǎn)理解
多態(tài)就是指程序中定義的引用變量所指向的具體類型和通過(guò)該引用變量發(fā)出的方法調(diào)用在編程時(shí)并不確定,而是在程序運(yùn)行期間才確定,即一個(gè)引用變量倒底會(huì)指向哪個(gè)類的實(shí)例對(duì)象,該引用變量發(fā)出的方法調(diào)用到底是哪個(gè)類中實(shí)現(xiàn)的方法,必須在由程序運(yùn)行期間才能決定2017-08-08解決java頁(yè)面URL地址傳輸參數(shù)亂碼的方法
這篇文章主要介紹了解決java頁(yè)面URL地址傳輸參數(shù)亂碼的方法,URL地址參數(shù)亂碼問(wèn)題,算是老話重談了吧!需要的朋友可以參考下2015-09-09synchronized背后的monitor鎖實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了synchronized背后的monitor鎖實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09Spring Cloud實(shí)戰(zhàn)技巧之使用隨機(jī)端口
這篇文章主要給大家介紹了關(guān)于Spring Cloud實(shí)戰(zhàn)技巧之使用隨機(jī)端口的相關(guān)資料,文中介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面跟著小編一起來(lái)學(xué)習(xí)學(xué)習(xí)吧。2017-06-06MyBatis傳入?yún)?shù)為L(zhǎng)ist對(duì)象的實(shí)現(xiàn)
這篇文章主要介紹了MyBatis傳入?yún)?shù)為L(zhǎng)ist對(duì)象的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03java如何導(dǎo)出insert語(yǔ)句并生成sql腳本
這篇文章主要介紹了java導(dǎo)出insert語(yǔ)句并生成sql腳本的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06