欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java實(shí)現(xiàn)識(shí)別二維碼圖片功能方法詳解與實(shí)例源碼

 更新時(shí)間:2022年12月10日 09:07:26   作者:啊猿  
這篇文章主要介紹了java實(shí)現(xiàn)識(shí)別二維碼圖片,java無(wú)法識(shí)別二維碼情況下對(duì)二維碼圖片調(diào)優(yōu)功能方法與實(shí)例源碼,需要的朋友可以參考下

首先添加依賴

<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識(shí)別二維碼代碼實(shí)現(xiàn)

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ù)雜模式開啟(我使用這種方式就可以識(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");//二維碼圖片路徑
}

Java二維碼圖片調(diào)優(yōu)

如果上述不能識(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;
     }
 
     /**
     * 二值化后的圖像的開運(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;
     }

第二種方法:

package com.ghl.magicbox.qrcode.b;
import cn.hutool.core.util.IdUtil;
import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.CLAHE;
import org.opencv.imgproc.Imgproc;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * @Author: GHL
 * @Date: 2022/2/18
 * @Description:
 */
@Slf4j
public class QRCodeUtil {
    /**
     * 默認(rèn)放大倍數(shù)
     */
    private final static int TIMES = 4;
    static {
        // 加載Opencv的dll文件
        URL url = ClassLoader.getSystemResource("lib/opencv_java3416.dll");
        System.load(url.getPath());
    }
    /**
     * 復(fù)雜圖片二維碼解析
     *
     * @param file
     * @return
     */
    public static String complexDecode(File file) {
        String tempFilePath = null;
        try {
            log.debug("QRCodeUtil -> complexDecode() fileName:{}",file.getName());
            tempFilePath = getFilePath(file.getName());
            //第一次解析:直接解析
            log.debug("QRCodeUtil -> complexDecode() firstDecode begin by:{}",file.getName());
            String codeDataByFirst = simpleDecode(file);
            if (codeDataByFirst != null) {
                return codeDataByFirst;
            }
            //第二次解析:定位圖中二維碼,截圖放大
            log.debug("QRCodeUtil -> complexDecode() secondDecode begin by:{}",file.getName());
            piz(file.getAbsolutePath(),tempFilePath);
            String codeDataBySecond = simpleDecode(tempFilePath);
            if (codeDataBySecond != null) {
                return codeDataBySecond;
            }
            //第三次解析:將截圖后二維碼二值化
            log.debug("QRCodeUtil -> complexDecode() thirdDecode begin by:{}",file.getName());
            Mat mat = binarization(tempFilePath);
            String codeDataByThird = simpleDecode(tempFilePath);
            if (codeDataByThird != null) {
                return codeDataByThird;
            }
            //第四次解析: 進(jìn)行限制對(duì)比度的自適應(yīng)直方圖均衡化處理
            log.debug("QRCodeUtil -> complexDecode() fourthDecode begin by:{}",file.getName());
            limitContrast(tempFilePath,mat);
            String codeDataByFourth = simpleDecode(tempFilePath);
            if (codeDataByFourth != null) {
                log.debug("QRCodeUtil -> complexDecode() fileName:{} state:{} result:{}",file.getName(),Boolean.TRUE,codeDataByFourth);
                return codeDataByFourth;
            }
            log.debug("QRCodeUtil -> complexDecode() fileName:{} state:{}",file.getName(), Boolean.FALSE);
        } finally {
            file.deleteOnExit();
            if (tempFilePath != null){
                file = new File(tempFilePath);
                file.deleteOnExit();
            }
        }
        return null;
    }
    /**
     * 復(fù)雜圖片二維碼解析
     *
     * @param path
     * @return
     */
    public static String complexDecode(String path) {
        return complexDecode(new File(path));
    }
    /**
     * 復(fù)雜圖片二維碼解析
     *
     * @param originalFile
     * @return
     */
    public static String complexDecode(MultipartFile originalFile) {
        String filePath = getFilePath(originalFile.getOriginalFilename());
        File mkFile = new File(filePath);
        if (!mkFile.exists()){
            mkFile.mkdir();
            log.debug("QRCodeUtil -> complexDecode() create temp file ready by:{}",originalFile.getOriginalFilename());
        }
        try {
            originalFile.transferTo(mkFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return complexDecode(mkFile);
    }
    /**
     * 簡(jiǎn)單二維碼解析
     *
     * @param path
     * @return
     */
    public static String simpleDecode(String path) {
        return simpleDecode(new File(path));
    }
    /**
     * 簡(jiǎn)單二維碼解析
     *
     * @param file
     * @return zxing解析率實(shí)測(cè)與opencv差不多。所以直接使用zxing解析
     * zxing版本高能提高識(shí)別率
     */
    public static String simpleDecode(File file) {
        try {
            BufferedImage image = ImageIO.read(file);
            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);
            return result.getText();
        } catch (Exception e) {
            return null;
        }
    }
    /**
     * 獲取臨時(shí)文件存儲(chǔ)地址
     */
    @SneakyThrows
    private static String getFilePath(String fileName) {
        String path = ResourceUtils.getFile("classpath:").getPath() + "/static/decodeWork/";
        File folder = new File(path);
        if (!folder.exists()){
            folder.mkdirs();
        }
        String contentType = fileName.contains(".") ? fileName.substring(fileName.lastIndexOf(".") + 1) : null;
        String newFileName = IdUtil.getSnowflake(0, 0).nextId() + "." + contentType;
        return path + newFileName;
    }
    /**
     * 定位 - > 截取 -> 放大
     * @param filePath
     * @param tempFilePath
     */
    private static void piz(String filePath, String tempFilePath) {
        Mat srcGray = new Mat();
        Mat src = Imgcodecs.imread(filePath, 1);
        List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
        List<MatOfPoint> markContours = new ArrayList<MatOfPoint>();
        //System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
//        URL url = ClassLoader.getSystemResource("lib/opencv_java3416.dll");
//        System.load(url.getPath());
        //圖片太小就放大
        if (src.width() * src.height() < 90000) {
            Imgproc.resize(src, src, new Size(800, 600));
        }
        // 彩色圖轉(zhuǎn)灰度圖
        Imgproc.cvtColor(src, srcGray, Imgproc.COLOR_RGB2GRAY);
        // 對(duì)圖像進(jìn)行平滑處理
        Imgproc.GaussianBlur(srcGray, srcGray, new Size(3, 3), 0);
        Imgproc.Canny(srcGray, srcGray, 112, 255);
        Mat hierarchy = new Mat();
        Imgproc.findContours(srcGray, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_NONE);
        for (int i = 0; i < contours.size(); i++) {
            MatOfPoint2f newMtx = new MatOfPoint2f(contours.get(i).toArray());
            RotatedRect rotRect = Imgproc.minAreaRect(newMtx);
            double w = rotRect.size.width;
            double h = rotRect.size.height;
            double rate = Math.max(w, h) / Math.min(w, h);
            // 長(zhǎng)短軸比小于1.3,總面積大于60
            if (rate < 1.3 && w < srcGray.cols() / 4 && h < srcGray.rows() / 4 && Imgproc.contourArea(contours.get(i)) > 60) {
                // 計(jì)算層數(shù),二維碼角框有五層輪廓(有說(shuō)六層),這里不計(jì)自己這一層,有4個(gè)以上子輪廓?jiǎng)t標(biāo)記這一點(diǎn)
                double[] ds = hierarchy.get(0, i);
                if (ds != null && ds.length > 3) {
                    int count = 0;
                    if (ds[3] == -1) {
                        //最外層輪廓排除
                        continue;
                    }
                    // 計(jì)算所有子輪廓數(shù)量
                    while ((int) ds[2] != -1) {
                        ++count;
                        ds = hierarchy.get(0, (int) ds[2]);
                    }
                    if (count >= 4) {
                        markContours.add(contours.get(i));
                    }
                }
            }
        }
        /*
         * 二維碼有三個(gè)角輪廓,正常需要定位三個(gè)角才能確定坐標(biāo),本工具當(dāng)識(shí)別到兩個(gè)點(diǎn)的時(shí)候也將二維碼定位出來(lái);
         * 當(dāng)識(shí)別到兩個(gè)及兩個(gè)以上點(diǎn)時(shí),取兩個(gè)點(diǎn)中間點(diǎn),往四周擴(kuò)散截取 當(dāng)小于兩個(gè)點(diǎn)時(shí),直接返回
         */
        if (markContours.size() == 0) {
            return;
        } else if (markContours.size() == 1) {
            capture(markContours.get(0), src ,tempFilePath);
        } else {
            List<MatOfPoint> threePointList = new ArrayList<>();
            threePointList.add(markContours.get(0));
            threePointList.add(markContours.get(1));
            capture(threePointList, src,tempFilePath);
        }
    }
    /**
     * 當(dāng)只識(shí)別到二維碼的兩個(gè)定位點(diǎn)時(shí),根據(jù)兩個(gè)點(diǎn)的中點(diǎn)進(jìn)行定位
     * @param threePointList
     * @param src
     */
    private static void capture(List<MatOfPoint> threePointList, Mat src, String tempFilePath) {
        Point p1 = centerCal(threePointList.get(0));
        Point p2 = centerCal(threePointList.get(1));
        Point centerPoint = new Point((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
        double width = Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y) + 50;
        // 設(shè)置截取規(guī)則
        Rect roiArea = new Rect((int) (centerPoint.x - width) > 0 ? (int) (centerPoint.x - width) : 0,
                (int) (centerPoint.y - width) > 0 ? (int) (centerPoint.y - width) : 0, (int) (2 * width),
                (int) (2 * width));
        // 截取二維碼
        Mat dstRoi = new Mat(src, roiArea);
        // 放大圖片
        Imgproc.resize(dstRoi, dstRoi, new Size(TIMES * width, TIMES * width));
        Imgcodecs.imwrite(tempFilePath, dstRoi);
    }
    /**
     * 針對(duì)對(duì)比度不高的圖片,只能識(shí)別到一個(gè)角的,直接以該點(diǎn)為中心截取
     * @param matOfPoint
     * @param src
     * @param tempFilePath
     */
    private static void capture(MatOfPoint matOfPoint, Mat src, String tempFilePath) {
        Point centerPoint = centerCal(matOfPoint);
        int width = 200;
        Rect roiArea = new Rect((int) (centerPoint.x - width) > 0 ? (int) (centerPoint.x - width) : 0,
                (int) (centerPoint.y - width) > 0 ? (int) (centerPoint.y - width) : 0, (int) (2 * width),
                (int) (2 * width));
        // 截取二維碼
        Mat dstRoi = new Mat(src, roiArea);
        // 放大圖片
        Imgproc.resize(dstRoi, dstRoi, new Size(TIMES * width, TIMES * width));
        Imgcodecs.imwrite(tempFilePath, dstRoi);
    }
    /**
     * 獲取輪廓的中心坐標(biāo)
     * @param matOfPoint
     * @return
     */
    private static Point centerCal(MatOfPoint matOfPoint) {
        double centerx = 0, centery = 0;
        MatOfPoint2f mat2f = new MatOfPoint2f(matOfPoint.toArray());
        RotatedRect rect = Imgproc.minAreaRect(mat2f);
        Point vertices[] = new Point[4];
        rect.points(vertices);
        centerx = ((vertices[0].x + vertices[1].x) / 2 + (vertices[2].x + vertices[3].x) / 2) / 2;
        centery = ((vertices[0].y + vertices[1].y) / 2 + (vertices[2].y + vertices[3].y) / 2) / 2;
        Point point = new Point(centerx, centery);
        return point;
    }
    /**
     * 二值化圖像
     * @param filePath 圖像地址
     */
    private static Mat binarization(String filePath){
        Mat mat = Imgcodecs.imread(filePath, 1);
        // 彩色圖轉(zhuǎn)灰度圖
        Imgproc.cvtColor(mat, mat, Imgproc.COLOR_RGB2GRAY);
        // 對(duì)圖像進(jìn)行平滑處理
        Imgproc.blur(mat, mat, new Size(3, 3));
        // 中值去噪
        Imgproc.medianBlur(mat, mat, 5);
        // 這里定義一個(gè)新的Mat對(duì)象,主要是為了保留原圖,未下次處理做準(zhǔn)備
        Mat mat2 = new Mat();
        // 根據(jù)OTSU算法進(jìn)行二值化
        Imgproc.threshold(mat, mat2, 205, 255, Imgproc.THRESH_OTSU);
        // 生成二值化后的圖像
        Imgcodecs.imwrite(filePath, mat2);
        return mat;
    }
    /**
     * 圖像進(jìn)行限制對(duì)比度的自適應(yīng)直方圖均衡化處理
     * @param filePath
     */
    public static void limitContrast(String filePath,Mat mat){
        CLAHE clahe = Imgproc.createCLAHE(2, new Size(8, 8));
        clahe.apply(mat, mat);
        Imgcodecs.imwrite(filePath, mat);
    }
    public static void main(String[] args) {
        String s = complexDecode("C:\\Users\\ghl\\Desktop\\b.jpg");
        System.out.println(s);
    }
}

更多關(guān)于java實(shí)現(xiàn)識(shí)別二維碼圖片功能文章請(qǐng)查看下面的相關(guān)鏈接

相關(guān)文章

  • Spring?Boot?集成JWT實(shí)現(xiàn)前后端認(rèn)證的示例代碼

    Spring?Boot?集成JWT實(shí)現(xiàn)前后端認(rèn)證的示例代碼

    小程序、H5應(yīng)用的快速發(fā)展,使得前后端分離已經(jīng)成為了趨勢(shì),本文主要介紹了Spring?Boot?集成JWT實(shí)現(xiàn)前后端認(rèn)證,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • springboot 使用yml配置文件給靜態(tài)變量賦值教程

    springboot 使用yml配置文件給靜態(tài)變量賦值教程

    這篇文章主要介紹了springboot 使用yml配置文件給靜態(tài)變量賦值教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-04-04
  • java實(shí)現(xiàn)單鏈表中是否有環(huán)的方法詳解

    java實(shí)現(xiàn)單鏈表中是否有環(huán)的方法詳解

    本篇文章介紹了,用java實(shí)現(xiàn)單鏈表中是否有環(huán)的方法詳解。需要的朋友參考下
    2013-05-05
  • Java線程間共享與協(xié)作詳細(xì)介紹

    Java線程間共享與協(xié)作詳細(xì)介紹

    這篇文章主要介紹了Java線程間共享與協(xié)作詳細(xì)介紹,Java?支持多個(gè)線程同時(shí)訪問(wèn)一個(gè)對(duì)象或者對(duì)象的成員變量,更多相關(guān)介紹需要的朋友可以參考一下
    2022-09-09
  • springboot自動(dòng)裝配的源碼與流程圖

    springboot自動(dòng)裝配的源碼與流程圖

    在日常的開發(fā)過(guò)程中Spring Boot自動(dòng)裝配的特性給我們開發(fā)減少了很多重復(fù)性的工作,這篇文章主要給大家介紹了關(guān)于springboot自動(dòng)裝配的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • springboot集成本地緩存Caffeine的三種使用方式(小結(jié))

    springboot集成本地緩存Caffeine的三種使用方式(小結(jié))

    本文主要介紹了springboot集成本地緩存Caffeine的三種使用方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • Java自定義Enum的實(shí)現(xiàn)示例

    Java自定義Enum的實(shí)現(xiàn)示例

    Java中的自定義Enum類型是一種特殊的類,用于表示固定數(shù)量的常量值,本文主要介紹了Java自定義Enum的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12
  • Java實(shí)現(xiàn)監(jiān)控多個(gè)線程狀態(tài)的簡(jiǎn)單實(shí)例

    Java實(shí)現(xiàn)監(jiān)控多個(gè)線程狀態(tài)的簡(jiǎn)單實(shí)例

    下面小編就為大家?guī)?lái)一篇Java實(shí)現(xiàn)監(jiān)控多個(gè)線程狀態(tài)的簡(jiǎn)單實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-03-03
  • Java Websocket Canvas實(shí)現(xiàn)井字棋網(wǎng)絡(luò)游戲

    Java Websocket Canvas實(shí)現(xiàn)井字棋網(wǎng)絡(luò)游戲

    這篇文章主要介紹了Java Websocket Canvas實(shí)現(xiàn)井字棋網(wǎng)絡(luò)游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • SpringCloud Gateway的熔斷限流配置實(shí)現(xiàn)方法

    SpringCloud Gateway的熔斷限流配置實(shí)現(xiàn)方法

    Spring Cloud Gateway支持通過(guò)配置熔斷和限流機(jī)制來(lái)保證服務(wù)的穩(wěn)定性和可用性,可通過(guò)Hystrix和Resilience4j兩種方式實(shí)現(xiàn)。Hystrix通過(guò)注解和配置文件實(shí)現(xiàn)熔斷限流,Resilience4j通過(guò)編程式配置實(shí)現(xiàn)
    2023-04-04

最新評(píng)論