package com.ruoyi.system.utils;
|
|
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONObject;
|
import com.baidu.aip.ocr.AipOcr;
|
import com.ruoyi.system.config.BaiduOCRConfig;
|
|
import lombok.extern.slf4j.Slf4j;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Component;
|
|
import java.io.File;
|
import java.util.HashMap;
|
import java.util.Map;
|
|
/**
|
* 百度OCR工具类
|
* 使用百度AI开放平台的OCR服务进行文字识别
|
* 支持通用文字识别、手写体识别等多种识别类型
|
*
|
* 使用示例:
|
* // 通用文字识别
|
* JSONObject result = BaiduOCRUtil.generalRecognize("path/to/image.jpg");
|
*
|
* // 手写体识别
|
* JSONObject result = BaiduOCRUtil.handwritingRecognize("path/to/image.jpg");
|
*/
|
@Component
|
@Slf4j
|
public class BaiduOCRUtil {
|
|
|
|
private static BaiduOCRConfig staticBaiduOcrConfig;
|
|
@Autowired
|
public void setBaiduOcrConfig(BaiduOCRConfig baiduOcrConfig) {
|
BaiduOCRUtil.staticBaiduOcrConfig = baiduOcrConfig;
|
}
|
|
/**
|
* 获取百度OCR客户端实例
|
* @return AipOcr客户端实例
|
*/
|
private static AipOcr getClient() {
|
AipOcr client = new AipOcr(staticBaiduOcrConfig.getAppId(),
|
staticBaiduOcrConfig.getApiKey(),
|
staticBaiduOcrConfig.getSecretKey());
|
|
// 设置连接超时时间和socket超时时间
|
client.setConnectionTimeoutInMillis(2000);
|
client.setSocketTimeoutInMillis(60000);
|
|
return client;
|
}
|
|
/**
|
* 通用文字识别(图片路径)
|
* @param imagePath 图片路径
|
* @return 识别结果
|
*/
|
public static JSONObject generalRecognize(String imagePath) {
|
try {
|
AipOcr client = getClient();
|
|
// 参数为图片路径
|
HashMap<String, String> options = new HashMap<String, String>();
|
options.put("language_type", "CHN_ENG"); // 识别语言类型
|
options.put("detect_direction", "true"); // 是否检测图像朝向
|
options.put("detect_language", "true"); // 是否检测语言
|
options.put("probability", "true"); // 是否返回识别结果中每一行的置信度
|
|
org.json.JSONObject res = client.basicGeneral(imagePath, options);
|
log.info("百度OCR通用文字识别成功,图片路径: {}", imagePath);
|
|
JSONObject result = new JSONObject();
|
result.put("success", true);
|
result.put("data", JSON.parseObject(res.toString()));
|
result.put("content", extractContentFromBaiduResult(JSON.parseObject(res.toString())));
|
|
return result;
|
|
} catch (Exception e) {
|
log.error("百度OCR通用文字识别失败: {}", e.getMessage(), e);
|
|
JSONObject errorResult = new JSONObject();
|
errorResult.put("success", false);
|
errorResult.put("error", e.getMessage());
|
|
return errorResult;
|
}
|
}
|
|
/**
|
* 通用文字识别(文件对象)
|
* @param imageFile 图片文件对象
|
* @return 识别结果
|
*/
|
public static JSONObject generalRecognize(File imageFile) {
|
try {
|
AipOcr client = getClient();
|
|
// 参数为图片文件
|
HashMap<String, String> options = new HashMap<String, String>();
|
options.put("language_type", "CHN_ENG");
|
options.put("detect_direction", "true");
|
options.put("detect_language", "true");
|
options.put("probability", "true");
|
|
// 读取文件字节数组或使用文件路径
|
org.json.JSONObject res = client.basicGeneral(imageFile.getAbsolutePath(), options);
|
log.info("百度OCR通用文字识别成功,文件名: {}", imageFile.getName());
|
|
JSONObject result = new JSONObject();
|
result.put("success", true);
|
result.put("data", JSON.parseObject(res.toString()));
|
result.put("content", extractContentFromBaiduResult(JSON.parseObject(res.toString())));
|
|
return result;
|
|
} catch (Exception e) {
|
log.error("百度OCR通用文字识别失败: {}", e.getMessage(), e);
|
|
JSONObject errorResult = new JSONObject();
|
errorResult.put("success", false);
|
errorResult.put("error", e.getMessage());
|
|
return errorResult;
|
}
|
}
|
|
/**
|
* 通用文字识别(图片字节数组)
|
* @param imageBytes 图片字节数组
|
* @return 识别结果
|
*/
|
public static JSONObject generalRecognize(byte[] imageBytes) {
|
try {
|
AipOcr client = getClient();
|
|
HashMap<String, String> options = new HashMap<String, String>();
|
options.put("language_type", "CHN_ENG");
|
options.put("detect_direction", "true");
|
options.put("detect_language", "true");
|
options.put("probability", "true");
|
|
org.json.JSONObject res = client.basicGeneral(imageBytes, options);
|
log.info("百度OCR通用文字识别成功,字节数组长度: {}", imageBytes.length);
|
|
JSONObject result = new JSONObject();
|
result.put("success", true);
|
result.put("data", JSON.parseObject(res.toString()));
|
result.put("content", extractContentFromBaiduResult(JSON.parseObject(res.toString())));
|
|
return result;
|
|
} catch (Exception e) {
|
log.error("百度OCR通用文字识别失败: {}", e.getMessage(), e);
|
|
JSONObject errorResult = new JSONObject();
|
errorResult.put("success", false);
|
errorResult.put("error", e.getMessage());
|
|
return errorResult;
|
}
|
}
|
|
/**
|
* 高精度文字识别
|
* @param imagePath 图片路径
|
* @return 识别结果
|
*/
|
public static JSONObject accurateRecognize(String imagePath) {
|
try {
|
AipOcr client = getClient();
|
|
HashMap<String, String> options = new HashMap<String, String>();
|
options.put("recognize_granularity", "big"); // 是否定位单字符位置
|
options.put("language_type", "CHN_ENG");
|
options.put("detect_direction", "true");
|
options.put("detect_language", "true");
|
options.put("vertexes_location", "true"); // 是否返回文字外接多边形顶点位置
|
options.put("probability", "true");
|
|
org.json.JSONObject res = client.accurateGeneral(imagePath, options);
|
log.info("百度OCR高精度文字识别成功,图片路径: {}", imagePath);
|
|
JSONObject result = new JSONObject();
|
result.put("success", true);
|
result.put("data", JSON.parseObject(res.toString()));
|
result.put("content", extractContentFromBaiduResult(JSON.parseObject(res.toString())));
|
|
return result;
|
|
} catch (Exception e) {
|
log.error("百度OCR高精度文字识别失败: {}", e.getMessage(), e);
|
|
JSONObject errorResult = new JSONObject();
|
errorResult.put("success", false);
|
errorResult.put("error", e.getMessage());
|
|
return errorResult;
|
}
|
}
|
|
/**
|
* 手写体识别
|
* @param imagePath 图片路径
|
* @return 识别结果
|
*/
|
public static JSONObject handwritingRecognize(String imagePath) {
|
try {
|
AipOcr client = getClient();
|
|
// 手写体识别参数
|
HashMap<String, String> options = new HashMap<String, String>();
|
options.put("language_type", "CHN_ENG");
|
|
org.json.JSONObject res = client.handwriting(imagePath, options);
|
log.info("百度OCR手写体识别成功,图片路径: {}", imagePath);
|
|
JSONObject result = new JSONObject();
|
result.put("success", true);
|
result.put("data", JSON.parseObject(res.toString()));
|
result.put("content", extractContentFromBaiduResult(JSON.parseObject(res.toString())));
|
|
return result;
|
|
} catch (Exception e) {
|
log.error("百度OCR手写体识别失败: {}", e.getMessage(), e);
|
|
JSONObject errorResult = new JSONObject();
|
errorResult.put("success", false);
|
errorResult.put("error", e.getMessage());
|
|
return errorResult;
|
}
|
}
|
|
/**
|
* 手写体识别(文件对象)
|
* @param imageFile 图片文件对象
|
* @return 识别结果
|
*/
|
public static JSONObject handwritingRecognize(File imageFile) {
|
try {
|
AipOcr client = getClient();
|
|
HashMap<String, String> options = new HashMap<String, String>();
|
options.put("language_type", "CHN_ENG");
|
|
org.json.JSONObject res = client.handwriting(imageFile.getAbsolutePath(), options);
|
log.info("百度OCR手写体识别成功,文件名: {}", imageFile.getName());
|
|
JSONObject result = new JSONObject();
|
result.put("success", true);
|
result.put("data", JSON.parseObject(res.toString()));
|
result.put("content", extractContentFromBaiduResult(JSON.parseObject(res.toString())));
|
|
return result;
|
|
} catch (Exception e) {
|
log.error("百度OCR手写体识别失败: {}", e.getMessage(), e);
|
|
JSONObject errorResult = new JSONObject();
|
errorResult.put("success", false);
|
errorResult.put("error", e.getMessage());
|
|
return errorResult;
|
}
|
}
|
|
/**
|
* 身份证识别
|
* @param imagePath 图片路径
|
* @param isFront true为正面,false为反面
|
* @return 识别结果
|
*/
|
public static JSONObject idCardRecognize(String imagePath, boolean isFront) {
|
try {
|
AipOcr client = getClient();
|
|
HashMap<String, String> options = new HashMap<String, String>();
|
String idCardSide = isFront ? "front" : "back";
|
|
org.json.JSONObject res = client.idcard(imagePath, idCardSide, options);
|
log.info("百度OCR身份证识别成功,图片路径: {},方向: {}", imagePath, idCardSide);
|
|
JSONObject result = new JSONObject();
|
result.put("success", true);
|
result.put("data", JSON.parseObject(res.toString()));
|
|
return result;
|
|
} catch (Exception e) {
|
log.error("百度OCR身份证识别失败: {}", e.getMessage(), e);
|
|
JSONObject errorResult = new JSONObject();
|
errorResult.put("success", false);
|
errorResult.put("error", e.getMessage());
|
|
return errorResult;
|
}
|
}
|
|
/**
|
* 银行卡识别
|
* @param imagePath 图片路径
|
* @return 识别结果
|
*/
|
public static JSONObject bankCardRecognize(String imagePath) {
|
try {
|
AipOcr client = getClient();
|
|
org.json.JSONObject res = client.bankcard(imagePath, new HashMap<String, String>());
|
log.info("百度OCR银行卡识别成功,图片路径: {}", imagePath);
|
|
JSONObject result = new JSONObject();
|
result.put("success", true);
|
result.put("data", JSON.parseObject(res.toString()));
|
|
return result;
|
|
} catch (Exception e) {
|
log.error("百度OCR银行卡识别失败: {}", e.getMessage(), e);
|
|
JSONObject errorResult = new JSONObject();
|
errorResult.put("success", false);
|
errorResult.put("error", e.getMessage());
|
|
return errorResult;
|
}
|
}
|
|
/**
|
* 营业执照识别
|
* @param imagePath 图片路径
|
* @return 识别结果
|
*/
|
public static JSONObject businessLicenseRecognize(String imagePath) {
|
try {
|
AipOcr client = getClient();
|
|
HashMap<String, String> options = new HashMap<String, String>();
|
|
org.json.JSONObject res = client.businessLicense(imagePath, options);
|
log.info("百度OCR营业执照识别成功,图片路径: {}", imagePath);
|
|
JSONObject result = new JSONObject();
|
result.put("success", true);
|
result.put("data", JSON.parseObject(res.toString()));
|
|
return result;
|
|
} catch (Exception e) {
|
log.error("百度OCR营业执照识别失败: {}", e.getMessage(), e);
|
|
JSONObject errorResult = new JSONObject();
|
errorResult.put("success", false);
|
errorResult.put("error", e.getMessage());
|
|
return errorResult;
|
}
|
}
|
|
/**
|
* 从百度OCR结果中提取文本内容
|
* @param result 百度OCR返回的结果(fastjson格式)
|
* @return 提取的文本内容
|
*/
|
private static String extractContentFromBaiduResult(JSONObject result) {
|
StringBuilder content = new StringBuilder();
|
|
if (result.containsKey("words_result") && result.getJSONArray("words_result") != null) {
|
JSONArray wordsResult = result.getJSONArray("words_result");
|
for (int i = 0; i < wordsResult.size(); i++) {
|
JSONObject wordResult = wordsResult.getJSONObject(i);
|
if (wordResult.containsKey("words")) {
|
content.append(wordResult.getString("words")).append("\n");
|
}
|
}
|
}
|
|
return content.toString().trim();
|
}
|
|
/**
|
* 从识别结果中提取目标字段(金额、日期、备注等)
|
* @param ocrResult OCR识别的原始结果
|
* @return 提取后的目标字段
|
*/
|
public static java.util.Map<String, String> extractTargetFields(JSONObject ocrResult) {
|
java.util.Map<String, String> extracted = new java.util.HashMap<>();
|
|
// 校验OCR结果是否有效
|
if (!ocrResult.containsKey("success") || !ocrResult.getBooleanValue("success")) {
|
extracted.put("error", ocrResult.getString("error"));
|
return extracted;
|
}
|
|
// 获取识别的文字内容
|
String content = ocrResult.getString("content");
|
if (content == null || content.isEmpty()) {
|
extracted.put("error", "OCR识别结果为空");
|
return extracted;
|
}
|
|
// 在内容中查找特定关键词
|
String[] lines = content.split("\n");
|
for (String line : lines) {
|
line = line.trim();
|
|
// 查找金额相关信息
|
if (line.contains("金额") || line.contains("合计") || line.contains("总计") || line.matches(".*\\d+\\.\\d{2}.*")) {
|
if (!extracted.containsKey("totalAmount")) {
|
extracted.put("totalAmount", line);
|
}
|
}
|
|
// 查找日期相关信息
|
if (line.contains("日期") || line.matches(".*\\d{4}[-/年]\\d{1,2}[-/月]\\d{1,2}.*")) {
|
if (!extracted.containsKey("date")) {
|
extracted.put("date", line);
|
}
|
}
|
|
// 查找备注相关信息
|
if (line.contains("备注") || line.contains("说明")) {
|
if (!extracted.containsKey("remark")) {
|
extracted.put("remark", line);
|
}
|
}
|
}
|
|
// 如果没有找到特定字段,返回全文
|
if (extracted.isEmpty()) {
|
extracted.put("fullText", content);
|
}
|
|
return extracted;
|
}
|
}
|