想體驗下微信的二維碼掃描組件嗎? 直接擼代碼,搞起~~~
import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import java.awt.*; import java.awt.image.BufferedImage; import java.awt.image.DataBufferByte; import java.awt.image.WritableRaster; import java.net.URL; import java.util.List; /** * @program: test-wechatqrcode * @description: 微信二維碼掃描opencv庫方法調用 * @author: test * @create: 221-08-21 17:05
* 原創點贊:java+opencv4.5.3+wechatqrcode代碼細節和 自編譯類庫(帶下載地址) - 斷舍離-重學JAVA之路 - 博客園 (cnblogs.com) **/ public class WeChatQRCodeTool { private static volatile WeChatQRCodeTool instance; private static volatile org.opencv.wechat_qrcode.WeChatQRCode detector; //封裝成了工具類,所以做成了單例 private WeChatQRCodeTool() { System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
//微信提供的4個模型配置文件放在resource/wechatqrcode文件夾里,
//下載地址:WeChatCV/opencv_3rdparty: OpenCV - 3rdparty (github.com) ClassLoader cl = WeChatQRCodeTool.class.getClassLoader();
URL detectprototxt = cl.getResource("wechatqrcode/detect.prototxt");
URL detectcaffemodel =cl.getResource("wechatqrcode/detect.caffemodel");
URL srprototxt=cl.getResource("wechatqrcode/sr.prototxt");
URL srcaffemodel =cl.getResource("wechatqrcode/sr.caffemodel");
//實例化微信二維碼掃描對象
//如果打成jar,那么路徑需要換到外部磁盤存儲目錄。 detector = new org.opencv.wechat_qrcode.WeChatQRCode( detectprototxt.getPath().substring(1), //因為使用的getResource方法獲取的是URL對象,而這個構造方法里需要傳入File的路徑,所以substring1去掉/D:/xx開頭的/ 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; }
/**
* 這里提供一個bufferimage的入參。如果是File對象,可以用ImageIO.read()獲取一下bufferimage.
*原創點贊:
*/
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; } /** * BufferedImage轉換成Mat * * @param original 要轉換的BufferedImage * @param imgType bufferedImage的類型 如 BufferedImage.TYPE_3BYTE_BGR * @param matType 轉換成mat的type 如 CvType.CV_8UC3
* 這里如果不懂這些參數的話,建議寫死:BufferedImage.TYPE_3BYTE_BGR, CvType.CV_8UC3 */ 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; } /** * Mat轉換為BufferedImage */ public static BufferedImage matToBufferedImage(Mat mat) { if (mat.height() > 0 && mat.width() > 0) { BufferedImage image = new BufferedImage(mat.width(), mat.height(), BufferedImage.TYPE_3BYTE_BGR); WritableRaster raster = image.getRaster(); DataBufferByte dataBuffer = (DataBufferByte) raster.getDataBuffer(); byte[] data = dataBuffer.getData(); mat.get(0, 0, data); return image; } return null; } }
由於wechatqrcode屬於第三方擴展庫,不屬於opencv的主版本,所以opencv自帶的發布dll和jar里沒有。需要自編譯。花了我一天時間。具體參考:
Windows下聯合編譯opencv+opencv_contrib微信二維碼引擎_VQB01799的博客-CSDN博客
不想花費時間編譯的,可以使用下面我分享到 網盤的opencv_java453.dll鏈接庫和opencv-453.jar
鏈接: https://pan.baidu.com/s/1quxjnThcehg1yjzY5Tp8wA 提取碼: 4bj6 復制這段內容后打開百度網盤手機App,操作更方便哦
如果有幫到你, 請點個贊!!!
/** * Mat轉換為BufferedImage */ public static BufferedImage mat2img(Mat mat) { int dataSize = mat.cols() * mat.rows() * (int)mat.elemSize(); byte[] data = new byte[dataSize]; mat.get(0, 0, data); int type = mat.channels() == 1 ? 10 : 5; if (type == 5) { for (int i = 0; i < dataSize; i += 3) { byte blue = data[(i + 0)]; data[(i + 0)] = data[(i + 2)]; data[(i + 2)] = blue; } } BufferedImage image = new BufferedImage(mat.cols(), mat.rows(), type); image.getRaster().setDataElements(0, 0, mat.cols(), mat.rows(), data); return image; }