mirror of
https://github.com/geekwenjie/SmartJavaAI.git
synced 2026-09-14 05:38:50 +00:00
- 新增 语音识别模块,集成 OpenAI 开源的 Whisper 和 Vosk
- 修复 质量评估模型的 Bug - 修复 OCR 模块 recognizeAndDraw 方法的 Bug - 修复 车牌识别在未检测到车牌时的报错问题 - 优化 OCR 表格识别功能,新增导出方式
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package smartai.examples.ocr.common;
|
||||
|
||||
import ai.djl.modality.cv.Image;
|
||||
import cn.smartjavaai.common.config.Config;
|
||||
import cn.smartjavaai.common.entity.DetectionResponse;
|
||||
import cn.smartjavaai.common.enums.DeviceEnum;
|
||||
import cn.smartjavaai.common.utils.ImageUtils;
|
||||
@@ -14,12 +15,14 @@ import cn.smartjavaai.ocr.model.common.detect.OcrCommonDetModel;
|
||||
import cn.smartjavaai.ocr.utils.OcrUtils;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
|
||||
@@ -32,9 +35,17 @@ import java.util.List;
|
||||
public class OcrDetectionDemo {
|
||||
|
||||
|
||||
|
||||
|
||||
//设备类型
|
||||
public static DeviceEnum device = DeviceEnum.CPU;
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeAll() throws IOException {
|
||||
//修改缓存路径
|
||||
// Config.setCachePath("/Users/xxx/smartjavaai_cache");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文本检测模型
|
||||
* @return
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package smartai.examples.ocr.common;
|
||||
|
||||
import cn.smartjavaai.common.config.Config;
|
||||
import cn.smartjavaai.common.enums.DeviceEnum;
|
||||
import cn.smartjavaai.ocr.config.DirectionModelConfig;
|
||||
import cn.smartjavaai.ocr.config.OcrDetModelConfig;
|
||||
@@ -12,8 +13,10 @@ import cn.smartjavaai.ocr.model.common.detect.OcrCommonDetModel;
|
||||
import cn.smartjavaai.ocr.model.common.direction.OcrDirectionModel;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -28,6 +31,12 @@ public class OcrDirectionDetDemo {
|
||||
//设备类型
|
||||
public static DeviceEnum device = DeviceEnum.CPU;
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeAll() throws IOException {
|
||||
//修改缓存路径
|
||||
// Config.setCachePath("/Users/xxx/smartjavaai_cache");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取方向检测模型
|
||||
* @return
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package smartai.examples.ocr.common;
|
||||
|
||||
import ai.djl.modality.cv.Image;
|
||||
import ai.djl.util.JsonUtils;
|
||||
import cn.hutool.core.img.ImgUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.smartjavaai.common.config.Config;
|
||||
import cn.smartjavaai.common.enums.DeviceEnum;
|
||||
import cn.smartjavaai.common.utils.ImageUtils;
|
||||
import cn.smartjavaai.ocr.config.DirectionModelConfig;
|
||||
@@ -18,9 +22,15 @@ import cn.smartjavaai.ocr.model.common.direction.OcrDirectionModel;
|
||||
import cn.smartjavaai.ocr.model.common.recognize.OcrCommonRecModel;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -35,6 +45,13 @@ public class OcrRecognizeDemo {
|
||||
//设备类型
|
||||
public static DeviceEnum device = DeviceEnum.CPU;
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeAll() throws IOException {
|
||||
//修改缓存路径
|
||||
//Config.setCachePath("/Users/xxx/smartjavaai_cache");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取通用识别模型(不带方向矫正)
|
||||
* @return
|
||||
@@ -44,7 +61,7 @@ public class OcrRecognizeDemo {
|
||||
//指定文本识别模型
|
||||
recModelConfig.setRecModelEnum(CommonRecModelEnum.PP_OCR_V5_MOBILE_REC_MODEL);
|
||||
//指定识别模型位置,需要更改为自己的模型路径(下载地址请查看文档)
|
||||
recModelConfig.setRecModelPath("/Users/xxx/Documents/develop/model/ocr/PP-OCRv5_mobile_rec_infer/PP-OCRv5_mobile_rec_infer.onnx");
|
||||
recModelConfig.setRecModelPath("/Users/wenjie/Documents/develop/model/ocr/PP-OCRv5_mobile_rec_infer/PP-OCRv5_mobile_rec_infer.onnx");
|
||||
recModelConfig.setDevice(device);
|
||||
recModelConfig.setTextDetModel(getDetectionModel());
|
||||
return OcrModelFactory.getInstance().getRecModel(recModelConfig);
|
||||
@@ -59,7 +76,7 @@ public class OcrRecognizeDemo {
|
||||
//指定检测模型
|
||||
config.setModelEnum(CommonDetModelEnum.PP_OCR_V5_MOBILE_DET_MODEL);
|
||||
//指定模型位置,需要更改为自己的模型路径(下载地址请查看文档)
|
||||
config.setDetModelPath("/Users/xxx/Documents/develop/model/ocr/PP-OCRv5_mobile_det_infer/PP-OCRv5_mobile_det_infer.onnx");
|
||||
config.setDetModelPath("/Users/wenjie/Documents/develop/model/ocr/PP-OCRv5_mobile_det_infer/PP-OCRv5_mobile_det_infer.onnx");
|
||||
config.setDevice(device);
|
||||
return OcrModelFactory.getInstance().getDetModel(config);
|
||||
}
|
||||
@@ -180,6 +197,59 @@ public class OcrRecognizeDemo {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void recognizeAndDraw2(){
|
||||
try {
|
||||
OcrCommonRecModel recModel = getRecModel();
|
||||
int fontSize = 18;
|
||||
//创建保存路径
|
||||
Path inputImagePath = Paths.get("src/main/resources/general_ocr_002.png");
|
||||
Path imageOutputPath = Paths.get("output/ocr_4_recognized.jpg");
|
||||
BufferedImage image = null;
|
||||
image = ImageIO.read(new File(inputImagePath.toAbsolutePath().toString()));
|
||||
BufferedImage resultImage = recModel.recognizeAndDraw(image, fontSize, new OcrRecOptions());
|
||||
ImageUtils.saveImage(resultImage, imageOutputPath.toAbsolutePath().toString());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 文本识别并绘制结果(返回base64)
|
||||
*/
|
||||
@Test
|
||||
public void recognizeAndDrawToBase64(){
|
||||
try {
|
||||
OcrCommonRecModel recModel = getRecModel();
|
||||
int fontSize = 18;
|
||||
//创建保存路径
|
||||
Path inputImagePath = Paths.get("src/main/resources/general_ocr_002.png");
|
||||
byte[] imageBytes = FileUtil.readBytes(inputImagePath);
|
||||
String base64 = recModel.recognizeAndDrawToBase64(imageBytes, fontSize, new OcrRecOptions());
|
||||
log.info("base64:{}", base64);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 文本识别并绘制结果(返回OcrInfo,OcrInfo中包含base64)
|
||||
*/
|
||||
@Test
|
||||
public void recognizeAndDraw3(){
|
||||
try {
|
||||
OcrCommonRecModel recModel = getRecModel();
|
||||
int fontSize = 18;
|
||||
//创建保存路径
|
||||
Path inputImagePath = Paths.get("src/main/resources/general_ocr_002.png");
|
||||
byte[] imageBytes = FileUtil.readBytes(inputImagePath);
|
||||
OcrInfo ocrInfo = recModel.recognizeAndDraw(imageBytes, fontSize, new OcrRecOptions());
|
||||
log.info("ocrInfo:{}", JsonUtils.toJson(ocrInfo));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量识别
|
||||
* 注意事项:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package smartai.examples.ocr.plate;
|
||||
|
||||
import ai.djl.util.JsonUtils;
|
||||
import cn.smartjavaai.common.config.Config;
|
||||
import cn.smartjavaai.common.entity.R;
|
||||
import cn.smartjavaai.common.enums.DeviceEnum;
|
||||
import cn.smartjavaai.common.utils.ImageUtils;
|
||||
@@ -13,9 +14,11 @@ import cn.smartjavaai.ocr.factory.PlateModelFactory;
|
||||
import cn.smartjavaai.ocr.model.plate.PlateDetModel;
|
||||
import cn.smartjavaai.ocr.model.plate.PlateRecModel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -27,6 +30,12 @@ public class PlateRecDemo {
|
||||
//设备类型
|
||||
public static DeviceEnum device = DeviceEnum.CPU;
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeAll() throws IOException {
|
||||
//修改缓存路径
|
||||
// Config.setCachePath("/Users/xxx/smartjavaai_cache");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取车牌检测模型
|
||||
* @return
|
||||
|
||||
@@ -2,6 +2,7 @@ package smartai.examples.ocr.table;
|
||||
|
||||
import ai.djl.modality.cv.Image;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.smartjavaai.common.config.Config;
|
||||
import cn.smartjavaai.common.entity.R;
|
||||
import cn.smartjavaai.common.enums.DeviceEnum;
|
||||
import cn.smartjavaai.common.utils.ImageUtils;
|
||||
@@ -21,17 +22,21 @@ import cn.smartjavaai.ocr.model.table.TableRecognizer;
|
||||
import cn.smartjavaai.ocr.model.table.TableStructureModel;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* OCR 文本识别 示例
|
||||
* OCR 表格识别 示例
|
||||
* 模型下载地址:https://pan.baidu.com/s/1MLfd73Vjdpnuls9-oqc9uw?pwd=1234 提取码: 1234
|
||||
* @author dwj
|
||||
* @date 2025/5/25
|
||||
@@ -39,6 +44,13 @@ import java.util.List;
|
||||
@Slf4j
|
||||
public class TableRecDemo {
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeAll() throws IOException {
|
||||
//修改缓存路径
|
||||
// Config.setCachePath("/Users/xxx/smartjavaai_cache");
|
||||
}
|
||||
|
||||
//设备类型
|
||||
public static DeviceEnum device = DeviceEnum.CPU;
|
||||
|
||||
@@ -51,7 +63,7 @@ public class TableRecDemo {
|
||||
//指定文本识别模型
|
||||
recModelConfig.setRecModelEnum(CommonRecModelEnum.PP_OCR_V5_MOBILE_REC_MODEL);
|
||||
//指定识别模型位置,需要更改为自己的模型路径(下载地址请查看文档)
|
||||
recModelConfig.setRecModelPath("/Users/xxx/Documents/develop/model/ocr/PP-OCRv5_mobile_rec_infer/PP-OCRv5_mobile_rec_infer.onnx");
|
||||
recModelConfig.setRecModelPath("/Users/wenjie/Documents/develop/model/ocr/PP-OCRv5_mobile_rec_infer/PP-OCRv5_mobile_rec_infer.onnx");
|
||||
recModelConfig.setDevice(device);
|
||||
recModelConfig.setTextDetModel(getDetectionModel());
|
||||
return OcrModelFactory.getInstance().getRecModel(recModelConfig);
|
||||
@@ -66,7 +78,7 @@ public class TableRecDemo {
|
||||
//指定检测模型
|
||||
config.setModelEnum(CommonDetModelEnum.PP_OCR_V5_MOBILE_DET_MODEL);
|
||||
//指定模型位置,需要更改为自己的模型路径(下载地址请查看文档)
|
||||
config.setDetModelPath("/Users/xxx/Documents/develop/model/ocr/PP-OCRv5_mobile_det_infer/PP-OCRv5_mobile_det_infer.onnx");
|
||||
config.setDetModelPath("/Users/wenjie/Documents/develop/model/ocr/PP-OCRv5_mobile_det_infer/PP-OCRv5_mobile_det_infer.onnx");
|
||||
// config.setDetModelPath("/Users/xxx/Documents/develop/model/ocr/PP-OCRv5_server_det_infer/PP-OCRv5_server_det.onnx");
|
||||
config.setDevice(device);
|
||||
return OcrModelFactory.getInstance().getDetModel(config);
|
||||
@@ -81,7 +93,7 @@ public class TableRecDemo {
|
||||
//指定行文本方向检测模型
|
||||
directionModelConfig.setModelEnum(DirectionModelEnum.PP_LCNET_X0_25);
|
||||
//指定行文本方向检测模型路径,需要更改为自己的模型路径(下载地址请查看文档)
|
||||
directionModelConfig.setModelPath("/Users/xxx/Documents/develop/model/ocr/PP-LCNet_x0_25_textline_ori_infer/PP-LCNet_x0_25_textline_ori_infer.onnx");
|
||||
directionModelConfig.setModelPath("/Users/wenjie/Documents/develop/model/ocr/PP-LCNet_x0_25_textline_ori_infer/PP-LCNet_x0_25_textline_ori_infer.onnx");
|
||||
directionModelConfig.setDevice(device);
|
||||
return OcrModelFactory.getInstance().getDirectionModel(directionModelConfig);
|
||||
}
|
||||
@@ -95,7 +107,7 @@ public class TableRecDemo {
|
||||
//指定行文本方向检测模型
|
||||
config.setModelEnum(TableStructureModelEnum.SLANET_PLUS);
|
||||
//指定行文本方向检测模型路径,需要更改为自己的模型路径(下载地址请查看文档)
|
||||
config.setModelPath("/Users/xxx/Documents/develop/model/ocr/slanet-plus/slanet-plus.onnx");
|
||||
config.setModelPath("/Users/wenjie/Documents/develop/model/ocr/slanet-plus/slanet-plus.onnx");
|
||||
// config.setModelPath("/Users/xxx/Documents/develop/model/ocr/SLANet_infer/SLANet.onnx");
|
||||
config.setDevice(device);
|
||||
return TableRecModelFactory.getInstance().getTableStructureModel(config);
|
||||
@@ -142,4 +154,47 @@ public class TableRecDemo {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 表格识别
|
||||
* 仅支持简单表格
|
||||
* 流程:表格结构识别 -> 文本检测 -> 文本识别 -> 合成html table
|
||||
* 注意事项:
|
||||
* 1、批量检测时,模型应统一放在外层 try 中使用,避免重复加载,自动释放资源更安全。
|
||||
* 2、模型文件需要放在单独文件夹
|
||||
*/
|
||||
@Test
|
||||
public void recognize2(){
|
||||
try {
|
||||
TableStructureModel tableStructureModel = getTableStructureModel();
|
||||
OcrCommonDetModel detModel = getDetectionModel();
|
||||
OcrCommonRecModel recModel = getRecModel();
|
||||
OcrDirectionModel directionModel = getDirectionModel();
|
||||
//创建表格识别器
|
||||
TableRecognizer tableRecognizer = TableRecognizer.builder()
|
||||
.withStructureModel(tableStructureModel)
|
||||
.withTextDetModel(detModel)
|
||||
// .withDirectionModel(getDirectionModel()) //如果表格中存在旋转的文字,可以使用方向分类模型
|
||||
.withTextRecModel(recModel).build();
|
||||
String imagePath = "src/main/resources/table/table_ch1.png";
|
||||
BufferedImage image = ImageIO.read(new File(Paths.get(imagePath).toAbsolutePath().toString()));
|
||||
R<TableStructureResult> result = tableRecognizer.recognize(image);
|
||||
if(result.isSuccess()){
|
||||
log.info("result: {}", result.getData().getHtml());
|
||||
//导出html内容到文件
|
||||
Path outputPath = Paths.get("output/table_ch2_result.html");
|
||||
FileUtil.writeUtf8String(result.getData().getHtml(), outputPath.toAbsolutePath().toString());
|
||||
//绘制表格结构
|
||||
BufferedImage resultImage = tableRecognizer.drawTable(result.getData(), image);
|
||||
ImageUtils.saveImage(resultImage, "output/table_ch2_result.jpg");
|
||||
//导出excel,如果导出失败,可能是因为表格结果识别的结果是错乱的
|
||||
try (OutputStream out = Files.newOutputStream(Paths.get("output/table_ch2_result2.xls"))) {
|
||||
tableRecognizer.exportExcel(result.getData().getHtml(), out);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user