JAVA 进行图片中文字识别(准确度高)!!!

2022-07-25,,,,

OCR 识别文字项目

该项目 可以进行两种方式进行身份证识别

1. 使用百度接口

1.1 application-dev.yml配置

ocr:
  # 使用baiduOcr 需要有Ocr服务器 使用百度需要相应的百度账号即可
  useOcrType: baiduOcr
  # 需要OCR 的文件夹
  ocrFolderPath: E:\ocr-wait-image\16210910333-8e2fa7f52db04a538ed584c919ce33b1
  # 需要OCR 的文件
  ocrFile: H:\Desktop\test\14.jpg
  # 百度OCR 配置  https://cloud.baidu.com/doc/OCR/s/Nkibizxlf
  baiduOcr:
    # 使用token 形式
    useToken: false
    # 使用卡证识别接口 卡证识别一天500次免费(识别率高推荐) 通用识别50000次免费(识别率较低)
    useIdCard: true
    # 使用token 形式调用接口 token 通过接口获取(推荐使用sdk模式)
    token: XXXXXXXX
    idCardUrl: https://aip.baidubce.com/rest/2.0/ocr/v1/idcard
    idCardPrefix: id_card_side=front&image=
    generalBasicUrl: https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic
    generalBasicPrefix: image=
    # 不使用token sak形式调用接口(通过百度账号创建应用获取)
    appId: XXXXXXXXXX
    apiKey: XXXXXXXXXX
    secretKey: XXXXXXXXXX

1.2 创建百度应用

填入必填项即可

再次出来即有一个创建的应用

以上配置的appId,apiKey,secretKey 三项在这里获取

1.3 结果显示

获得结果会保存在这个文件夹

1.3 使用百度免费OCR 项目配置结束

1.4 主要代码展示

package com.ocr.baidu;

import com.baidu.aip.ocr.AipOcr;
import com.framework.config.OcrConfig;
import com.utils.Base64Util;
import com.utils.FileUtil;
import com.utils.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;

