├── .gitignore ├── src ├── main │ ├── resources │ │ ├── model │ │ │ ├── ocr │ │ │ │ ├── ocr_cls_model.txt │ │ │ │ ├── ocr_det_model.txt │ │ │ │ ├── ocr_rec_model.txt │ │ │ │ └── ch_ppocr_mobile_v2.0_cls_infer.zip │ │ │ └── layout │ │ │ │ └── layout.zip │ │ └── application.properties │ └── java │ │ └── com │ │ ├── sy │ │ ├── DocAIServiceApplication.java │ │ ├── common │ │ │ ├── Constants.java │ │ │ ├── PredictException.java │ │ │ ├── ModelUrlUtils.java │ │ │ ├── DetectObjectDto.java │ │ │ └── ImageUtils.java │ │ ├── layout │ │ │ ├── LayoutProperties.java │ │ │ ├── LayoutTranslator.java │ │ │ ├── LayoutController.java │ │ │ └── LayoutService.java │ │ └── ocr │ │ │ ├── OcrProperties.java │ │ │ ├── MyRotateTranslator.java │ │ │ ├── MyRecognitionTranslator.java │ │ │ ├── OcrController.java │ │ │ └── OcrService.java │ │ └── utils │ │ ├── FileFormatUtil.java │ │ ├── PropertiesReader.java │ │ ├── FileUploadConfig.java │ │ └── CollectionUtil.java └── test │ └── java │ └── com │ └── sy │ └── doc_ai │ └── DocAiApplicationTests.java ├── requirements.txt ├── img ├── ocr_result.png └── layout_result.png ├── .idea ├── encodings.xml ├── modules.xml ├── libraries │ ├── Maven__ai_djl_api_0_15_0.xml │ ├── Maven__org_ow2_asm_asm_9_1.xml │ ├── Maven__dom4j_dom4j_1_6_1.xml │ ├── Maven__org_apache_poi_poi_4_0_0.xml │ ├── Maven__net_java_dev_jna_jna_5_9_0.xml │ ├── Maven__org_hamcrest_hamcrest_2_2.xml │ ├── Maven__org_yaml_snakeyaml_1_29.xml │ ├── Maven__xml_apis_xml_apis_1_0_b2.xml │ ├── Maven__com_aspose_aspose_ocr_22_9.xml │ ├── Maven__org_objenesis_objenesis_3_2.xml │ ├── Maven__org_slf4j_slf4j_api_1_7_36.xml │ ├── Maven__com_google_code_gson_gson_2_8_9.xml │ ├── Maven__com_fasterxml_classmate_1_5_1.xml │ ├── Maven__net_minidev_json_smart_2_4_8.xml │ ├── Maven__org_mockito_mockito_core_4_0_0.xml │ ├── Maven__org_opentest4j_opentest4j_1_2_0.xml │ ├── Maven__org_projectlombok_lombok_1_18_22.xml │ ├── Maven__org_slf4j_jul_to_slf4j_1_7_36.xml │ ├── Maven__org_xmlunit_xmlunit_core_2_8_4.xml │ ├── Maven__org_skyscreamer_jsonassert_1_5_0.xml │ ├── Maven__commons_codec_commons_codec_1_15.xml │ ├── Maven__net_bytebuddy_byte_buddy_1_11_22.xml │ ├── Maven__org_assertj_assertj_core_3_21_0.xml │ ├── Maven__com_jayway_jsonpath_json_path_2_6_0.xml │ ├── Maven__io_springfox_springfox_oas_3_0_0.xml │ ├── Maven__io_springfox_springfox_spi_3_0_0.xml │ ├── Maven__io_springfox_springfox_core_3_0_0.xml │ ├── Maven__io_swagger_swagger_models_1_5_20.xml │ ├── Maven__ch_qos_logback_logback_core_1_2_10.xml │ ├── Maven__net_minidev_accessors_smart_2_4_8.xml │ ├── Maven__org_apache_commons_commons_lang3_3_7.xml │ ├── Maven__org_springframework_spring_aop_5_3_16.xml │ ├── Maven__org_springframework_spring_jcl_5_3_16.xml │ ├── Maven__org_springframework_spring_web_5_3_16.xml │ ├── Maven__io_github_classgraph_classgraph_4_8_83.xml │ ├── Maven__io_springfox_springfox_schema_3_0_0.xml │ ├── Maven__org_mapstruct_mapstruct_1_3_1_Final.xml │ ├── Maven__ai_djl_pytorch_pytorch_engine_0_15_0.xml │ ├── Maven__org_junit_jupiter_junit_jupiter_5_8_2.xml │ ├── Maven__org_springframework_spring_core_5_3_16.xml │ ├── Maven__org_springframework_spring_test_5_3_16.xml │ ├── Maven__ch_qos_logback_logback_classic_1_2_10.xml │ ├── Maven__org_apiguardian_apiguardian_api_1_1_2.xml │ ├── Maven__io_swagger_core_v3_swagger_models_2_1_2.xml │ ├── Maven__org_apache_logging_log4j_log4j_api_2_17_1.xml │ ├── Maven__org_springframework_spring_beans_5_3_16.xml │ ├── Maven__io_springfox_springfox_swagger2_3_0_0.xml │ ├── Maven__org_springframework_boot_spring_boot_2_6_4.xml │ ├── Maven__org_springframework_spring_webmvc_5_3_16.xml │ ├── Maven__io_springfox_springfox_data_rest_3_0_0.xml │ ├── Maven__io_swagger_swagger_annotations_1_5_20.xml │ ├── Maven__net_bytebuddy_byte_buddy_agent_1_11_22.xml │ ├── Maven__org_apache_commons_commons_compress_1_21.xml │ ├── Maven__ai_djl_pytorch_pytorch_model_zoo_0_15_0.xml │ ├── Maven__org_springframework_spring_context_5_3_16.xml │ ├── Maven__ai_djl_pytorch_pytorch_native_auto_1_9_1.xml │ ├── Maven__com_microsoft_onnxruntime_onnxruntime_1_10_0.xml │ ├── Maven__io_springfox_springfox_spring_web_3_0_0.xml │ ├── Maven__io_springfox_springfox_swagger_ui_3_0_0.xml │ ├── Maven__org_junit_jupiter_junit_jupiter_api_5_8_2.xml │ ├── Maven__org_mockito_mockito_junit_jupiter_4_0_0.xml │ ├── Maven__com_fasterxml_jackson_core_jackson_core_2_13_1.xml │ ├── Maven__io_springfox_springfox_boot_starter_3_0_0.xml │ ├── Maven__org_apache_commons_commons_collections4_4_2.xml │ ├── Maven__ai_djl_onnxruntime_onnxruntime_engine_0_15_0.xml │ ├── Maven__io_swagger_core_v3_swagger_annotations_2_1_2.xml │ ├── Maven__jakarta_xml_bind_jakarta_xml_bind_api_2_3_3.xml │ ├── Maven__org_apache_logging_log4j_log4j_to_slf4j_2_17_1.xml │ ├── Maven__org_apache_tomcat_embed_tomcat_embed_el_9_0_58.xml │ ├── Maven__org_springframework_spring_expression_5_3_16.xml │ ├── Maven__commons_collections_commons_collections_3_2_2.xml │ ├── Maven__io_springfox_springfox_spring_webmvc_3_0_0.xml │ ├── Maven__org_junit_jupiter_junit_jupiter_engine_5_8_2.xml │ ├── Maven__org_junit_jupiter_junit_jupiter_params_5_8_2.xml │ ├── Maven__org_springframework_boot_spring_boot_test_2_6_4.xml │ ├── Maven__io_springfox_springfox_spring_webflux_3_0_0.xml │ ├── Maven__io_springfox_springfox_swagger_common_3_0_0.xml │ ├── Maven__ai_djl_paddlepaddle_paddlepaddle_engine_0_15_0.xml │ ├── Maven__org_junit_platform_junit_platform_engine_1_8_2.xml │ ├── Maven__io_springfox_springfox_bean_validators_3_0_0.xml │ ├── Maven__org_apache_tomcat_embed_tomcat_embed_core_9_0_58.xml │ ├── Maven__com_fasterxml_jackson_core_jackson_databind_2_13_1.xml │ ├── Maven__jakarta_activation_jakarta_activation_api_1_2_2.xml │ ├── Maven__jakarta_annotation_jakarta_annotation_api_1_3_5.xml │ ├── Maven__org_junit_platform_junit_platform_commons_1_8_2.xml │ ├── Maven__org_springframework_boot_spring_boot_starter_2_6_4.xml │ ├── Maven__ai_djl_paddlepaddle_paddlepaddle_model_zoo_0_15_0.xml │ ├── Maven__com_fasterxml_jackson_core_jackson_annotations_2_13_1.xml │ ├── Maven__org_apache_tomcat_embed_tomcat_embed_websocket_9_0_58.xml │ ├── Maven__org_springframework_boot_spring_boot_starter_web_2_6_4.xml │ ├── Maven__org_springframework_boot_spring_boot_starter_json_2_6_4.xml │ ├── Maven__org_springframework_boot_spring_boot_starter_test_2_6_4.xml │ ├── Maven__org_springframework_boot_spring_boot_autoconfigure_2_6_4.xml │ ├── Maven__com_fasterxml_jackson_datatype_jackson_datatype_jdk8_2_13_1.xml │ ├── Maven__org_springframework_boot_spring_boot_starter_tomcat_2_6_4.xml │ ├── Maven__org_springframework_boot_spring_boot_starter_logging_2_6_4.xml │ ├── Maven__org_springframework_plugin_spring_plugin_core_2_0_0_RELEASE.xml │ ├── Maven__com_fasterxml_jackson_datatype_jackson_datatype_jsr310_2_13_1.xml │ ├── Maven__com_vaadin_external_google_android_json_0_0_20131108_vaadin1.xml │ ├── Maven__org_springframework_boot_spring_boot_test_autoconfigure_2_6_4.xml │ ├── Maven__org_springframework_plugin_spring_plugin_metadata_2_0_0_RELEASE.xml │ ├── Maven__com_fasterxml_jackson_module_jackson_module_parameter_names_2_13_1.xml │ └── Maven__org_springframework_boot_spring_boot_configuration_processor_2_6_4.xml ├── misc.xml ├── compiler.xml ├── jarRepositories.xml ├── workspace.xml └── doc_ai.iml ├── README.md ├── pom.xml └── doc_ai.iml /.gitignore: -------------------------------------------------------------------------------- 1 | # Project exclude paths 2 | /target/ -------------------------------------------------------------------------------- /src/main/resources/model/ocr/ocr_cls_model.txt: -------------------------------------------------------------------------------- 1 | 这里是ocr的方向模型 -------------------------------------------------------------------------------- /src/main/resources/model/ocr/ocr_det_model.txt: -------------------------------------------------------------------------------- 1 | 这里是ocr的检测模型 -------------------------------------------------------------------------------- /src/main/resources/model/ocr/ocr_rec_model.txt: -------------------------------------------------------------------------------- 1 | 这里是ocr的识别模型 -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | java11 2 | djl 3 | springboot 4 | onnxruntime 5 | -------------------------------------------------------------------------------- /img/ocr_result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangnanboy/doc_ai/HEAD/img/ocr_result.png -------------------------------------------------------------------------------- /img/layout_result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangnanboy/doc_ai/HEAD/img/layout_result.png -------------------------------------------------------------------------------- /src/main/resources/model/layout/layout.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangnanboy/doc_ai/HEAD/src/main/resources/model/layout/layout.zip -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.mvc.pathmatch.matching-strategy=ant_path_matcher 2 | spring.servlet.multipart.max-file-size=10MB 3 | -------------------------------------------------------------------------------- /src/main/resources/model/ocr/ch_ppocr_mobile_v2.0_cls_infer.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangnanboy/doc_ai/HEAD/src/main/resources/model/ocr/ch_ppocr_mobile_v2.0_cls_infer.zip -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/test/java/com/sy/doc_ai/DocAiApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.sy.doc_ai; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class DocAiApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/sy/DocAIServiceApplication.java: -------------------------------------------------------------------------------- 1 | package com.sy; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * @author sy 8 | * @date 2022/9/13 22:25 9 | */ 10 | @SpringBootApplication 11 | public class DocAIServiceApplication { 12 | public static void main(String[] args) { 13 | SpringApplication.run(DocAIServiceApplication.class, args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/sy/common/Constants.java: -------------------------------------------------------------------------------- 1 | package com.sy.common; 2 | 3 | import lombok.experimental.UtilityClass; 4 | 5 | /** 6 | * @author sy 7 | * @date 2022/9/13 22:24 8 | */ 9 | @UtilityClass 10 | public class Constants { 11 | /** 12 | * OCR推理引擎使用不同框架 13 | */ 14 | public static final String ENGINE_PADDLE = "PaddlePaddle"; 15 | public static final String ENGINE_ONNX = "OnnxRuntime"; 16 | public static final String ENGINE_PYTORCH = "PyTorch"; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/sy/common/PredictException.java: -------------------------------------------------------------------------------- 1 | package com.sy.common; 2 | 3 | /** 4 | * 推理异常 5 | * @author sy 6 | * @date 2022/9/13 21:30 7 | */ 8 | public class PredictException extends RuntimeException { 9 | 10 | public PredictException() { 11 | } 12 | 13 | public PredictException(Throwable exception) { 14 | super(exception); 15 | } 16 | 17 | public PredictException(String message, Throwable cause) { 18 | super(message, cause); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__ai_djl_api_0_15_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_ow2_asm_asm_9_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__dom4j_dom4j_1_6_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_apache_poi_poi_4_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__net_java_dev_jna_jna_5_9_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_hamcrest_hamcrest_2_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_yaml_snakeyaml_1_29.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__xml_apis_xml_apis_1_0_b2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_aspose_aspose_ocr_22_9.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_objenesis_objenesis_3_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_slf4j_slf4j_api_1_7_36.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_google_code_gson_gson_2_8_9.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_fasterxml_classmate_1_5_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__net_minidev_json_smart_2_4_8.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/main/java/com/utils/FileFormatUtil.java: -------------------------------------------------------------------------------- 1 | package com.utils; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | /** 7 | * @author sy 8 | * @date 2022/11/11 22:35 9 | */ 10 | public class FileFormatUtil { 11 | static List supportFileFormats = CollectionUtil.newArrayList(Arrays.asList("jpeg,jpg,png".split(","))); 12 | public static boolean checkFormats(String fileFullName) { 13 | String suffix = fileFullName.substring(fileFullName.lastIndexOf(".") + 1).toLowerCase(); 14 | return supportFileFormats.stream().anyMatch(suffix::contains); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_mockito_mockito_core_4_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_opentest4j_opentest4j_1_2_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_projectlombok_lombok_1_18_22.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_slf4j_jul_to_slf4j_1_7_36.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_xmlunit_xmlunit_core_2_8_4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_skyscreamer_jsonassert_1_5_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__commons_codec_commons_codec_1_15.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__net_bytebuddy_byte_buddy_1_11_22.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_assertj_assertj_core_3_21_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_jayway_jsonpath_json_path_2_6_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__io_springfox_springfox_oas_3_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__io_springfox_springfox_spi_3_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__io_springfox_springfox_core_3_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__io_swagger_swagger_models_1_5_20.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__ch_qos_logback_logback_core_1_2_10.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__net_minidev_accessors_smart_2_4_8.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_apache_commons_commons_lang3_3_7.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_aop_5_3_16.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_jcl_5_3_16.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_web_5_3_16.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__io_github_classgraph_classgraph_4_8_83.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__io_springfox_springfox_schema_3_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_mapstruct_mapstruct_1_3_1_Final.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__ai_djl_pytorch_pytorch_engine_0_15_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_5_8_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_core_5_3_16.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_test_5_3_16.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__ch_qos_logback_logback_classic_1_2_10.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_apiguardian_apiguardian_api_1_1_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__io_swagger_core_v3_swagger_models_2_1_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_apache_logging_log4j_log4j_api_2_17_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_beans_5_3_16.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__io_springfox_springfox_swagger2_3_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_2_6_4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_webmvc_5_3_16.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__io_springfox_springfox_data_rest_3_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__io_swagger_swagger_annotations_1_5_20.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__net_bytebuddy_byte_buddy_agent_1_11_22.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_apache_commons_commons_compress_1_21.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__ai_djl_pytorch_pytorch_model_zoo_0_15_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_context_5_3_16.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__ai_djl_pytorch_pytorch_native_auto_1_9_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_microsoft_onnxruntime_onnxruntime_1_10_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__io_springfox_springfox_spring_web_3_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__io_springfox_springfox_swagger_ui_3_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_api_5_8_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_mockito_mockito_junit_jupiter_4_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_core_2_13_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__io_springfox_springfox_boot_starter_3_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_apache_commons_commons_collections4_4_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__ai_djl_onnxruntime_onnxruntime_engine_0_15_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__io_swagger_core_v3_swagger_annotations_2_1_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__jakarta_xml_bind_jakarta_xml_bind_api_2_3_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_apache_logging_log4j_log4j_to_slf4j_2_17_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_el_9_0_58.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_expression_5_3_16.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__commons_collections_commons_collections_3_2_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__io_springfox_springfox_spring_webmvc_3_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_engine_5_8_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_params_5_8_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_test_2_6_4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__io_springfox_springfox_spring_webflux_3_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__io_springfox_springfox_swagger_common_3_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__ai_djl_paddlepaddle_paddlepaddle_engine_0_15_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_junit_platform_junit_platform_engine_1_8_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__io_springfox_springfox_bean_validators_3_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_core_9_0_58.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_databind_2_13_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__jakarta_activation_jakarta_activation_api_1_2_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__jakarta_annotation_jakarta_annotation_api_1_3_5.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_junit_platform_junit_platform_commons_1_8_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_2_6_4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__ai_djl_paddlepaddle_paddlepaddle_model_zoo_0_15_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_annotations_2_13_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_websocket_9_0_58.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/main/java/com/sy/layout/LayoutProperties.java: -------------------------------------------------------------------------------- 1 | package com.sy.layout; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | /** 8 | * @author sy 9 | * @date 2022/9/13 21:56 10 | */ 11 | @Data 12 | @ConfigurationProperties(prefix = "doc.ai.layout1") 13 | @Configuration 14 | public class LayoutProperties { 15 | private String deviceType = "cpu"; 16 | private String yoloUrl = "/model/layout/layout.zip"; 17 | private String modelName = "layout_model.onnx"; 18 | private String nameList = "coco.names"; 19 | private Float threshold = 0.45f; 20 | private Integer width = 640; 21 | private Integer height = 640; 22 | } 23 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_web_2_6_4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_json_2_6_4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_test_2_6_4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_autoconfigure_2_6_4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jdk8_2_13_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_tomcat_2_6_4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_logging_2_6_4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_plugin_spring_plugin_core_2_0_0_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jsr310_2_13_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_vaadin_external_google_android_json_0_0_20131108_vaadin1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/main/java/com/sy/ocr/OcrProperties.java: -------------------------------------------------------------------------------- 1 | package com.sy.ocr; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | /** 8 | * @author sy 9 | * @date 2022/9/13 22:24 10 | */ 11 | @Data 12 | @ConfigurationProperties(prefix = "doc.ai.ocr") 13 | @Configuration 14 | public class OcrProperties { 15 | private String detectUrl = "/model/ocr/ocr_det_model.onnx"; 16 | private String recognizeUrl = "/model/ocr/ocr_rec_model.onnx"; 17 | private String recognizerUrl = "/model/ocr/ch_ppocr_mobile_v2.0_cls_infer.zip"; 18 | private String deviceType = "cpu"; 19 | private String ppocrKeysV1Path = "/model/ocr/ppocr_keys_v1.txt"; 20 | private double rotateThreshold = 0.8; 21 | } 22 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_test_autoconfigure_2_6_4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_plugin_spring_plugin_metadata_2_0_0_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_fasterxml_jackson_module_jackson_module_parameter_names_2_13_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_configuration_processor_2_6_4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | -------------------------------------------------------------------------------- /src/main/java/com/utils/PropertiesReader.java: -------------------------------------------------------------------------------- 1 | package com.utils; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStreamReader; 8 | import java.util.Properties; 9 | 10 | /** 11 | * @author sy 12 | * @date 2022/9/14 19:07 13 | */ 14 | public class PropertiesReader { 15 | 16 | private static final Logger LOGGER = LoggerFactory.getLogger(PropertiesReader.class); 17 | 18 | private static Properties properties = new Properties(); 19 | 20 | static { 21 | try { 22 | properties.load(new InputStreamReader(PropertiesReader.class.getClassLoader().getResourceAsStream("properties.properties"), "UTF-8")); 23 | 24 | } catch (IOException e) { 25 | e.printStackTrace(); 26 | } 27 | } 28 | 29 | public static String get(String keyName) { 30 | return properties.getProperty(keyName, ""); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | -------------------------------------------------------------------------------- /src/main/java/com/utils/FileUploadConfig.java: -------------------------------------------------------------------------------- 1 | package com.utils; 2 | 3 | import ai.djl.training.dataset.Dataset; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | import org.springframework.boot.web.servlet.MultipartConfigFactory; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.util.unit.DataSize; 10 | 11 | import javax.servlet.MultipartConfigElement; 12 | 13 | /** 14 | * @author sy 15 | * @date 2022/11/11 22:57 16 | */ 17 | @Configuration 18 | public class FileUploadConfig { 19 | @Bean 20 | public MultipartConfigElement multipartConfigElement() { 21 | MultipartConfigFactory multipartConfigFactory = new MultipartConfigFactory(); 22 | // 单个文件大小为5MB 23 | multipartConfigFactory.setMaxFileSize(DataSize.ofMegabytes(5)); 24 | // 总上传数据大小10MB 25 | multipartConfigFactory.setMaxRequestSize(DataSize.ofMegabytes(10)); 26 | return multipartConfigFactory.createMultipartConfig(); 27 | } 28 | } 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/main/java/com/sy/common/ModelUrlUtils.java: -------------------------------------------------------------------------------- 1 | package com.sy.common; 2 | 3 | import lombok.SneakyThrows; 4 | import lombok.experimental.UtilityClass; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.core.io.ClassPathResource; 7 | 8 | import java.io.IOException; 9 | import java.net.URI; 10 | 11 | /** 12 | * @author sy 13 | * @date 2022/9/13 15:24 14 | */ 15 | @UtilityClass 16 | @Slf4j 17 | public class ModelUrlUtils { 18 | 19 | /** 20 | * 获取模型url,如果是http或file开头,直接返回 21 | * @param name 模型名称 22 | * @return url 23 | */ 24 | @SneakyThrows 25 | public static String getRealUrl(String name) { 26 | if (name.startsWith("http") || name.startsWith("file:")) { 27 | System.out.println("model url is : " + name); 28 | return name; 29 | } 30 | 31 | URI uri = null; 32 | try { 33 | uri = new ClassPathResource(name).getURI(); 34 | } catch (IOException e) { 35 | e.printStackTrace(); 36 | } 37 | 38 | System.out.println("model uri of " + name + " is " + uri); 39 | if (uri.toString().startsWith("jar:")) { 40 | return "jar://" + name; 41 | } 42 | 43 | return uri.toString(); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

