JAVA 进行图片中文字识别(准确度高)!!!
程序员文章站
2022-06-04 11:32:30
OCR 识别文字项目该项目 可以进行两种方式进行身份证识别1. 使用百度接口1.1 application-dev.yml配置ocr: # 使用baiduOcr 需要有Ocr服务器 使用百度需要相应的百度账号即可 useOcrType: baiduOcr # 需要OCR 的文件夹 ocrFolderPath: E:\ocr-wait-image\16210910333-8e2fa7f52db04a538ed584c919ce33b1 # 需要OCR 的文件 ocrFile:...
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 面试题关于包装类