@Slf4j
public class BaiduOCRUtils {
    /**
     * 卡证识别
     */
    public static String idCardByToken(OcrConfig.BaiduOcr baiduOcr,String filePath) {
        String idCardPrefix = baiduOcr.getIdCardPrefix();
        String idCardUrl = baiduOcr.getIdCardUrl();
        String token = baiduOcr.getToken();
        // 请求url
        try {
            // 本地文件路径

            byte[] imgData = FileUtil.readFileByBytes(filePath);
            String imgStr = Base64Util.encode(imgData);
            String imgParam = URLEncoder.encode(imgStr, StandardCharsets.UTF_8.name());

            String param = idCardPrefix + imgParam;
            // 注意这里仅为了简化编码每一次请求都去获取access_token,线上环境access_token有过期时间, 客户端可自行缓存,过期后重新获取。
            return  HttpUtil.post(idCardUrl, token, param);
        } catch (Exception e) {
            log.error(e.getMessage());
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 通用文字识别
     */
    public static String generalBasicByToken(OcrConfig.BaiduOcr baiduOcr,String filePath) {
        String generalBasicPrefix = baiduOcr.getGeneralBasicPrefix();
        String generalBasicUrl = baiduOcr.getGeneralBasicUrl();
        String token = baiduOcr.getToken();
        // 请求url
        try {
            // 本地文件路径
            byte[] imgData = FileUtil.readFileByBytes(filePath);
            String imgStr = Base64Util.encode(imgData);
            String imgParam = URLEncoder.encode(imgStr, StandardCharsets.UTF_8.name());

            String param = generalBasicPrefix + imgParam;
            // 注意这里仅为了简化编码每一次请求都去获取access_token,线上环境access_token有过期时间, 客户端可自行缓存,过期后重新获取。
            return HttpUtil.post(generalBasicUrl, token, param);
        } catch (Exception e) {
            log.error(e.getMessage());
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 通用文字识别 sdk
     */
    public static JSONObject generalBasicBySdk(OcrConfig.BaiduOcr baiduOcr,String filePath) {
        String appId = baiduOcr.getAppId();
        String apiKey = baiduOcr.getApiKey();
        String secredKey = baiduOcr.getSecretKey();
        AipOcr client = new AipOcr(appId, apiKey, secredKey);
        // 可选:设置网络连接参数
        client.setConnectionTimeoutInMillis(2000);
        client.setSocketTimeoutInMillis(60000);
        return client.basicGeneral(filePath, new HashMap<>());
    }
    /**
     * 身份证文字识别 sdk
     */
    public static JSONObject idCardBySdk(OcrConfig.BaiduOcr baiduOcr,String filePath) {
        String appId = baiduOcr.getAppId();
        String apiKey = baiduOcr.getApiKey();
        String secredKey = baiduOcr.getSecretKey();
        AipOcr client = new AipOcr(appId, apiKey, secredKey);
        // 可选:设置网络连接参数
        client.setConnectionTimeoutInMillis(2000);
        client.setSocketTimeoutInMillis(60000);
        return client.idcard(filePath,"front", new HashMap<>());
    }
}

2. 使用百度开源项目PaddleHub

PS: 识别通过paddle(python 运行) ,JAVA 进行结果处理

2.1 按照教程安装PaddleHub

2.2 application-dev.yml配置

ocr:
  paddleOcr:
    # 使用本地
    url: 192.168.0.106
    port: 8866
    moduleMap:
      # 文字识别OCR 安装 https://www.paddlepaddle.org.cn/hubdetail?name=chinese_ocr_db_crnn_mobile&en_category=TextRecognition
      chinese_ocr_db_crnn_mobile: 1.1.1
      # 人脸识别OCR(识别身份证正面或手持身份证) 安装  https://www.paddlepaddle.org.cn/hubdetail?name=pyramidbox_lite_server&en_category=FaceDetection
      pyramidbox_lite_server: 1.2.0
    # 是否分析
    analysis: false

2.3 结果显示

获得结果会保存在这个文件夹

2.4 主要代码展示

package com.ocr.paddle;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.ocr.paddle.domain.LocalHubOcrResultDTO;
import com.ocr.paddle.domain.OCRHubResultDTO;
import com.utils.Base64Util;
import com.utils.FileUtil;
import com.utils.HttpClientUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
public class LocalHubOcrUtils {

    public static List<LocalHubOcrResultDTO> localAllOcr(String textUrl, String faceUrl, List<File> allFiles) {
        long l = System.currentTimeMillis();
        List<LocalHubOcrResultDTO> localOcrResultDTOList = Lists.newArrayList();
        int urlCount = 0;
        boolean useTextUrl = false;
        boolean useFaceUrl = false;
        if (StringUtils.isEmpty(textUrl)) {
            log.info("不进行文字识别");
        } else {
            urlCount++;
            useTextUrl = true;
            log.info("需要进行文字识别");
        }
        if (StringUtils.isEmpty(faceUrl)) {
            log.info("不进行人脸识别");
        } else {
            urlCount++;
            useFaceUrl = true;
            log.info("需要进行人脸识别");
        }
        int ocrCount = allFiles.size() * urlCount;
        log.info("预估进行OCR" + ocrCount + "次");
        if (ocrCount == 0) {
            return localOcrResultDTOList;
        }

        int textIndex = 0;
        int faceIndex = 0;
        // 本地文件路径
        Map<String, String> partentFile = allFiles.stream().collect(Collectors.toMap(File::getName, File::getParent, (e1, e2) -> e1));
        for (File imageFile : allFiles) {
            List<OCRHubResultDTO> ocrHubResultDTOS = Lists.newArrayList();

            byte[] imgData = new byte[0];
            try {
                imgData = FileUtil.readFileByBytes(imageFile);
            } catch (IOException e) {
                log.error("图片读取错误");
                continue;
            }
            String imgStr = Base64Util.encode(imgData);
            JSONObject jsonObject = new JSONObject();
            List<String> imageParams = Lists.newArrayList();
            imageParams.add(imgStr);
            jsonObject.put("images", imageParams);

            String textResult = "";
            if (useTextUrl) {
                textResult = HttpClientUtils.sendJsonStr(textUrl, jsonObject.toJSONString());
                textIndex++;
                log.info("已进行文字OCR" + textIndex + "次");
                if (StringUtils.isEmpty(textResult)) {
                    log.error("获取文字接口失败");
                    log.info("还需进行" + (ocrCount - faceIndex - textIndex) + "次");
                    continue;
                }
                JSONObject resultTest = (JSONObject) JSONObject.parse(textResult);
                JSONArray textResultsArray = resultTest.getJSONArray("results");
                if (textResultsArray == null){
                    log.error("返回值错误,错误信息为:" + textResult);
                }

                for (Object o : textResultsArray) {
                    JSONObject j = (JSONObject) o;
                    JSONArray data = j.getJSONArray("data");
                    for (Object datum : data) {
                        JSONObject jo = (JSONObject) datum;
                        jo.remove("text_box_position");
                        OCRHubResultDTO ocrHubResultDTO = jo.toJavaObject(OCRHubResultDTO.class);
                        ocrHubResultDTOS.add(ocrHubResultDTO);
                    }
                }

            }
            int faceCount = 0;
            String faceResult = "";
            if (useFaceUrl) {
                faceResult = HttpClientUtils.sendJsonStr(faceUrl, jsonObject.toJSONString());
                faceIndex++;
                log.info("已进行人脸OCR" + faceIndex + "次");
                if (StringUtils.isEmpty(faceResult)) {
                    log.error("获取人脸识别接口失败");
                    log.info("还需进行" + (ocrCount - faceIndex - textIndex) + "次");
                    continue;
                }
                JSONObject resultFace = (JSONObject) JSONObject.parse(faceResult);
                JSONArray faceResultsArray = resultFace.getJSONArray("results");
                for (Object o : faceResultsArray) {
                    JSONObject j = (JSONObject) o;
                    JSONArray data = j.getJSONArray("data");
                    faceCount = data.size();
                }
            }

            log.info("还需进行" + (ocrCount - faceIndex - textIndex) + "次");
            localOcrResultDTOList.add(new LocalHubOcrResultDTO(imageFile.getAbsolutePath(), imageFile.getParent(), ocrHubResultDTOS, faceCount));
        }
        log.info("OCR 总耗时" + (System.currentTimeMillis() - l) / 1000 + "S");
        log.info("OCR 次数" + ocrCount + "次");
        log.info("OCR 平均耗时" + (System.currentTimeMillis() - l) / 1000 / ocrCount + "s");
        return localOcrResultDTOList;
    }

    private static void func(File file, List<File> fileList) {
        File[] fs = file.listFiles();
        for (File f : fs) {
            if (f.isDirectory()) {
                //若是目录,则递归打印该目录下的文件
                func(f, fileList);
            }
            if (f.isFile()) {
                String imageName = f.getName();
                boolean isJpg = imageName.endsWith(".jpg");
                boolean isJPG = imageName.endsWith(".JPG");
                boolean isPng = imageName.endsWith(".png");
                if (isJPG || isPng || isJpg) {
                    //若是图片加入列表
                    fileList.add(f);
                }
            }
        }
    }
}

sJpg = imageName.endsWith(".jpg");
boolean isJPG = imageName.endsWith(".JPG");
boolean isPng = imageName.endsWith(".png");
if (isJPG || isPng || isJpg) {
//若是图片加入列表
fileList.add(f);
}
}
}
}
}


本文地址:https://blog.csdn.net/AirOrange_qi/article/details/112102739

《JAVA 进行图片中文字识别(准确度高)!!!.doc》

下载本文的Word格式文档,以方便收藏与打印。