DJL for document AI

2 | 3 | 4 |
5 | Table of Contents 6 |
    7 |
  1. 8 | About 9 |
  2. 10 |
  3. 11 | Getting Started 12 |
  4. 13 |
  5. 14 | Result 15 |
  6. 16 |
  7. 17 | Contact 18 |
  8. 19 |
  9. 20 | Reference 21 |
  10. 22 | 23 |
24 |
25 | 26 | #### About 27 | 28 | 这里将paddle中的ocr等模型转为onnx格式,并利用java版深度框架djl加载这些onnx模型进行推理预测尝试。 29 | 30 | #### Getting started 31 | onnx模型下载: 32 | 33 | 链接:https://pan.baidu.com/s/1Vcsn-VPTU_GHB_KU4pQFPg 34 | 35 | 提取码:uepl 36 | 37 | 项目启动后可以进入swagger进行接口使用 http://localhost:8080/swagger-ui/ 38 | 39 | #### Result 40 | ![image](https://raw.githubusercontent.com/jiangnanboy/doc_ai/master/img/layout_result.png) 41 | 42 | ![image](https://raw.githubusercontent.com/jiangnanboy/doc_ai/master/img/ocr_result.png) 43 | 44 | 45 | #### Contact 46 | 如有问题,联系我: 47 | 48 | 1、github:https://github.com/jiangnanboy 49 | 50 | 2、QQ:2229029156 51 | 52 | #### Reference 53 | https://github.com/PaddlePaddle/PaddleOCR 54 | 55 | https://github.com/deepjavalibrary/djl 56 | 57 | 58 | -------------------------------------------------------------------------------- /src/main/java/com/utils/CollectionUtil.java: -------------------------------------------------------------------------------- 1 | package com.utils; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * @author sy 7 | * @date 2022/9/14 21:36 8 | */ 9 | public class CollectionUtil { 10 | 11 | public static List newArrayList() { 12 | return new ArrayList<>(); 13 | } 14 | 15 | public static LinkedList newLinkedList() { 16 | return new LinkedList<>(); 17 | } 18 | 19 | public static List newArrayList(int N) { 20 | return new ArrayList<>(N); 21 | } 22 | 23 | public static List newArrayList(Set entry) { 24 | return new ArrayList<>(entry); 25 | } 26 | 27 | public static Set newHashset() { 28 | return new HashSet<>(); 29 | } 30 | 31 | public static Set newHashset(List entry) { 32 | return new HashSet<>(entry); 33 | } 34 | 35 | public static Map newHashMap() { 36 | return new HashMap<>(); 37 | } 38 | 39 | public static LinkedHashMap newLinkedHashMap() { 40 | return new LinkedHashMap<>(); 41 | } 42 | 43 | public static Map newTreeMap() { 44 | return new TreeMap<>(); 45 | } 46 | 47 | public static List newArrayList(List asList) { 48 | return asList; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/sy/common/DetectObjectDto.java: -------------------------------------------------------------------------------- 1 | package com.sy.common; 2 | 3 | import ai.djl.modality.Classifications; 4 | import ai.djl.modality.cv.output.DetectedObjects; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import lombok.experimental.Accessors; 8 | 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | import static java.util.Objects.isNull; 13 | 14 | /** 15 | * @author sy 16 | * @date 2022/9/13 19:24 17 | */ 18 | @Data 19 | @Accessors(chain = true) 20 | @NoArgsConstructor 21 | public class DetectObjectDto { 22 | private String className; 23 | private Double probability; 24 | private Double x; 25 | private Double y; 26 | private Double width; 27 | private Double height; 28 | private Map data; 29 | 30 | public DetectObjectDto(Classifications.Classification item) { 31 | if (!(item instanceof DetectedObjects.DetectedObject)) { 32 | throw new IllegalArgumentException("item is not DetectedObject"); 33 | } 34 | 35 | DetectedObjects.DetectedObject i = (DetectedObjects.DetectedObject) item; 36 | 37 | this.className = i.getClassName(); 38 | this.x = i.getBoundingBox().getBounds().getX(); 39 | this.y = i.getBoundingBox().getBounds().getY(); 40 | this.width = i.getBoundingBox().getBounds().getWidth(); 41 | this.height = i.getBoundingBox().getBounds().getHeight(); 42 | } 43 | 44 | public Map getData() { 45 | if (isNull(data)) { 46 | data = new HashMap<>(); 47 | } 48 | return data; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/sy/ocr/MyRotateTranslator.java: -------------------------------------------------------------------------------- 1 | package com.sy.ocr; 2 | 3 | import ai.djl.modality.Classifications; 4 | import ai.djl.modality.cv.Image; 5 | import ai.djl.modality.cv.util.NDImageUtils; 6 | import ai.djl.ndarray.NDArray; 7 | import ai.djl.ndarray.NDList; 8 | import ai.djl.translate.NoBatchifyTranslator; 9 | import ai.djl.translate.TranslatorContext; 10 | import com.utils.CollectionUtil; 11 | 12 | import java.util.Arrays; 13 | import java.util.List; 14 | 15 | /** 16 | * @author sy 17 | * @date 2022/11/9 23:59 18 | */ 19 | public class MyRotateTranslator implements NoBatchifyTranslator { 20 | List rotateCls = Arrays.asList("No Rotate", "Rotate"); 21 | 22 | public MyRotateTranslator() { 23 | } 24 | 25 | @Override 26 | public Classifications processOutput(TranslatorContext ctx, NDList list) { 27 | NDArray prob = list.singletonOrThrow(); 28 | float[] probDoub = prob.toFloatArray(); 29 | List probabilities = CollectionUtil.newArrayList(); 30 | probabilities.add((double) probDoub[0]); 31 | probabilities.add((double) probDoub[1]); 32 | System.out.println("prob: " + probabilities.get(0) + " " + probabilities.get(1)); 33 | return new Classifications(this.rotateCls, probabilities); 34 | } 35 | 36 | @Override 37 | public NDList processInput(TranslatorContext ctx, Image input) { 38 | NDArray img = input.toNDArray(ctx.getNDManager()); 39 | int[] hw = this.resize32((double) input.getHeight(), (double) input.getWidth()); 40 | img = NDImageUtils.resize(img, hw[1], hw[0]); 41 | img = NDImageUtils.toTensor(img).sub(0.5F).div(0.5F); 42 | img = img.expandDims(0); 43 | return new NDList(new NDArray[]{img}); 44 | } 45 | 46 | private int[] resize32(double h, double w) { 47 | double min = Math.min(h, w); 48 | if (min < 32.0D) { 49 | h = 32.0D / min * h; 50 | w = 32.0D / min * w; 51 | } 52 | 53 | int h32 = (int) h / 32; 54 | int w32 = (int) w / 32; 55 | return new int[]{h32 * 32, w32 * 32}; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/sy/ocr/MyRecognitionTranslator.java: -------------------------------------------------------------------------------- 1 | package com.sy.ocr; 2 | 3 | import ai.djl.modality.cv.Image; 4 | import ai.djl.modality.cv.util.NDImageUtils; 5 | import ai.djl.ndarray.NDArray; 6 | import ai.djl.ndarray.NDList; 7 | import ai.djl.translate.NoBatchifyTranslator; 8 | import ai.djl.translate.TranslatorContext; 9 | 10 | import java.io.BufferedReader; 11 | import java.io.IOException; 12 | import java.nio.charset.StandardCharsets; 13 | import java.nio.file.Files; 14 | import java.nio.file.Paths; 15 | import java.util.List; 16 | import java.util.stream.Collectors; 17 | 18 | /** 19 | * @author sy 20 | * @date 2022/11/8 22:00 21 | */ 22 | public class MyRecognitionTranslator implements NoBatchifyTranslator { 23 | 24 | private List synset; 25 | 26 | public MyRecognitionTranslator(String keysPath) { 27 | try(BufferedReader br = Files.newBufferedReader(Paths.get(keysPath), StandardCharsets.UTF_8)) { 28 | synset = br.lines().collect(Collectors.toList()); 29 | synset.add(0, "blank"); 30 | synset.add(""); 31 | } catch (IOException i) { 32 | i.printStackTrace(); 33 | } 34 | } 35 | 36 | @Override 37 | public String processOutput(TranslatorContext ctx, NDList list) { 38 | StringBuilder sb = new StringBuilder(); 39 | NDArray tokens = list.singletonOrThrow(); 40 | long[] indices = tokens.get(new long[]{0L}).argMax(1).toLongArray(); 41 | int lastIdx = 0; 42 | for(int i = 0; i < indices.length; ++i) { 43 | if (indices[i] > 0L && (i <= 0 || indices[i] != (long)lastIdx)) { 44 | sb.append((String)this.synset.get((int)indices[i])); 45 | } 46 | } 47 | return sb.toString(); 48 | } 49 | 50 | @Override 51 | public NDList processInput(TranslatorContext ctx, Image image) { 52 | NDArray img = image.toNDArray(ctx.getNDManager()); 53 | int[] hw = this.resize32((double)image.getWidth()); 54 | img = NDImageUtils.resize(img, hw[1], hw[0]); 55 | img = NDImageUtils.toTensor(img).sub(0.5F).div(0.5F); 56 | img = img.expandDims(0); 57 | return new NDList(new NDArray[]{img}); 58 | } 59 | 60 | private int[] resize32(double w) { 61 | int width = (int)Math.max(32.0D, w) / 32 * 32; 62 | return new int[]{48, width}; 63 | } 64 | 65 | } 66 | 67 | -------------------------------------------------------------------------------- /src/main/java/com/sy/ocr/OcrController.java: -------------------------------------------------------------------------------- 1 | package com.sy.ocr; 2 | 3 | import ai.djl.modality.cv.Image; 4 | import ai.djl.modality.cv.ImageFactory; 5 | import ai.djl.modality.cv.output.DetectedObjects; 6 | import com.sy.common.DetectObjectDto; 7 | import com.sy.common.ImageUtils; 8 | import io.swagger.annotations.ApiOperation; 9 | import lombok.RequiredArgsConstructor; 10 | import lombok.extern.slf4j.Slf4j; 11 | import org.apache.commons.lang3.tuple.Pair; 12 | import org.springframework.web.bind.annotation.*; 13 | import org.springframework.web.multipart.MultipartFile; 14 | 15 | import javax.imageio.ImageIO; 16 | import javax.servlet.ServletOutputStream; 17 | import javax.servlet.http.HttpServletResponse; 18 | import java.awt.image.BufferedImage; 19 | import java.io.IOException; 20 | import java.util.List; 21 | import java.util.stream.Collectors; 22 | 23 | //import static com.sy.common.ImageUtils.evalAngle; 24 | 25 | 26 | /** 27 | * @author sy 28 | * @date 2022/9/13 21:43 29 | */ 30 | @RestController 31 | @RequestMapping("ocr") 32 | @RequiredArgsConstructor 33 | @Slf4j 34 | public class OcrController { 35 | 36 | private final OcrService ocrService; 37 | 38 | /** 39 | * 返回文字识别后的图片 40 | * 41 | * @param image 42 | * @param response 43 | * @throws IOException 44 | */ 45 | @PostMapping("image") 46 | @ApiOperation("文字识别,返回图片结果") 47 | public void ocrImage(@RequestPart MultipartFile image, HttpServletResponse response) throws IOException { 48 | Image img = ImageFactory.getInstance().fromInputStream(image.getInputStream()); 49 | img = ImageUtils.checkSize(img); 50 | DetectedObjects result = ocrService.ocr(img); 51 | BufferedImage resultImage = ocrService.createResultImage(img, result); 52 | response.setContentType("image/png"); 53 | ServletOutputStream os = response.getOutputStream(); 54 | ImageIO.write(resultImage, "PNG", os); 55 | os.flush(); 56 | } 57 | 58 | /** 59 | * @param image 60 | * @return 61 | * @throws IOException 62 | */ 63 | @PostMapping 64 | @ApiOperation("文字识别,返回对象结果") 65 | public List ocr(@RequestPart MultipartFile image) throws IOException { 66 | Image img = ImageFactory.getInstance().fromInputStream(image.getInputStream()); 67 | img = ImageUtils.checkSize(img); 68 | DetectedObjects result = ocrService.ocr(img); 69 | return result.items().stream().map(DetectObjectDto::new).collect(Collectors.toList()); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/sy/layout/LayoutTranslator.java: -------------------------------------------------------------------------------- 1 | package com.sy.layout; 2 | 3 | import ai.djl.modality.cv.Image; 4 | import ai.djl.modality.cv.output.BoundingBox; 5 | import ai.djl.modality.cv.output.DetectedObjects; 6 | import ai.djl.modality.cv.output.Rectangle; 7 | import ai.djl.ndarray.NDList; 8 | import ai.djl.translate.Batchifier; 9 | import ai.djl.translate.Translator; 10 | import ai.djl.translate.TranslatorContext; 11 | import com.utils.CollectionUtil; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | * @author sy 17 | * @date 2022/9/13 21:07 18 | */ 19 | public class LayoutTranslator implements Translator { 20 | 21 | private final LayoutProperties layoutProperties; 22 | 23 | private final Translator delegated; 24 | 25 | public LayoutTranslator(Translator translator, LayoutProperties layoutProperties) { 26 | this.delegated = translator; 27 | this.layoutProperties = layoutProperties; 28 | } 29 | 30 | @Override 31 | public DetectedObjects processOutput(TranslatorContext ctx, NDList list) throws Exception { 32 | DetectedObjects output = delegated.processOutput(ctx, list); 33 | List classList = CollectionUtil.newArrayList(); 34 | List probList = CollectionUtil.newArrayList(); 35 | List rectList = CollectionUtil.newArrayList(); 36 | 37 | final int width = layoutProperties.getWidth(); 38 | final int height = layoutProperties.getHeight(); 39 | 40 | final List items = output.items(); 41 | items.forEach(item -> { 42 | classList.add(item.getClassName()); 43 | probList.add(item.getProbability()); 44 | 45 | Rectangle b = item.getBoundingBox().getBounds(); 46 | Rectangle newBox = new Rectangle(b.getX() / width, b.getY() / height, b.getWidth() / width, b.getHeight() / height); 47 | 48 | rectList.add(newBox); 49 | }); 50 | return new DetectedObjects(classList, probList, rectList); 51 | } 52 | 53 | @Override 54 | public NDList processInput(TranslatorContext ctx, Image input) throws Exception { 55 | return delegated.processInput(ctx, input); 56 | } 57 | 58 | @Override 59 | public void prepare(TranslatorContext ctx) throws Exception { 60 | delegated.prepare(ctx); 61 | } 62 | 63 | @Override 64 | public Batchifier getBatchifier() { 65 | return delegated.getBatchifier(); 66 | } 67 | 68 | } 69 | 70 | -------------------------------------------------------------------------------- /src/main/java/com/sy/layout/LayoutController.java: -------------------------------------------------------------------------------- 1 | package com.sy.layout; 2 | 3 | import ai.djl.modality.cv.output.DetectedObjects; 4 | import com.sy.common.DetectObjectDto; 5 | import io.swagger.annotations.ApiOperation; 6 | import lombok.RequiredArgsConstructor; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.apache.commons.lang3.tuple.Pair; 9 | import org.springframework.web.bind.annotation.PostMapping; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RequestPart; 12 | import org.springframework.web.bind.annotation.RestController; 13 | import org.springframework.web.multipart.MultipartFile; 14 | 15 | import javax.imageio.ImageIO; 16 | import javax.servlet.ServletOutputStream; 17 | import javax.servlet.http.HttpServletResponse; 18 | import java.awt.image.BufferedImage; 19 | import java.io.IOException; 20 | import java.util.List; 21 | import java.util.stream.Collectors; 22 | 23 | import static com.sy.common.ImageUtils.evalAngle; 24 | 25 | /** 26 | * @author sy 27 | * @date 2022/9/13 22:00 28 | */ 29 | @RestController 30 | @RequestMapping("layout_onnx") 31 | @RequiredArgsConstructor 32 | @Slf4j 33 | public class LayoutController { 34 | 35 | private final LayoutService layoutService; 36 | 37 | @PostMapping("image") 38 | @ApiOperation("图片文档版面检测,返回图片结果") 39 | public void ocr(@RequestPart MultipartFile file, HttpServletResponse response) throws IOException { 40 | BufferedImage image = ImageIO.read(file.getInputStream()); 41 | Pair pair = evalAngle(image); 42 | double skew = pair.getLeft(); 43 | BufferedImage imageRes = pair.getRight(); 44 | if(skew != 0) { 45 | image = imageRes; 46 | } 47 | BufferedImage result = layoutService.getResultImage(image); 48 | response.setContentType("image/png"); 49 | ServletOutputStream os = response.getOutputStream(); 50 | ImageIO.write(result, "PNG", os); 51 | os.flush(); 52 | } 53 | 54 | @PostMapping 55 | @ApiOperation("图片文档版面检测,返回结果对象") 56 | public List ocr(@RequestPart MultipartFile file) throws IOException { 57 | BufferedImage image = ImageIO.read(file.getInputStream()); 58 | Pair pair = evalAngle(image); 59 | double skew = pair.getLeft(); 60 | BufferedImage imageRes = pair.getRight(); 61 | if(skew != 0) { 62 | image = imageRes; 63 | } 64 | DetectedObjects result = layoutService.detect(image); 65 | return result.items().stream().map(DetectObjectDto::new).collect(Collectors.toList()); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/sy/layout/LayoutService.java: -------------------------------------------------------------------------------- 1 | package com.sy.layout; 2 | 3 | import ai.djl.Device; 4 | import ai.djl.MalformedModelException; 5 | import ai.djl.inference.Predictor; 6 | import ai.djl.modality.cv.Image; 7 | import ai.djl.modality.cv.ImageFactory; 8 | import ai.djl.modality.cv.output.DetectedObjects; 9 | import ai.djl.modality.cv.translator.YoloV5Translator; 10 | import ai.djl.repository.zoo.Criteria; 11 | import ai.djl.repository.zoo.ModelNotFoundException; 12 | import ai.djl.repository.zoo.ModelZoo; 13 | import ai.djl.repository.zoo.ZooModel; 14 | import ai.djl.translate.TranslateException; 15 | import ai.djl.translate.Translator; 16 | import com.sy.common.ImageUtils; 17 | import com.sy.common.ModelUrlUtils; 18 | import lombok.RequiredArgsConstructor; 19 | import lombok.SneakyThrows; 20 | import lombok.extern.slf4j.Slf4j; 21 | import org.springframework.stereotype.Service; 22 | 23 | import javax.annotation.PostConstruct; 24 | import javax.annotation.PreDestroy; 25 | import java.awt.image.BufferedImage; 26 | import java.io.IOException; 27 | 28 | import static com.sy.common.Constants.ENGINE_ONNX; 29 | import static com.sy.common.ImageUtils.scale; 30 | import static java.util.Objects.nonNull; 31 | 32 | /** 33 | * @author sy 34 | * @date 2022/9/13 19:32 35 | */ 36 | @Slf4j 37 | @Service 38 | @RequiredArgsConstructor 39 | public class LayoutService { 40 | 41 | private final LayoutProperties layoutProperties; 42 | private ZooModel layoutModel; 43 | private Device device = null; 44 | 45 | @PostConstruct 46 | public void init() throws ModelNotFoundException, MalformedModelException, IOException { 47 | device = Device.Type.CPU.equalsIgnoreCase(layoutProperties.getDeviceType()) ? Device.cpu() : Device.gpu(); 48 | System.out.println("开始加载YOLO模型"); 49 | loadLayoutModel(); 50 | System.out.println("YOLO模型加载完成"); 51 | } 52 | 53 | /** 54 | * 加载layout model 55 | * @throws MalformedModelException 56 | * @throws ModelNotFoundException 57 | * @throws IOException 58 | */ 59 | public void loadLayoutModel() throws MalformedModelException, ModelNotFoundException, IOException { 60 | Translator translator = YoloV5Translator 61 | .builder() 62 | .optThreshold(layoutProperties.getThreshold()) 63 | .optSynsetArtifactName(layoutProperties.getNameList()) 64 | .build(); 65 | LayoutTranslator myTranslator = new LayoutTranslator(translator, layoutProperties); 66 | Criteria criteria = Criteria.builder() 67 | .setTypes(Image.class, DetectedObjects.class) 68 | .optDevice(device) 69 | .optModelUrls(ModelUrlUtils.getRealUrl(layoutProperties.getYoloUrl())) 70 | .optModelName(layoutProperties.getModelName()) 71 | .optTranslator(myTranslator) 72 | .optEngine(ENGINE_ONNX) 73 | .build(); 74 | layoutModel = ModelZoo.loadModel(criteria); 75 | } 76 | 77 | @PreDestroy 78 | public void destroy() { 79 | if (nonNull(layoutModel)) { 80 | layoutModel.close(); 81 | } 82 | System.out.println("yolo model closed..."); 83 | } 84 | 85 | /** 86 | * 对象检测函数 87 | * @param image 图片,尺寸需满足yolo网络入参大小 88 | */ 89 | @SneakyThrows 90 | public DetectedObjects detect(BufferedImage image) { 91 | final BufferedImage scale = scale(image, layoutProperties.getWidth(), layoutProperties.getHeight()); 92 | Image img = ImageFactory.getInstance().fromImage(scale); 93 | return detect(img); 94 | } 95 | 96 | /** 97 | * 对象检测函数 98 | * @param image 99 | */ 100 | @SneakyThrows 101 | public DetectedObjects detect(Image image) { 102 | long startTime = System.currentTimeMillis(); 103 | Image scaledImage = scale(image, layoutProperties.getWidth(), layoutProperties.getHeight()); 104 | //开始检测图片 105 | DetectedObjects detections = null; 106 | try (Predictor predictor = layoutModel.newPredictor()) { 107 | detections = predictor.predict(scaledImage); 108 | } catch (TranslateException e) { 109 | e.printStackTrace(); 110 | } 111 | System.out.println("results : " + detections); 112 | System.out.println("detect cost : " + (System.currentTimeMillis() - startTime) + " ms"); 113 | return detections; 114 | } 115 | 116 | /** 117 | * 检测并绘制结果 118 | * @param image 119 | * @return 带有绘制结果的图片 120 | */ 121 | public BufferedImage getResultImage(BufferedImage image) { 122 | //将图片大小设置为网络输入要求的大小 123 | BufferedImage scale = scale(image, layoutProperties.getWidth(), layoutProperties.getHeight()); 124 | Image img = ImageFactory.getInstance().fromImage(scale); 125 | DetectedObjects detections = detect(img); 126 | //将结果绘制到图片中 127 | return ImageUtils.drawDetections(image, detections); 128 | } 129 | 130 | } 131 | 132 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.example 8 | doc_ai 9 | 1.0-SNAPSHOT 10 | 11 | 12 | org.springframework.boot 13 | spring-boot-starter-parent 14 | 2.6.4 15 | 16 | 17 | 18 | 19 | 11 20 | 1.10.0 21 | 1.9.1 22 | 23 | 24 | 25 | 26 | 27 | ai.djl 28 | bom 29 | 0.15.0 30 | pom 31 | import 32 | 33 | 34 | 35 | 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-web 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-configuration-processor 44 | true 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-starter-test 49 | 50 | 51 | 52 | org.projectlombok 53 | lombok 54 | true 55 | 56 | 57 | 58 | io.springfox 59 | springfox-boot-starter 60 | 3.0.0 61 | 62 | 63 | 64 | ai.djl 65 | api 66 | 67 | 68 | ai.djl.paddlepaddle 69 | paddlepaddle-model-zoo 70 | 71 | 72 | ai.djl.pytorch 73 | pytorch-model-zoo 74 | 75 | 76 | ai.djl.pytorch 77 | pytorch-engine 78 | runtime 79 | 80 | 81 | ai.djl.pytorch 82 | pytorch-native-auto 83 | ${pytorch.version} 84 | 85 | 86 | 87 | ai.djl.onnxruntime 88 | onnxruntime-engine 89 | 90 | 91 | com.microsoft.onnxruntime 92 | onnxruntime 93 | 94 | 95 | 96 | 97 | 98 | com.microsoft.onnxruntime 99 | onnxruntime 100 | ${onnx.version} 101 | runtime 102 | 103 | 104 | 105 | org.apache.commons 106 | commons-lang3 107 | 3.7 108 | 109 | 110 | 111 | org.apache.poi 112 | poi 113 | 4.0.0 114 | 115 | 116 | 117 | dom4j 118 | dom4j 119 | 1.6.1 120 | 121 | 122 | 123 | commons-collections 124 | commons-collections 125 | 3.2.2 126 | 127 | 128 | 129 | com.aspose 130 | aspose-ocr 131 | 22.9 132 | 133 | 134 | 135 | 136 | 137 | 138 | AsposeJavaAPI 139 | Aspose Java API 140 | https://releases.aspose.com/java/repo/ 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | org.springframework.boot 149 | spring-boot-maven-plugin 150 | 151 | 152 | 153 | org.projectlombok 154 | lombok 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 13 | 14 | 16 | 17 | 18 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 1668221848189 62 | 69 | 70 | 71 | 72 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /src/main/java/com/sy/ocr/OcrService.java: -------------------------------------------------------------------------------- 1 | package com.sy.ocr; 2 | 3 | import ai.djl.Device; 4 | import ai.djl.MalformedModelException; 5 | import ai.djl.inference.Predictor; 6 | import ai.djl.modality.Classifications; 7 | import ai.djl.modality.cv.Image; 8 | import ai.djl.modality.cv.ImageFactory; 9 | import ai.djl.modality.cv.output.BoundingBox; 10 | import ai.djl.modality.cv.output.DetectedObjects; 11 | import ai.djl.paddlepaddle.zoo.cv.imageclassification.PpWordRotateTranslator; 12 | import ai.djl.paddlepaddle.zoo.cv.objectdetection.PpWordDetectionTranslator; 13 | import ai.djl.repository.zoo.Criteria; 14 | import ai.djl.repository.zoo.ModelNotFoundException; 15 | import ai.djl.repository.zoo.ZooModel; 16 | import ai.djl.translate.TranslateException; 17 | import com.sy.common.ImageUtils; 18 | import com.sy.common.ModelUrlUtils; 19 | import com.utils.CollectionUtil; 20 | import lombok.RequiredArgsConstructor; 21 | import lombok.SneakyThrows; 22 | import lombok.extern.slf4j.Slf4j; 23 | import org.springframework.stereotype.Service; 24 | 25 | import javax.annotation.PostConstruct; 26 | import javax.annotation.PreDestroy; 27 | import java.awt.image.BufferedImage; 28 | import java.io.IOException; 29 | import java.util.List; 30 | import java.util.Optional; 31 | import java.util.concurrent.ConcurrentHashMap; 32 | 33 | import static com.sy.common.Constants.ENGINE_ONNX; 34 | import static com.sy.common.Constants.ENGINE_PADDLE; 35 | import static com.sy.common.ImageUtils.rotateImage; 36 | 37 | 38 | /** 39 | * @author sy 40 | * @date 2022/9/13 19:27 41 | */ 42 | @Service 43 | @Slf4j 44 | @RequiredArgsConstructor 45 | public class OcrService { 46 | private final OcrProperties prop; 47 | 48 | // 文本检测 49 | private ZooModel detector = null; 50 | // 文本方向检测 51 | private ZooModel classifier = null; 52 | // 文字识别 53 | private ZooModel recognizer = null; 54 | private Device device = null; 55 | 56 | /** 57 | * 初始化加载ocr几个模型 58 | */ 59 | @PostConstruct 60 | private void init() { 61 | device = Device.Type.CPU.equalsIgnoreCase(prop.getDeviceType()) ? Device.cpu() : Device.gpu(); 62 | System.out.println("开始加载Ocr工具类"); 63 | loadOcrDetModel(); 64 | loadOcrClsModel(); 65 | loadOcrRecModel(); 66 | System.out.println("加载Ocr工具类完成"); 67 | } 68 | 69 | /** 70 | * 文字识别 71 | * @param url 72 | * @return 73 | */ 74 | @SneakyThrows 75 | public DetectedObjects ocr(String url) { 76 | Image image = null; 77 | try { 78 | image = ImageFactory.getInstance().fromUrl(url); 79 | } catch (IOException e) { 80 | e.printStackTrace(); 81 | } 82 | return ocr(image); 83 | } 84 | 85 | /** 86 | * 文字识别 87 | * @param image 88 | * @return 89 | */ 90 | public DetectedObjects ocr(Image image) { 91 | DetectedObjects detect = detect(image); 92 | 93 | List names = CollectionUtil.newArrayList(); 94 | List prob = CollectionUtil.newArrayList(); 95 | List rect = CollectionUtil.newArrayList(); 96 | 97 | List list = detect.items(); 98 | for (DetectedObjects.DetectedObject result : list) { 99 | BoundingBox box = result.getBoundingBox(); 100 | 101 | //扩展文字块的大小,因为检测出来的文字块比实际文字块要小 102 | Image subImg = ImageUtils.getSubImage(image, ImageUtils.extendBox(box)); 103 | 104 | // if (subImg.getHeight() * 1.0 / subImg.getWidth() > 1.5) { 105 | // subImg = ImageUtils.rotateImage(subImg); 106 | // } 107 | 108 | Classifications.Classification classifications = checkRotate(subImg); 109 | if ("Rotate".equals(classifications.getClassName()) && classifications.getProbability() > prop.getRotateThreshold()) { 110 | subImg = rotateImage(subImg); 111 | } 112 | String name = recognize(subImg); 113 | names.add(name); 114 | prob.add(1.0); 115 | rect.add(box); 116 | } 117 | return new DetectedObjects(names, prob, rect); 118 | } 119 | 120 | /** 121 | * 结果图片 122 | * @param image 图片 123 | * @return image 124 | */ 125 | public BufferedImage createResultImage(Image image, DetectedObjects result) { 126 | image.drawBoundingBoxes(result); 127 | return (BufferedImage) image.getWrappedImage(); 128 | } 129 | 130 | /** 131 | * 文字识别 132 | * @param image 133 | */ 134 | @SneakyThrows 135 | private String recognize(Image image) { 136 | String result = null; 137 | try (Predictor predictor = recognizer.newPredictor()){ 138 | result = predictor.predict(image); 139 | } catch (TranslateException e) { 140 | e.printStackTrace(); 141 | } 142 | return result; 143 | } 144 | 145 | /** 146 | * 判断文字角度,如果需要旋转则进行相应处理 147 | * @return Classifications 148 | */ 149 | @SneakyThrows 150 | private Classifications.Classification checkRotate(Image image) { 151 | Classifications.Classification result = null; 152 | try (Predictor predictor = classifier.newPredictor()){ 153 | result = predictor.predict(image).best(); 154 | } catch (TranslateException e) { 155 | e.printStackTrace(); 156 | } 157 | return result; 158 | } 159 | 160 | /** 161 | * 检测文字所在区域 162 | * @param image 163 | * @return 164 | */ 165 | @SneakyThrows 166 | public DetectedObjects detect(Image image) { 167 | DetectedObjects result = null; 168 | try (Predictor predictor = detector.newPredictor()){ 169 | result = predictor.predict(image); 170 | } catch (TranslateException e) { 171 | e.printStackTrace(); 172 | } 173 | return result; 174 | } 175 | 176 | /** 177 | * 加载检测模型 178 | */ 179 | public void loadOcrDetModel() { 180 | Criteria criterial = Criteria.builder() 181 | .optEngine(ENGINE_ONNX) 182 | .optDevice(device) 183 | .setTypes(Image.class, DetectedObjects.class) 184 | .optModelUrls(ModelUrlUtils.getRealUrl(prop.getDetectUrl())) 185 | .optTranslator(new PpWordDetectionTranslator(new ConcurrentHashMap())) 186 | .build(); 187 | try { 188 | detector = criterial.loadModel(); 189 | } catch (IOException e) { 190 | e.printStackTrace(); 191 | } catch (ModelNotFoundException e) { 192 | e.printStackTrace(); 193 | } catch (MalformedModelException e) { 194 | e.printStackTrace(); 195 | } 196 | if(Optional.ofNullable(detector).isPresent()) { 197 | logModelInfo(detector); 198 | } 199 | } 200 | 201 | /** 202 | * 加载方向检测模型 203 | */ 204 | public void loadOcrClsModel() { 205 | Criteria criteria = Criteria.builder() 206 | .optEngine(ENGINE_PADDLE) 207 | .optDevice(device) 208 | .setTypes(Image.class, Classifications.class) 209 | .optModelUrls(ModelUrlUtils.getRealUrl(prop.getRecognizerUrl())) 210 | .optTranslator(new PpWordRotateTranslator()) 211 | .build(); 212 | try { 213 | classifier = criteria.loadModel(); 214 | } catch (IOException e) { 215 | e.printStackTrace(); 216 | } catch (ModelNotFoundException e) { 217 | e.printStackTrace(); 218 | } catch (MalformedModelException e) { 219 | e.printStackTrace(); 220 | } 221 | if(Optional.ofNullable(classifier).isPresent()) { 222 | logModelInfo(classifier); 223 | } 224 | } 225 | 226 | /** 227 | * 加载文字识别模型 228 | */ 229 | public void loadOcrRecModel() { 230 | String ppocrKeysV1Path = ModelUrlUtils.getRealUrl(prop.getPpocrKeysV1Path()); 231 | ppocrKeysV1Path = ppocrKeysV1Path.replace("file:/", ""); 232 | Criteria criteria = Criteria.builder() 233 | .optEngine(ENGINE_ONNX) 234 | .optDevice(device) 235 | .setTypes(Image.class, String.class) 236 | .optModelUrls(ModelUrlUtils.getRealUrl(prop.getRecognizeUrl())) 237 | .optTranslator(new MyRecognitionTranslator(ppocrKeysV1Path)) 238 | .build(); 239 | try { 240 | recognizer = criteria.loadModel(); 241 | } catch (IOException e) { 242 | e.printStackTrace(); 243 | } catch (ModelNotFoundException e) { 244 | e.printStackTrace(); 245 | } catch (MalformedModelException e) { 246 | e.printStackTrace(); 247 | } 248 | if(Optional.ofNullable(recognizer).isPresent()) { 249 | logModelInfo(recognizer); 250 | } 251 | } 252 | 253 | /** 254 | * 服务停止关闭所有模型 255 | */ 256 | @PreDestroy 257 | public void closeAll() { 258 | if(Optional.ofNullable(this.detector).isPresent()) { 259 | this.detector.close(); 260 | } 261 | if(Optional.ofNullable(this.recognizer).isPresent()) { 262 | this.recognizer.close(); 263 | } 264 | if(Optional.ofNullable(this.classifier).isPresent()) { 265 | this.classifier.close(); 266 | } 267 | System.out.println("close all models"); 268 | } 269 | 270 | /** 271 | * 打印model信息 272 | * @param model 273 | */ 274 | private void logModelInfo(ZooModel model) { 275 | System.out.println("model name : " + model.getName() + "\n" + 276 | "model path : " + model.getModelPath()); 277 | } 278 | 279 | } 280 | -------------------------------------------------------------------------------- /src/main/java/com/sy/common/ImageUtils.java: -------------------------------------------------------------------------------- 1 | package com.sy.common; 2 | 3 | import ai.djl.modality.cv.Image; 4 | import ai.djl.modality.cv.ImageFactory; 5 | import ai.djl.modality.cv.output.BoundingBox; 6 | import ai.djl.modality.cv.output.DetectedObjects; 7 | import ai.djl.modality.cv.output.Rectangle; 8 | import ai.djl.modality.cv.util.NDImageUtils; 9 | import ai.djl.ndarray.NDArray; 10 | import ai.djl.ndarray.NDManager; 11 | import ai.djl.ndarray.types.DataType; 12 | import com.aspose.ocr.AsposeOCR; 13 | import com.aspose.ocr.PreprocessingFilter; 14 | import com.aspose.ocr.RecognitionResult; 15 | import com.aspose.ocr.RecognitionSettings; 16 | import lombok.experimental.UtilityClass; 17 | import org.apache.commons.lang3.tuple.Pair; 18 | import org.assertj.core.util.Files; 19 | 20 | import javax.imageio.ImageIO; 21 | import java.awt.*; 22 | import java.awt.image.BufferedImage; 23 | import java.io.File; 24 | import java.io.IOException; 25 | import java.nio.file.Paths; 26 | import java.util.List; 27 | import java.util.Map; 28 | 29 | import static java.awt.Image.SCALE_DEFAULT; 30 | 31 | /** 32 | * @author sy 33 | * @date 2022/9/13 21:24 34 | */ 35 | @UtilityClass 36 | public class ImageUtils { 37 | 38 | private static final Map colorMap = Map.of( 39 | 0, new Color(200, 0, 0), 40 | 1, new Color(0, 200, 0), 41 | 2, new Color(0, 0, 200), 42 | 3, new Color(200, 200, 0), 43 | 4, new Color(200, 0, 200), 44 | 5, new Color(0, 200, 200) 45 | ); 46 | 47 | /** 48 | * 旋转图片90度 49 | * 50 | * @param image 图片 51 | * @return 旋转90度后的图片 52 | */ 53 | public static Image rotateImage(Image image) { 54 | try (NDManager manager = NDManager.newBaseManager()) { 55 | NDArray rotated = NDImageUtils.rotate90(image.toNDArray(manager), 1); 56 | return ImageFactory.getInstance().fromNDArray(rotated); 57 | } 58 | } 59 | 60 | public static Image readImg(String imgPath) { 61 | Image img = null; 62 | try { 63 | img = ImageFactory.getInstance().fromFile(Paths.get(imgPath)); 64 | img.getWrappedImage(); 65 | } catch (IOException e) { 66 | e.printStackTrace(); 67 | } 68 | return img; 69 | } 70 | 71 | /** 72 | * 图片缩放 73 | * 74 | * @param original 原始图 75 | * @param width 宽 76 | * @param height 高 77 | * @return 缩放后的图片 78 | */ 79 | public static BufferedImage scale(BufferedImage original, int width, int height) { 80 | if (width == original.getWidth() && height == original.getHeight()) { 81 | return original; 82 | } 83 | 84 | java.awt.Image scaledInstance = original.getScaledInstance(width, height, SCALE_DEFAULT); 85 | BufferedImage scaledImage = new BufferedImage(width, height, original.getType()); 86 | scaledImage.getGraphics().drawImage(scaledInstance, 0, 0, null); 87 | return scaledImage; 88 | } 89 | 90 | /** 91 | * 图片缩放 92 | * 93 | * @param original 原始图 94 | * @param width 宽 95 | * @param height 高 96 | * @return 缩放后的图片 97 | */ 98 | public static Image scale(Image original, int width, int height) { 99 | if (width == original.getWidth() && height == original.getHeight()) { 100 | return original; 101 | } 102 | 103 | try(NDManager manager = NDManager.newBaseManager()) { 104 | NDArray ndArray = original.toNDArray(manager); 105 | NDArray resize = NDImageUtils.resize(ndArray, width, height, Image.Interpolation.BILINEAR); 106 | resize = resize.toType(DataType.FLOAT32, false); // INT8 107 | resize = resize.div(255); 108 | return ImageFactory.getInstance().fromNDArray(resize); 109 | } 110 | } 111 | 112 | public static Image checkSize(Image image) { 113 | if((image.getHeight() > 960) && (image.getWidth() > 960)) { 114 | try (NDManager manager = NDManager.newBaseManager()) { 115 | NDArray ndArray = image.toNDArray(manager); 116 | ndArray = NDImageUtils.resize(ndArray, 960, 960); 117 | image = ImageFactory.getInstance().fromNDArray(ndArray.toType(DataType.UINT8, false)); 118 | } 119 | } 120 | return image; 121 | } 122 | 123 | /** 124 | * 绘制检测结果 125 | * djl自带的绘制内容太少,只有名称,因此做了修改 126 | * 以下是djl自带的绘制方法 127 | * Image img = ImageFactory.getInstance().fromImage(image); 128 | * img.drawBoundingBoxes(detections); 129 | * return (BufferedImage) img.getWrappedImage(); 130 | * 131 | * @param image 图片 132 | * @param detections 检测结果 133 | */ 134 | public static BufferedImage drawDetections(BufferedImage image, DetectedObjects detections) { 135 | 136 | Graphics2D g = (Graphics2D) image.getGraphics(); 137 | int stroke = 2; 138 | g.setStroke(new BasicStroke(stroke)); 139 | g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 140 | int imageWidth = image.getWidth(); 141 | int imageHeight = image.getHeight(); 142 | 143 | List list = detections.items(); 144 | for (DetectedObjects.DetectedObject result : list) { 145 | String className = result.getClassName(); 146 | BoundingBox box = result.getBoundingBox(); 147 | double probability = result.getProbability(); 148 | Color color = colorMap.get(Math.abs(className.hashCode() % 6)); 149 | g.setPaint(color); 150 | 151 | Rectangle rectangle = box.getBounds(); 152 | int x = (int) (rectangle.getX() * imageWidth); 153 | int y = (int) (rectangle.getY() * imageHeight); 154 | int width = (int) (rectangle.getWidth() * imageWidth); 155 | int height = (int) (rectangle.getHeight() * imageHeight); 156 | g.drawRect(x, y, width, height); 157 | 158 | drawText(g, className, probability, x, y, width); 159 | } 160 | g.dispose(); 161 | 162 | return image; 163 | } 164 | 165 | private static void drawText(Graphics2D g, String className, double probability, int x, int y, int width) { 166 | //设置水印的坐标 167 | String showText = String.format("%s %.0f%%", className, probability * 100); 168 | g.fillRect(x, y - 30, width, 30); 169 | 170 | g.setColor(Color.WHITE); 171 | g.setFont(new Font("Monospaced", Font.BOLD, 25));//设置字体 172 | g.drawString(showText, x, y - 10); 173 | } 174 | 175 | /** 176 | * 获取文字所在的区块图 177 | * 178 | * @param image 原始图片 179 | * @param box 子区块 180 | * @return 带有文字的image 181 | */ 182 | public static Image getSubImage(Image image, BoundingBox box) { 183 | Rectangle rect = box.getBounds(); 184 | 185 | int width = image.getWidth(); 186 | int height = image.getHeight(); 187 | int[] recovered = { 188 | (int) (rect.getX() * width), 189 | (int) (rect.getY() * height), 190 | (int) (rect.getWidth() * width), 191 | (int) (rect.getHeight() * height) 192 | }; 193 | return image.getSubImage(recovered[0], recovered[1], recovered[2], recovered[3]); 194 | } 195 | 196 | public static Image getExtendSubImage(Image img, BoundingBox box) { 197 | Rectangle rect = box.getBounds(); 198 | double[] extended = extendRect(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight()); 199 | int width = img.getWidth(); 200 | int height = img.getHeight(); 201 | int[] recovered = { 202 | (int) (extended[0] * width), 203 | (int) (extended[1] * height), 204 | (int) (extended[2] * width), 205 | (int) (extended[3] * height) 206 | }; 207 | return img.getSubImage(recovered[0], recovered[1], recovered[2], recovered[3]); 208 | } 209 | 210 | /** 211 | * 扩展矩形框 212 | * 213 | * @param box 矩形 214 | * @return 扩展后的大小 215 | */ 216 | public static BoundingBox extendBox(BoundingBox box) { 217 | Rectangle rect = box.getBounds(); 218 | double x = rect.getX(); 219 | double y = rect.getY(); 220 | double width = rect.getWidth(); 221 | double height = rect.getHeight(); 222 | 223 | double centerX = x + width / 2; 224 | double centerY = y + height / 2; 225 | if (width > height) { 226 | width += height * 2.0; 227 | height *= 3.0; 228 | } else { 229 | height += width * 2.0; 230 | width *= 3.0; 231 | } 232 | double newX = centerX - width / 2 < 0 ? 0 : centerX - width / 2; 233 | double newY = centerY - height / 2 < 0 ? 0 : centerY - height / 2; 234 | double newWidth = newX + width > 1 ? 1 - newX : width; 235 | double newHeight = newY + height > 1 ? 1 - newY : height; 236 | return new Rectangle(newX, newY, newWidth, newHeight); 237 | } 238 | 239 | public static double[] extendRect(double xmin, double ymin, double width, double height) { 240 | double centerx = xmin + width / 2; 241 | double centery = ymin + height / 2; 242 | if (width > height) { 243 | width += height * 2.0; 244 | height *= 3.0; 245 | } else { 246 | height += width * 2.0; 247 | width *= 3.0; 248 | } 249 | double newX = centerx - width / 2 < 0 ? 0 : centerx - width / 2; 250 | double newY = centery - height / 2 < 0 ? 0 : centery - height / 2; 251 | double newWidth = newX + width > 1 ? 1 - newX : width; 252 | double newHeight = newY + height > 1 ? 1 - newY : height; 253 | return new double[] {newX, newY, newWidth, newHeight}; 254 | } 255 | 256 | public static Pair evalAngle(BufferedImage image) { 257 | AsposeOCR asposeOCR = new AsposeOCR(); 258 | double skew=0; 259 | try { 260 | skew = asposeOCR.CalcSkewImage(image); 261 | } catch (IOException e) { 262 | e.printStackTrace(); 263 | } 264 | // 添加纠偏过滤器 265 | PreprocessingFilter filters = new PreprocessingFilter(); 266 | filters.add(PreprocessingFilter.AutoSkew()); 267 | BufferedImage imageRes = asposeOCR.PreprocessImage(image, filters); 268 | // 获取Graphics2D 269 | Graphics2D g2d = image.createGraphics(); 270 | //消除锯齿 271 | g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 272 | g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); 273 | // 释放对象 274 | g2d.dispose(); 275 | 276 | return Pair.of(skew, imageRes); 277 | } 278 | 279 | } 280 | 281 | -------------------------------------------------------------------------------- /doc_ai.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /.idea/doc_ai.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | --------------------------------------------------------------------------------