no message

This commit is contained in:
Calvin 2024-10-27 15:39:21 +08:00
parent 8812056b5c
commit 079f0ad71a
22 changed files with 3280 additions and 0 deletions

View File

@ -0,0 +1,41 @@
## 目录:
https://aias.top/
# 图像预处理SDK
在OCR文字识别的时候我们得到的图像一般情况下都不是正的多少都会有一定的倾斜。
所以需要将图片转正。并且图片有可能是透视视角拍摄,需要重新矫正。
### SDK功能
-图像转正
-图像二值化,灰度化,去燥等经典算法。
### 完善中的功能:
-完善透视矫正
-完善文字方向检测算法,判断转正后的图片角度,以便进一步旋转图片使得文字水平。
## 运行例子
运行成功后,命令行应该看到下面的信息:
```text
319.0 , 865.0
319.0 , 113.0
785.0 , 113.0
785.0 , 865.0
startLeft = 319
startUp = 113
width = 467
height = 753
```
输出图片效果如下:
![ocr_result](https://aias-home.oss-cn-beijing.aliyuncs.com/AIAS/image_sdk/images/rotation.png)
### 帮助
引擎定制化配置,可以提升首次运行的引擎下载速度,解决外网无法访问或者带宽过低的问题。
[引擎定制化配置](https://aias.top/engine_cpu.html)
### 官网:
[官网链接](https://www.aias.top/)
### Git地址
[Github链接](https://github.com/mymagicpower/AIAS)
[Gitee链接](https://gitee.com/mymagicpower/AIAS)

View File

@ -0,0 +1,188 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="CheckStyle-IDEA-Module">
<option name="configuration">
<map />
</option>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: com.google.code.gson:gson:2.8.6" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.30" level="project" />
<orderEntry type="library" name="Maven: commons-cli:commons-cli:1.4" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-slf4j-impl:2.12.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.12.1" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: org.apache.logging.log4j:log4j-core:2.12.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacv-platform:1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacv:1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacpp:1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:0.3.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:4.1.2-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:4.2.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flycapture:2.13.3.31-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:2.2.6-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:0.5.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect2:0.2.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense:1.12.4-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense2:2.29.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:videoinput:0.200-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:2.3.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:1.07-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:1.78.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:4.1.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas-platform:0.3.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:android-arm:0.3.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:android-arm64:0.3.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:android-x86:0.3.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:android-x86_64:0.3.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:ios-arm64:0.3.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:ios-x86_64:0.3.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:linux-x86:0.3.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:linux-x86_64:0.3.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:linux-armhf:0.3.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:linux-arm64:0.3.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:linux-ppc64le:0.3.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:macosx-x86_64:0.3.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:windows-x86:0.3.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:windows-x86_64:0.3.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv-platform:4.1.2-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:android-arm:4.1.2-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:android-arm64:4.1.2-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:android-x86:4.1.2-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:android-x86_64:4.1.2-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:ios-arm64:4.1.2-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:ios-x86_64:4.1.2-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:linux-x86:4.1.2-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:linux-x86_64:4.1.2-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:linux-armhf:4.1.2-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:linux-arm64:4.1.2-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:linux-ppc64le:4.1.2-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:macosx-x86_64:4.1.2-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:windows-x86:4.1.2-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:windows-x86_64:4.1.2-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg-platform:4.2.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:android-arm:4.2.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:android-arm64:4.2.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:android-x86:4.2.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:android-x86_64:4.2.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:linux-x86:4.2.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:linux-x86_64:4.2.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:linux-armhf:4.2.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:linux-arm64:4.2.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:linux-ppc64le:4.2.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:macosx-x86_64:4.2.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:windows-x86:4.2.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:windows-x86_64:4.2.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flycapture-platform:2.13.3.31-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flycapture:linux-x86:2.13.3.31-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flycapture:linux-x86_64:2.13.3.31-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flycapture:linux-armhf:2.13.3.31-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flycapture:linux-arm64:2.13.3.31-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flycapture:windows-x86:2.13.3.31-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flycapture:windows-x86_64:2.13.3.31-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394-platform:2.2.6-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:linux-x86:2.2.6-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:linux-x86_64:2.2.6-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:linux-armhf:2.2.6-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:linux-arm64:2.2.6-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:linux-ppc64le:2.2.6-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:macosx-x86_64:2.2.6-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:windows-x86:2.2.6-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:windows-x86_64:2.2.6-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect-platform:0.5.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:linux-x86:0.5.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:linux-x86_64:0.5.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:linux-armhf:0.5.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:linux-arm64:0.5.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:linux-ppc64le:0.5.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:macosx-x86_64:0.5.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:windows-x86:0.5.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:windows-x86_64:0.5.7-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect2-platform:0.2.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect2:linux-x86:0.2.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect2:linux-x86_64:0.2.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect2:macosx-x86_64:0.2.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect2:windows-x86_64:0.2.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense-platform:1.12.4-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense:linux-x86:1.12.4-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense:linux-x86_64:1.12.4-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense:macosx-x86_64:1.12.4-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense:windows-x86:1.12.4-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense:windows-x86_64:1.12.4-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense2-platform:2.29.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense2:linux-x86:2.29.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense2:linux-x86_64:2.29.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense2:macosx-x86_64:2.29.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense2:windows-x86:2.29.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense2:windows-x86_64:2.29.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:videoinput-platform:0.200-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:videoinput:windows-x86:0.200-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:videoinput:windows-x86_64:0.200-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus-platform:2.3.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:android-arm:2.3.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:android-arm64:2.3.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:android-x86:2.3.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:android-x86_64:2.3.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:linux-x86:2.3.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:linux-x86_64:2.3.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:linux-armhf:2.3.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:linux-arm64:2.3.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:linux-ppc64le:2.3.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:macosx-x86_64:2.3.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:windows-x86:2.3.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:windows-x86_64:2.3.1-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark-platform:1.07-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:android-arm:1.07-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:android-arm64:1.07-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:android-x86:1.07-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:android-x86_64:1.07-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:linux-x86:1.07-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:linux-x86_64:1.07-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:linux-armhf:1.07-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:linux-arm64:1.07-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:linux-ppc64le:1.07-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:macosx-x86_64:1.07-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:windows-x86:1.07-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:windows-x86_64:1.07-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica-platform:1.78.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:android-arm:1.78.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:android-arm64:1.78.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:android-x86:1.78.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:android-x86_64:1.78.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:linux-x86:1.78.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:linux-x86_64:1.78.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:linux-armhf:1.78.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:linux-arm64:1.78.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:linux-ppc64le:1.78.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:macosx-x86_64:1.78.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:windows-x86:1.78.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:windows-x86_64:1.78.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract-platform:4.1.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:android-arm:4.1.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:android-arm64:4.1.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:android-x86:4.1.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:android-x86_64:4.1.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:linux-x86:4.1.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:linux-x86_64:4.1.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:linux-armhf:4.1.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:linux-arm64:4.1.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:linux-ppc64le:4.1.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:macosx-x86_64:4.1.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:windows-x86:4.1.0-1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:windows-x86_64:4.1.0-1.5.2" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.projectlombok:lombok:1.18.18" level="project" />
<orderEntry type="library" name="Maven: junit:junit:4.13.1" level="project" />
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
<orderEntry type="library" name="aais-image-lib-0.1.0" level="project" />
</component>
</module>

View File

@ -0,0 +1,213 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="CheckStyle-IDEA-Module">
<option name="configuration">
<map />
</option>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: com.google.code.gson:gson:2.8.6" level="project" />
<orderEntry type="library" name="Maven: commons-cli:commons-cli:1.4" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-slf4j-impl:2.17.2" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.25" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.17.2" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: org.apache.logging.log4j:log4j-core:2.17.2" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacv-platform:1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacv:1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacpp:1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:0.3.19-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:4.5.5-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:5.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flycapture:2.13.3.31-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:2.2.6-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:0.5.7-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect2:0.2.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense:1.12.4-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense2:2.50.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:videoinput:0.200-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:2.3.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:1.07-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:1.82.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:5.0.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.openjfx:javafx-graphics:11" level="project" />
<orderEntry type="library" name="Maven: org.openjfx:javafx-graphics:mac:11" level="project" />
<orderEntry type="library" name="Maven: org.openjfx:javafx-base:11" level="project" />
<orderEntry type="library" name="Maven: org.openjfx:javafx-base:mac:11" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas-platform:0.3.19-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacpp-platform:1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacpp:android-arm:1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacpp:android-arm64:1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacpp:android-x86:1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacpp:android-x86_64:1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacpp:ios-arm64:1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacpp:ios-x86_64:1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacpp:linux-armhf:1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacpp:linux-arm64:1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacpp:linux-ppc64le:1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacpp:linux-x86:1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacpp:linux-x86_64:1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacpp:macosx-arm64:1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacpp:macosx-x86_64:1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacpp:windows-x86:1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacpp:windows-x86_64:1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:android-arm:0.3.19-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:android-arm64:0.3.19-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:android-x86:0.3.19-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:android-x86_64:0.3.19-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:ios-arm64:0.3.19-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:ios-x86_64:0.3.19-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:linux-x86:0.3.19-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:linux-x86_64:0.3.19-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:linux-armhf:0.3.19-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:linux-arm64:0.3.19-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:linux-ppc64le:0.3.19-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:macosx-arm64:0.3.19-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:macosx-x86_64:0.3.19-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:windows-x86:0.3.19-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:windows-x86_64:0.3.19-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv-platform:4.5.5-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:android-arm:4.5.5-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:android-arm64:4.5.5-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:android-x86:4.5.5-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:android-x86_64:4.5.5-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:ios-arm64:4.5.5-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:ios-x86_64:4.5.5-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:linux-x86:4.5.5-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:linux-x86_64:4.5.5-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:linux-armhf:4.5.5-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:linux-arm64:4.5.5-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:linux-ppc64le:4.5.5-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:macosx-arm64:4.5.5-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:macosx-x86_64:4.5.5-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:windows-x86:4.5.5-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:windows-x86_64:4.5.5-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg-platform:5.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:android-arm:5.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:android-arm64:5.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:android-x86:5.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:android-x86_64:5.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:linux-x86:5.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:linux-x86_64:5.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:linux-armhf:5.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:linux-arm64:5.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:linux-ppc64le:5.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:macosx-arm64:5.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:macosx-x86_64:5.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:windows-x86:5.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:windows-x86_64:5.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flycapture-platform:2.13.3.31-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flycapture:linux-x86:2.13.3.31-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flycapture:linux-x86_64:2.13.3.31-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flycapture:linux-armhf:2.13.3.31-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flycapture:linux-arm64:2.13.3.31-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flycapture:windows-x86:2.13.3.31-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flycapture:windows-x86_64:2.13.3.31-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394-platform:2.2.6-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:linux-x86:2.2.6-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:linux-x86_64:2.2.6-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:linux-armhf:2.2.6-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:linux-arm64:2.2.6-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:linux-ppc64le:2.2.6-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:macosx-x86_64:2.2.6-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:windows-x86:2.2.6-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:windows-x86_64:2.2.6-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect-platform:0.5.7-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:linux-x86:0.5.7-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:linux-x86_64:0.5.7-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:linux-armhf:0.5.7-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:linux-arm64:0.5.7-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:linux-ppc64le:0.5.7-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:macosx-x86_64:0.5.7-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:windows-x86:0.5.7-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:windows-x86_64:0.5.7-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect2-platform:0.2.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect2:linux-x86:0.2.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect2:linux-x86_64:0.2.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect2:macosx-x86_64:0.2.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect2:windows-x86_64:0.2.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense-platform:1.12.4-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense:linux-armhf:1.12.4-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense:linux-arm64:1.12.4-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense:linux-x86:1.12.4-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense:linux-x86_64:1.12.4-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense:macosx-x86_64:1.12.4-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense:windows-x86:1.12.4-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense:windows-x86_64:1.12.4-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense2-platform:2.50.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense2:linux-armhf:2.50.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense2:linux-arm64:2.50.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense2:linux-x86:2.50.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense2:linux-x86_64:2.50.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense2:macosx-x86_64:2.50.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense2:windows-x86:2.50.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense2:windows-x86_64:2.50.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:videoinput-platform:0.200-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:videoinput:windows-x86:0.200-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:videoinput:windows-x86_64:0.200-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus-platform:2.3.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:android-arm:2.3.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:android-arm64:2.3.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:android-x86:2.3.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:android-x86_64:2.3.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:linux-x86:2.3.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:linux-x86_64:2.3.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:linux-armhf:2.3.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:linux-arm64:2.3.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:linux-ppc64le:2.3.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:macosx-x86_64:2.3.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:windows-x86:2.3.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:windows-x86_64:2.3.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark-platform:1.07-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:android-arm:1.07-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:android-arm64:1.07-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:android-x86:1.07-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:android-x86_64:1.07-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:linux-x86:1.07-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:linux-x86_64:1.07-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:linux-armhf:1.07-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:linux-arm64:1.07-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:linux-ppc64le:1.07-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:macosx-x86_64:1.07-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:windows-x86:1.07-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:windows-x86_64:1.07-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica-platform:1.82.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:android-arm:1.82.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:android-arm64:1.82.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:android-x86:1.82.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:android-x86_64:1.82.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:linux-x86:1.82.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:linux-x86_64:1.82.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:linux-armhf:1.82.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:linux-arm64:1.82.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:linux-ppc64le:1.82.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:macosx-x86_64:1.82.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:windows-x86:1.82.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:windows-x86_64:1.82.0-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract-platform:5.0.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:android-arm:5.0.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:android-arm64:5.0.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:android-x86:5.0.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:android-x86_64:5.0.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:linux-x86:5.0.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:linux-x86_64:5.0.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:linux-armhf:5.0.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:linux-arm64:5.0.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:linux-ppc64le:5.0.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:macosx-x86_64:5.0.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:windows-x86:5.0.1-1.5.7" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:windows-x86_64:5.0.1-1.5.7" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.projectlombok:lombok:1.18.18" level="project" />
<orderEntry type="library" name="Maven: junit:junit:4.13.1" level="project" />
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
</component>
</module>

View File

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one
~ or more contributor license agreements. See the NOTICE file
~ distributed with this work for additional information
~ regarding copyright ownership. The ASF licenses this file
~ to you under the Apache License, Version 2.0 (the
~ "License"); you may not use this file except in compliance
~ with the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>aias</groupId>
<artifactId>image-sdk</artifactId>
<version>0.17.0</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
<version>3.8.1</version>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.17.2</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.7</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.18</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,47 @@
package me.aias;
import me.aias.util.BinaryUtils;
import me.aias.util.GeneralUtils;
import me.aias.util.GrayUtils;
import org.bytedeco.opencv.opencv_core.Mat;
import org.junit.Test;
public class TestBinaryUtils {
@Test
/**
* 测试opencv自带的二值化
* Test OpenCV's built-in binary method
*/
public void testBinaryNative(){
String imgPath = "src/test/resources/1.png";
String destPath = "build/output/binary/";
Mat src = GeneralUtils.matFactory(imgPath);
src = GrayUtils.grayColByAdapThreshold(src);
src = BinaryUtils.binaryNative(src);
GeneralUtils.saveImg(src , destPath + "binaryNative.png");
}
@Test
/**
* 测试自定义二值化
* Test custom binary method
*/
public void testBinaryzation(){
String imgPath = "src/test/resources/1.png";
String destPath = "build/output/binary/";
Mat src = GeneralUtils.matFactory(imgPath);
src = GrayUtils.grayColByAdapThreshold(src);
src = BinaryUtils.binaryzation(src);
GeneralUtils.saveImg(src , destPath + "binaryzation.png");
}
}

View File

@ -0,0 +1,105 @@
package me.aias;
import me.aias.util.GeneralUtils;
import me.aias.util.GrayUtils;
import org.bytedeco.opencv.opencv_core.Mat;
import org.junit.Test;
/**
* 测试灰度化
* Testing grayscale
*/
public class TestGrayUtils {
@Test
/**
* 测试opencv自带的灰度化方法
* Testing OpenCV's built-in grayscale method
*/
public void testGrayNative(){
String imgPath = "src/test/resources/1.png";
String destPath = "build/output/gray/";
Mat src = GeneralUtils.matFactory(imgPath);
src = GrayUtils.grayNative(src);
GeneralUtils.saveImg(src , destPath + "grayNative.png");
}
@Test
/**
* 测试细粒度灰度化方法
* Testing fine-grained grayscale method
* 均值灰度化减噪
* Mean grayscale denoising
*/
public void testGrayColByMidle() {
String imgPath = "src/test/resources/1.png";
String destPath = "build/output/gray/";
Mat src = GeneralUtils.matFactory(imgPath);
src = GrayUtils.grayColByMidle(src);
GeneralUtils.saveImg(src , destPath + "grayRowByMidle.png");
}
@Test
/**
* 测试细粒度灰度化方法
* Testing fine-grained grayscale method
* k值灰度化减噪
* K-value grayscale denoising
*/
public void testGrayColByKLargest() {
String imgPath = "src/test/resources/1.png";
String destPath = "build/output/gray/";
Mat src = GeneralUtils.matFactory(imgPath);
src = GrayUtils.grayColByKLargest(src);
GeneralUtils.saveImg(src , destPath + "grayRowByKLargest.png");
}
@Test
/**
* 测试细粒度灰度化方法
* Testing fine-grained grayscale method
* 局部自适应阀值灰度化减噪
* Local adaptive threshold grayscale denoising
*/
public void testGrayColByPartAdapThreshold() {
String imgPath = "src/test/resources/1.png";
String destPath = "build/output/gray/";
Mat src = GeneralUtils.matFactory(imgPath);
src = GrayUtils.grayColByPartAdapThreshold(src);
GeneralUtils.saveImg(src , destPath + "grayColByPartAdapThreshold.png");
}
@Test
/**
* 测试细粒度灰度化方法
* Testing fine-grained grayscale method
* 全局自适应阀值灰度化减噪
* Global adaptive threshold grayscale denoising
*/
public void testGrayColByAdapThreshold() {
String imgPath = "src/test/resources/1.png";
String destPath = "build/output/gray/";
Mat src = GeneralUtils.matFactory(imgPath);
src = GrayUtils.grayColByAdapThreshold(src);
GeneralUtils.saveImg(src , destPath + "grayColByAdapThreshold.png");
}
}

View File

@ -0,0 +1,60 @@
package me.aias;
import me.aias.util.BinaryUtils;
import me.aias.util.GeneralUtils;
import me.aias.util.GrayUtils;
import me.aias.util.NoiseUtils;
import org.bytedeco.opencv.opencv_core.Mat;
import org.junit.Test;
/**
* 测试降噪
* Test denoising
*/
public class TestRemoveNoiseUtils {
@Test
/**
* 测试8邻域降噪
* Test 8-neighborhood denoising
*/
public void testNativeRemoveNoise(){
String imgPath = "src/test/resources/1.png";
String destPath = "build/output/noise/";
Mat src = GeneralUtils.matFactory(imgPath);
src = GrayUtils.grayColByPartAdapThreshold(src);
src = BinaryUtils.binaryzation(src);
// 8邻域降噪
// 8-neighborhood denoising
src = NoiseUtils.navieRemoveNoise(src , 1);
GeneralUtils.saveImg(src , destPath + "nativeRemoveNoise.png");
}
@Test
/**
* 连通域降噪
* Connected domain denoising
*/
public void testConnectedRemoveNoise(){
String imgPath = "src/test/resources/1.png";
String destPath = "build/output/noise/";
Mat src = GeneralUtils.matFactory(imgPath);
src = GrayUtils.grayColByPartAdapThreshold(src);
src = BinaryUtils.binaryzation(src);
// 连通域降噪 - Connected domain denoising
src = NoiseUtils.connectedRemoveNoise(src , 1);
GeneralUtils.saveImg(src , destPath + "connectedRemoveNoise.png");
}
}

View File

@ -0,0 +1,62 @@
package me.aias;
import me.aias.util.*;
import org.bytedeco.opencv.opencv_core.*;
import java.io.IOException;
import java.util.stream.LongStream;
import static org.bytedeco.opencv.global.opencv_imgproc.*;
import static org.bytedeco.opencv.helper.opencv_imgcodecs.cvLoadImage;
public class TestRotation {
public static void main(String[] args) throws IOException {
IplImage marcel_ = cvLoadImage("src/test/resources/ticket_r2.png");
Mat marcel = new Mat(marcel_);
GeneralUtils.saveImg(marcel, "build/output/srcImg.jpg");
// 边缘检测
// Edge detection
Mat cannyMat = GeneralUtils.canny(marcel);
GeneralUtils.saveImg(cannyMat, "build/output/canny.jpg");
// 获取所有轮廓
// Get all the contours
MatVector contours = ContourUtils.getContours(cannyMat);
Mat resultImage = cannyMat.clone();
LongStream.range(0, contours.size())
.mapToObj(contours::get)
.forEach(
contour -> {
Mat points = new Mat();
approxPolyDP(contour, points, arcLength(contour, true) * 0.02, true);
drawContours(resultImage, new MatVector(points), -1, Scalar.BLUE);
});
GeneralUtils.saveImg(resultImage, "build/output/contours.jpg");
// 获取最大外接矩形
// Get the maximum bounding rectangle
RotatedRect rect = RectUtils.getMaxRect(contours);
Mat rectMat = marcel.clone();
Scalar scalar = new Scalar(255, 0, 0, 1);
Rect r = rect.boundingRect();
rectMat = DrawUtils.drawRect(rectMat, r, scalar);
GeneralUtils.saveImg(rectMat, "build/output/maxRect.jpg");
// 旋转矩形
// Rotate the rectangle
Mat rotatedImg = RotationUtils.rotation(cannyMat, rect);
GeneralUtils.saveImg(rotatedImg, "build/output/rotatedImg.jpg");
Mat nativeRotatedImg = RotationUtils.rotation(marcel, rect);
GeneralUtils.saveImg(nativeRotatedImg, "build/output/nativeRotatedImg.jpg");
// 裁剪矩形
// Crop the rectangle
Mat cutMat = RectUtils.cutRect(rotatedImg, nativeRotatedImg);
GeneralUtils.saveImg(cutMat, "build/output/cutRect.jpg");
}
}

View File

@ -0,0 +1,198 @@
package me.aias.util;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.Mat;
/**
* 二值化的工具类
*/
public class BinaryUtils {
/**
* opencv自带的二值化
* @param src
* @return
*/
public static Mat binaryNative(Mat src){
Mat dst = src.clone();
opencv_imgproc.adaptiveThreshold(src, dst, 255, opencv_imgproc.ADAPTIVE_THRESH_MEAN_C, opencv_imgproc.THRESH_BINARY, 25, 10);
return dst;
}
/**
* 图像二值化 阀值自适应确定
*
* @param src
* Mat矩阵图像
* @return
*/
public static Mat binaryzation(Mat src) {
if (src.channels() != 1) {
throw new RuntimeException("不是单通道图,需要先灰度话!!!");
}
int threshold = getAdapThreshold(src);
return binaryzation(src, threshold);
}
/**
* 图像二值化
*
* @param src
* Mat矩阵图像
* @param b
* [true/false] true表示白底黑字false表示黑底白字
* @return
*/
public static Mat binaryzation(Mat src, boolean b) {
if (src.channels() != 1) {
throw new RuntimeException("不是单通道图,需要先灰度话!!!");
}
int threshold = getAdapThreshold(src);
return binaryzation(src, threshold, b);
}
/**
* 图像二值化
*
* @param src
* Mat矩阵图像
* @param threshold
* 阀值
* @return
*/
public static Mat binaryzation(Mat src, int threshold) {
if (src.channels() != 1) {
throw new RuntimeException("不是单通道图,需要先灰度化");
}
return binaryzation(src, threshold, true);
}
/**
* 图像二值化
*
* @param src
* Mat矩阵图像
* @param threshold
* 阀值
* @param b
* [true/false] true表示白底黑字false表示黑底白字
* @return
*/
public static Mat binaryzation(Mat src, int threshold, boolean b) {
if (src.channels() != 1 || threshold < 0) {
System.out.println("不是单通道图像或者阀值异常");
return src;
}
int nWhite_sum = 0, nBlack_sum = 0;
int i, j;
int width = GeneralUtils.getImgWidth(src), height = GeneralUtils.getImgHeight(src);
int value;
for (j = 0; j < height; j++) {
for (i = 0; i < width; i++) {
value = GeneralUtils.getPixel(src, j, i);
if (value > threshold) {
GeneralUtils.setPixel(src, j, i, GeneralUtils.getWHITE());
nWhite_sum++;
} else {
GeneralUtils.setPixel(src, j, i, GeneralUtils.getBLACK());
nBlack_sum++;
}
}
}
if (b) {
// 白底黑字
if (nBlack_sum > nWhite_sum) {
src = GeneralUtils.turnPixel(src);
}
} else {
// 黑底白字
if (nWhite_sum > nBlack_sum) {
src = GeneralUtils.turnPixel(src);
}
}
return src;
}
/**
* 作用自适应选取阀值
*
* @param src
* Mat矩阵图像
* @return
*/
public static int getAdapThreshold(Mat src) {
int threshold = 0, threshold_new = 127;
int nWhite_count, nBlack_count;
int nWhite_sum, nBlack_sum;
int value, i, j;
int width = GeneralUtils.getImgWidth(src), height = GeneralUtils.getImgHeight(src);
if(width == 0 || height == 0){
System.out.println("图像加载异常");
return -1;
}
while (threshold != threshold_new) {
nWhite_sum = nBlack_sum = 0;
nWhite_count = nBlack_count = 0;
for (j = 0; j < height; j++) {
for (i = 0; i < width; i++) {
value = GeneralUtils.getPixel(src, j, i);
if (value > threshold_new) {
nWhite_count++;
nWhite_sum += value;
} else {
nBlack_count++;
nBlack_sum += value;
}
}
}
threshold = threshold_new;
if(nWhite_count == 0 || nBlack_count == 0){
threshold_new = (nWhite_sum + nBlack_sum) / (nWhite_count + nBlack_count);
}else{
threshold_new = (nWhite_sum / nWhite_count + nBlack_sum / nBlack_count) / 2;
}
}
return threshold;
}
/**
* 局部自适应二值化
* @param src
* @return
*/
public static Mat partBinaryzation(Mat src){
int width = GeneralUtils.getImgWidth(src);
int height = GeneralUtils.getImgHeight(src);
int value;
for(int i = 0 ; i < width ; i++){
Mat partMat = src.col(i);
int thresold = getAdapThreshold(partMat);
int black_num = 0 , white_num = 0;
for(int j = 0 ; j < height ; j++){
value = GeneralUtils.getPixel(src , j , i);
if(value > thresold){
GeneralUtils.setPixel(src , j , i , GeneralUtils.getWHITE());
white_num++;
}else{
GeneralUtils.setPixel(src, j, i, GeneralUtils.getBLACK());
black_num++;
}
}
}
return src;
}
}

View File

@ -0,0 +1,112 @@
package me.aias.util;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.MatVector;
import org.bytedeco.opencv.opencv_core.Point;
import org.bytedeco.opencv.opencv_core.RotatedRect;
import static org.bytedeco.opencv.global.opencv_imgproc.*;
/** 轮廓工具类 */
public class ContourUtils {
/**
* 寻找轮廓
*
* @param cannyMat
* @return
*/
public static MatVector getContours(Mat cannyMat) {
MatVector contours = new MatVector();
Mat hierarchy = new Mat();
// 寻找轮廓
// CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE
// CV_RETR_TREE
findContours(
cannyMat,
contours,
hierarchy,
opencv_imgproc.RETR_LIST,
opencv_imgproc.CHAIN_APPROX_SIMPLE,
new Point(0, 0));
if (contours.size() <= 0) {
throw new RuntimeException("未找到图像轮廓");
} else {
return contours;
}
}
/**
* 作用返回边缘检测之后的最大轮廓
*
* @param contours
* @return
*/
public static Mat getMaxContour(MatVector contours) {
// 找出匹配到的最大轮廓
double area = boundingRect(contours.get(0)).area();
int index = 0;
// 找出匹配到的最大轮廓
for (int i = 0; i < contours.size(); i++) {
double tempArea = boundingRect(contours.get(i)).area();
if (tempArea > area) {
area = tempArea;
index = i;
}
}
return contours.get(index);
}
/**
* 作用返回边缘检测之后的最大轮廓
*
* @param cannyMat Canny之后的Mat矩阵
* @return
*/
public static Mat getMaxContour(Mat cannyMat) {
MatVector contours = getContours(cannyMat);
// 找出匹配到的最大轮廓
double area = boundingRect(contours.get(0)).area();
int index = 0;
// 找出匹配到的最大轮廓
for (int i = 0; i < contours.size(); i++) {
double tempArea = boundingRect(contours.get(i)).area();
if (tempArea > area) {
area = tempArea;
index = i;
}
}
return contours.get(index);
}
/**
* 利用函数approxPolyDP来对指定的点集进行逼近 精确度设置好效果还是比较好的
*
* @param cannyMat
*/
public static Mat useApproxPolyDPFindPoints(Mat cannyMat) {
return useApproxPolyDPFindPoints(cannyMat, 0.01);
}
/**
* 利用函数approxPolyDP来对指定的点集进行逼近 精确度设置好效果还是比较好的
*
* @param cannyMat
* @param threshold 阀值(精确度)
* @return
*/
public static Mat useApproxPolyDPFindPoints(Mat cannyMat, double threshold) {
Mat maxContour = getMaxContour(cannyMat);
Mat approxCurve = new Mat();
// 原始曲线与近似曲线之间的最大距离设置为0.01true表示是闭合的曲线
opencv_imgproc.approxPolyDP(maxContour, approxCurve, threshold, true);
return approxCurve;
}
}

View File

@ -0,0 +1,104 @@
package me.aias.util;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.*;
import static org.bytedeco.opencv.global.opencv_imgproc.minAreaRect;
/** 画图工具类 */
public class DrawUtils {
/**
* 画出所有的矩形
*
* @param src
* @return
*/
public static Mat drawContours(Mat src, String filePath) {
Mat cannyMat = GeneralUtils.canny(src);
MatVector contours = ContourUtils.getContours(cannyMat);
Mat rectMat = src.clone();
Scalar scalar = new Scalar(255, 0, 0, 1);
for (long i = contours.size() - 1; i >= 0; i--) {
Mat mat = contours.get(i);
RotatedRect rect = minAreaRect(mat);
Rect r = rect.boundingRect();
System.out.println(r.area() + " --- " + i);
rectMat = drawRect(rectMat, r, scalar);
}
GeneralUtils.saveImg(rectMat, filePath);
return rectMat;
}
/**
* 画出最大的矩形
*
* @param src
* @return
*/
public static void drawMaxRect(Mat src, String filePath) {
Mat cannyMat = GeneralUtils.canny(src);
RotatedRect rect = RectUtils.getMaxRect(cannyMat);
Rect r = rect.boundingRect();
Mat rectMat = src.clone();
Scalar scalar = new Scalar(255, 0, 0, 1);
rectMat = drawRect(rectMat, r, scalar);
GeneralUtils.saveImg(rectMat, filePath);
}
/**
* 画矩形
*
* @param src
* @param r
* @param scalar
* @return
*/
public static Mat drawRect(Mat src, Rect r, Scalar scalar) {
Point pt1 = new Point(r.x(), r.y());
Point pt2 = new Point(r.x() + r.width(), r.y());
Point pt3 = new Point(r.x() + r.width(), r.y() + r.height());
Point pt4 = new Point(r.x(), r.y() + r.height());
opencv_imgproc.line(src, pt1, pt2, scalar);
opencv_imgproc.line(src, pt2, pt3, scalar);
opencv_imgproc.line(src, pt3, pt4, scalar);
opencv_imgproc.line(src, pt4, pt1, scalar);
return src;
}
/**
* 画实心圆
*
* @param src
* @param point
* @param size 点的尺寸
* @param scalar 颜色
* @param path 保存路径
*/
public static boolean drawCircle(Mat src, Point[] point, int size, Scalar scalar, String path) {
if (src == null || point == null) {
throw new RuntimeException("Mat 或者 Point 数组不能为NULL");
}
for (Point p : point) {
opencv_imgproc.circle(src, p, size, scalar);
}
if (path != null && !"".equals(path)) {
return GeneralUtils.saveImg(src, path);
}
return false;
}
}

View File

@ -0,0 +1,201 @@
package me.aias.util;
import org.bytedeco.javacpp.indexer.UByteRawIndexer;
import org.bytedeco.opencv.global.opencv_imgcodecs;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.Size;
/** opencv的一些通用方法工具类 */
public class GeneralUtils {
private static final int BLACK = 0;
private static final int WHITE = 255;
// 设置归一化图像的固定大小
private static final Size dsize = new Size(32, 32);
/**
* 作用输入图像路径返回mat矩阵
*
* @param imgPath 图像路径
* @return
*/
public static Mat matFactory(String imgPath) {
return opencv_imgcodecs.imread(imgPath);
}
/**
* 作用输入图像Mat矩阵对象返回图像的宽度
*
* @param src Mat矩阵图像
* @return
*/
public static int getImgWidth(Mat src) {
return src.cols();
}
/**
* 作用输入图像Mat矩阵返回图像的高度
*
* @param src Mat矩阵图像
* @return
*/
public static int getImgHeight(Mat src) {
return src.rows();
}
/**
* 作用获取图像(y,x)点的像素我们只针对单通道(灰度图)
*
* @param src Mat矩阵图像
* @param y y坐标轴
* @param x x坐标轴
* @return
*/
public static int getPixel(Mat src, int y, int x) {
UByteRawIndexer ldIdx = src.createIndexer();
int result = ldIdx.get(y, x);
ldIdx.release();
return result;
}
/**
* 作用设置图像(y,x)点的像素我们只针对单通道(灰度图)
*
* @param src Mat矩阵图像
* @param y y坐标轴 row
* @param x x坐标轴 col
* @param color 颜色值[0-255]
*/
public static void setPixel(Mat src, int y, int x, int color) {
UByteRawIndexer ldIdx = src.createIndexer();
ldIdx.put(y, x, color);
ldIdx.release();
}
/**
* 作用保存图像
*
* @param src Mat矩阵图像
* @param filePath 要保存图像的路径及名字
* @return
*/
public static boolean saveImg(Mat src, String filePath) {
return opencv_imgcodecs.imwrite(filePath, src);
}
/**
* 作用翻转图像像素
* 确保白底黑字或者黑底白字
*
* @param src
* @param b true表示白底黑字 false相反
* @return
*/
public static Mat turnPixel(Mat src, boolean b) {
if (src != null) {
int width = GeneralUtils.getImgWidth(src);
int height = GeneralUtils.getImgHeight(src);
int value;
int black_num = 0;
int white_num = 0;
int i, j;
for (i = 0; i < width; i++) {
for (j = 0; j < height; j++) {
value = GeneralUtils.getPixel(src, j, i);
if (value == GeneralUtils.getWHITE()) {
white_num++;
} else if (value == GeneralUtils.getBLACK()) {
black_num++;
}
}
}
if (b && black_num > white_num) {
// 反转
src = turnPixel(src);
} else if (!b && white_num > black_num) {
// 反转
src = turnPixel(src);
}
}
return src;
}
/**
* 作用翻转图像像素
*
* @param src Mat矩阵图像
* @return
*/
public static Mat turnPixel(Mat src) {
if (src.channels() != 1) {
throw new RuntimeException("不是单通道图,需要先灰度化");
}
int j, i, value;
int width = getImgWidth(src), height = getImgHeight(src);
for (j = 0; j < height; j++) {
for (i = 0; i < width; i++) {
value = getPixel(src, j, i);
if (value == 0) {
setPixel(src, j, i, WHITE);
} else {
setPixel(src, j, i, BLACK);
}
}
}
return src;
}
/** 图像腐蚀/膨胀处理 腐蚀和膨胀对处理没有噪声的图像很有利,慎用 */
public static Mat erodeDilateImg(Mat src) {
Mat outImage = new Mat();
// size 越小腐蚀的单位越小图片越接近原图
Mat structImage =
opencv_imgproc.getStructuringElement(opencv_imgproc.MORPH_RECT, new Size(2, 2));
/**
* 图像腐蚀 腐蚀说明 图像的一部分区域与指定的核进行卷积 求核的最``值并赋值给指定区域 腐蚀可以理解为图像中`高亮区域`'领域缩小'
* 意思是高亮部分会被不是高亮部分的像素侵蚀掉使高亮部分越来越少
*/
opencv_imgproc.erode(src, outImage, structImage);
// opencv_imgproc.erode(src, outImage, structImage, new Point(-1, -1), 2);
src = outImage;
/**
* 膨胀 膨胀说明 图像的一部分区域与指定的核进行卷积 求核的最``值并赋值给指定区域 膨胀可以理解为图像中`高亮区域`'领域扩大'
* 意思是高亮部分会侵蚀不是高亮的部分使高亮部分越来越多
*/
opencv_imgproc.dilate(src, outImage, structImage);
// opencv_imgproc.dilate(src, outImage, structImage, new Point(-1, -1), 2);
src = outImage;
return src;
}
/**
* canny算法边缘检测
*
* @param src
* @return
*/
public static Mat canny(Mat src) {
Mat mat = src.clone();
opencv_imgproc.Canny(src, mat, 60, 200);
return mat;
}
public static int getBLACK() {
return BLACK;
}
public static int getWHITE() {
return WHITE;
}
public static Size getDsize() {
return dsize;
}
}

View File

@ -0,0 +1,266 @@
package me.aias.util;
import org.bytedeco.javacpp.indexer.UByteRawIndexer;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.Mat;
import java.util.List;
import java.util.Random;
/** 对图像灰度化处理的工具类 默认有效数据的灰度值小于底色,即有效数据更清晰 */
public class GrayUtils {
/**
* 作用灰度化
*
* @param src
* @return
*/
public static Mat grayNative(Mat src) {
Mat gray = src.clone();
if (src.channels() == 3) {
// 进行灰度化
opencv_imgproc.cvtColor(src, gray, opencv_imgproc.COLOR_BGR2GRAY);
src = gray;
}
return src;
}
/**
* 均值灰度化减噪 细粒度灰度化只降低噪声不对有效数据做任何的加强的处理 根据灰度化后的图像每一列的像素值的平均值(默认)或者其他表达式值作为阀值把大于阀值的像素都改为255
* 可以在一定程度上降低噪声而不对有效数据造成任何影响
*
* @param src
* @return
*/
public static Mat grayColByMidle(Mat src) {
if (src.channels() != 1) {
src = grayNative(src);
}
List<List<Double>> data = MathUtils.MatPixelToList(src);
return grayColByMidle(src, data);
}
/**
* 根据灰度化后的图像每一列的像素值的平均值作为阀值把大于阀值的像素都改为255
*
* @param data List<Double>中存储图像灰度化后的每一列的像素值
* @return
*/
public static Mat grayColByMidle(Mat src, List<List<Double>> data) {
if (src.channels() != 1) {
src = grayNative(src);
}
UByteRawIndexer ldIdx = src.createIndexer();
// IntRawIndexer ldIdx = src.createIndexer();
for (int j = 0; j < data.size(); j++) {
List<Double> list = data.get(j);
int avg = (int) ((MathUtils.getSumInList(list) / list.size()) * 0.95);
// 随机的更新像素值
int count = 3 * list.size() / 4;
int time = 0;
while (count > 0) {
int index = new Random().nextInt(list.size());
if (list.get(index) >= avg) {
ldIdx.put(index, j, 255);
count--;
}
if (count == count) {
time++;
}
// 避免程序进入死循环
if (time == list.size() / 2) {
break;
}
}
}
ldIdx.release();
return src;
}
/**
* k值灰度化减噪 根据灰度化后的图像每一列的像素值的第k大值作为阀值把大于阀值的像素都改为255 默认选取第1/3大的值作为阀值
*
* @param src
* @return
*/
public static Mat grayColByKLargest(Mat src) {
if (src.channels() != 1) {
src = grayNative(src);
}
List<List<Double>> data = MathUtils.MatPixelToList(src);
return grayColByKLargest(src, 3, data);
}
/**
* 根据灰度化后的图像每一列的像素值的第k大值作为阀值把大于阀值的像素都改为255
*
* @param src
* @param k 分母
* @return
*/
public static Mat grayColByKLargest(Mat src, int k) {
if (k == 0) {
throw new RuntimeException("k不能为0");
}
if (src.channels() != 1) {
src = grayNative(src);
}
List<List<Double>> data = MathUtils.MatPixelToList(src);
return grayColByKLargest(src, k, data);
}
/**
* 根据灰度化后的图像每一列的像素值的第k大值作为阀值把大于阀值的像素都改为255
*
* @param src
* @param k
* @param data
* @return
*/
public static Mat grayColByKLargest(Mat src, int k, List<List<Double>> data) {
if (k == 0) {
throw new RuntimeException("k不能为0");
}
if (src.channels() != 1) {
src = grayNative(src);
}
UByteRawIndexer ldIdx = src.createIndexer();
// IntRawIndexer ldIdx = src.createIndexer();
for (int j = 0; j < data.size(); j++) {
List<Double> list = data.get(j);
Object[] doubles = list.toArray();
Double[] doubles1 = new Double[doubles.length];
for (int i = 0; i < doubles.length; i++) {
doubles1[i] = (Double) doubles[i];
}
double d = MathUtils.findKthLargest(doubles1, list.size() / k);
// 随机的更新像素值
int count = 3 * doubles.length / 4;
int time = 0;
while (count > 0) {
int index = new Random().nextInt(list.size());
if (list.get(index) >= d) {
ldIdx.put(index, j, 255);
count--;
}
if (count == count) {
time++;
}
// 避免程序进入死循环
if (time == list.size() / 2) {
break;
}
}
}
ldIdx.release();
return src;
}
/**
* 作用自适应选取阀值
*
* @param src Mat矩阵图像
* @return
*/
public static int getAdapThreshold(Mat src) {
int threshold = 0, threshold_new = 127;
int nWhite_count, nBlack_count;
int nWhite_sum, nBlack_sum;
int value, i, j;
int width = GeneralUtils.getImgWidth(src), height = GeneralUtils.getImgHeight(src);
if (width == 0 || height == 0) {
System.out.println("图像加载异常");
return -1;
}
while (threshold != threshold_new) {
nWhite_sum = nBlack_sum = 0;
nWhite_count = nBlack_count = 0;
for (j = 0; j < height; j++) {
for (i = 0; i < width; i++) {
value = GeneralUtils.getPixel(src, j, i);
if (value > threshold_new) {
nWhite_count++;
nWhite_sum += value;
} else {
nBlack_count++;
nBlack_sum += value;
}
}
}
threshold = threshold_new;
if (nWhite_count == 0 || nBlack_count == 0) {
threshold_new = (nWhite_sum + nBlack_sum) / (nWhite_count + nBlack_count);
} else {
threshold_new = (nWhite_sum / nWhite_count + nBlack_sum / nBlack_count) / 2;
}
}
return threshold;
}
/**
* 局部自适应阀值灰度化降噪
*
* @param src
* @return
*/
public static Mat grayColByPartAdapThreshold(Mat src) {
if (src.channels() != 1) {
src = grayNative(src);
}
int width = GeneralUtils.getImgWidth(src);
int height = GeneralUtils.getImgHeight(src);
int value;
for (int i = 0; i < width; i++) {
Mat partMat = src.col(i);
int thresold = getAdapThreshold(partMat);
for (int j = 0; j < height; j++) {
value = GeneralUtils.getPixel(src, j, i);
if (value > thresold) {
GeneralUtils.setPixel(src, j, i, GeneralUtils.getWHITE());
}
}
}
return src;
}
/**
* 全局自适应阀值灰度化降噪
*
* @param src
* @return
*/
public static Mat grayColByAdapThreshold(Mat src) {
if (src.channels() != 1) {
src = grayNative(src);
}
int i, j;
int width = GeneralUtils.getImgWidth(src), height = GeneralUtils.getImgHeight(src);
int value;
int threshold = getAdapThreshold(src);
for (j = 0; j < height; j++) {
for (i = 0; i < width; i++) {
value = GeneralUtils.getPixel(src, j, i);
if (value > threshold) {
GeneralUtils.setPixel(src, j, i, GeneralUtils.getWHITE());
}
}
}
return src;
}
}

View File

@ -0,0 +1,89 @@
package me.aias.util;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameConverter;
import org.bytedeco.opencv.opencv_core.Mat;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
/**
* 图片类型转换
*
* @author Calvin
*/
public class ImageUtils {
/**
* BufferedImage Mat
*
* @param original
*/
public static Mat bufferedImage2Mat(BufferedImage original) {
OpenCVFrameConverter.ToMat cv = new OpenCVFrameConverter.ToMat();
return cv.convertToMat(new Java2DFrameConverter().convert(original));
}
/**
* 将mat转BufferedImage
*
* @param matrix
*/
public static BufferedImage mat2BufferedImage(Mat matrix) {
int cols = matrix.cols();
int rows = matrix.rows();
int elemSize = (int) matrix.elemSize();
byte[] data = new byte[cols * rows * elemSize];
matrix.data().get(data);
int type = 0;
switch (matrix.channels()) {
case 1:
type = BufferedImage.TYPE_BYTE_GRAY;
break;
case 3:
type = BufferedImage.TYPE_3BYTE_BGR;
byte b;
for (int i = 0; i < data.length; i = i + 3) {
b = data[i];
data[i] = data[i + 2];
data[i + 2] = b;
}
break;
default:
return null;
}
BufferedImage image = new BufferedImage(cols, rows, type);
// BufferedImage对象中最重要的两个组件为Raster和ColorModel分别用于存储图像的像素数据与颜色数据
// 表示像素矩形数组的类Raster 封装存储样本值的 DataBuffer以及描述如何在 DataBuffer 中定位给定样本值的 SampleModel
// 由于Raster对象是BufferedImage对象中的像素数据存储对象因此BufferedImage支持从Raster对象中获取任意位置xy点的像素值pxy
image.getRaster().setDataElements(0, 0, cols, rows, data);
return image;
}
/**
* 将bufferImage转Mat
*
* @param original
* @param matType
* @param msg
* @param x
* @param y
*/
public static Mat bufferedImage2Mat(
BufferedImage original, int matType, String msg, int x, int y) {
Graphics2D g = original.createGraphics();
try {
g.setComposite(AlphaComposite.Src);
g.drawImage(original, 0, 0, null);
g.drawString(msg, x, y);
} finally {
g.dispose();
}
Mat mat = new Mat(original.getHeight(), original.getWidth(), matType);
mat.data().put(((DataBufferByte) original.getRaster().getDataBuffer()).getData());
return mat;
}
}

View File

@ -0,0 +1,374 @@
package me.aias.util;
import org.bytedeco.javacpp.indexer.DoubleRawIndexer;
import org.bytedeco.javacpp.indexer.UByteRawIndexer;
import org.bytedeco.opencv.opencv_core.Mat;
import java.util.ArrayList;
import java.util.List;
/**
* 一些数学计算工具类
*/
public class MathUtils {
/**
* 把opencv的灰度图Mat转化为List<List<Double>> , 即数组对象
* List<Double>是每一列的灰度值
* @param gray
* @return
*/
public static List<List<Double>> MatPixelToList(Mat gray){
if(gray == null){
throw new RuntimeException("不能传入空对象");
}
return MatPixelToList(gray , true);
}
/**
* 把opencv的灰度图Mat转化为List<List<Double>> , 即数组对象
* @param gray
* @param b true 表示List<Double>是每一列的灰度值否则List<Double>是每一行的灰度值
* @return
*/
public static List<List<Double>> MatPixelToList(Mat gray , boolean b){
if(gray == null){
throw new RuntimeException("不能传入空对象");
}
List<List<Double>> result = new ArrayList<>();
int x , y;
int i , j;
double value;
if(b){
//List<Double>是每一列的灰度值
x = gray.cols();
y = gray.rows();
}else{
//List<Double>是每一行的灰度值
x = gray.rows();
y = gray.cols();
}
UByteRawIndexer ldIdx = gray.createIndexer();
for(i = 0 ; i < x ; i++){
List<Double> oneLine = new ArrayList<>();
for(j = 0 ; j < y ; j++){
if(b){
value = ldIdx.get(j, i);
}else{
value = ldIdx.get(i , j);
}
oneLine.add(value);
}
result.add(oneLine);
}
ldIdx.release();
return result;
}
/**
* 返回Mat每一列的平均值
* @param grayMat
* @return
*/
public static List<Double> avgColMat(Mat grayMat){
List<List<Double>> data = MatPixelToList(grayMat);
List<Double> result = new ArrayList<>();
for(List<Double> col : data) {
double sum = getSumInList(col);
result.add(sum / col.size());
}
return result;
}
/**
* 返回Mat每一行的平均值
* @param grayMat
* @return
*/
public static List<Double> avgRowMat(Mat grayMat){
List<List<Double>> data = MatPixelToList(grayMat , false);
List<Double> result = new ArrayList<>();
for(List<Double> row : data) {
double sum = getSumInList(row);
result.add(sum / row.size());
}
return result;
}
/**
* 返回list集合中最大的那个数
* @param list
* @return
*/
public static double getMaxInList(List<Double> list){
if(list == null){
throw new RuntimeException("不能传入空对象");
}
double max = list.get(0);
for(double d : list){
if(d > max){
max = d;
}
}
return max;
}
/**
* 返回list集合中最大的那个数
* @param list
* @return
*/
public static double getMinInList(List<Double> list){
if(list == null){
throw new RuntimeException("不能传入空对象");
}
double min = list.get(0);
for(double d : list){
if(d < min){
min = d;
}
}
return min;
}
/**
* 返回list集合中总和
* @param list
* @return
*/
public static double getSumInList(List<Double> list){
if(list == null){
throw new RuntimeException("不能传入空对象");
}
double sum = 0;
for(double d : list){
sum += d;
}
return sum;
}
/**
* 寻找第k大的元素快速排序实现
* @param nums
* @param k
* @return
*/
public static double findKthLargest(List<Double> nums , int k){
int len = nums.size();
Double[] doubles1 = new Double[len];
for(int i = 0 ; i < len ; i++){
doubles1[i] = (Double)nums.get(i);
}
return findKthLargest(doubles1 , k);
}
/**
* 寻找第k大的元素快速排序实现
* @param nums
* @param k
* @return
*/
public static double findKthLargest(Double[] nums, int k) {
if (k < 1 || nums == null || k > nums.length) {
return -1;
}
return getKth(nums.length - k + 1, nums, 0, nums.length - 1);
}
public static double getKth(int k, Double[] nums, int start, int end) {
double pivot = nums[end];
int left = start;
int right = end;
while (true) {
while (nums[left] < pivot && left < right) {
left++;
}
while (nums[right] >= pivot && right > left) {
right--;
}
if (left == right) {
break;
}
swap(left, right , nums);
}
swap(left, end , nums);
if (k == left + 1) { return pivot; }
else if (k < left + 1) { return getKth(k, nums, start, left - 1); }
else { return getKth(k, nums, left + 1, end); }
}
/**
* 交换数组中l1和l2的数据
* @param l1
* @param l2
* @param arr
* @return
*/
private static void swap(int l1 , int l2 , Double[] arr){
double temp = arr[l1];
arr[l1] = arr[l2];
arr[l2] = temp;
}
/**
* 计算指定范围的List的和
* @param data
* @param start
* @param end
* @return
*/
public static int sumList(List<Integer> data, int start , int end){
if(start < 0 || start >= data.size() || end < start || end > data.size()){
throw new RuntimeException("参数不合法");
}
int sum = 0;
for(int i = start ; i < end ; i++){
sum += data.get(i);
}
return sum;
}
/**
* 计算指定范围List的最大值
* @param data
* @param start
* @param end
* @return
*/
public static int maxList(List<Integer> data, int start , int end){
if(start < 0 || start >= data.size() || end < start || end > data.size()){
throw new RuntimeException("参数不合法");
}
int max = data.get(start);
for(int i = start + 1; i < end ; i++){
int value = data.get(i);
if(max < value){
max = value;
}
}
return max;
}
/**
* 计算指定范围List的最小值
* @param data
* @param start
* @param end
* @return
*/
public static int minList(List<Integer> data, int start , int end){
if(start < 0 || start >= data.size() || end < start || end > data.size()){
throw new RuntimeException("参数不合法");
}
int min = data.get(start);
for(int i = start + 1; i < end ; i++){
int value = data.get(i);
if(min > value){
min = value;
}
}
return min;
}
//TODO
/**
* 返回切割片段中最小的片段的起始下标
* @param cutPoint 图像上的切割点
* @param width 图像宽度
* @return
*/
public static int minChoicedPart(List<Integer> cutPoint , int width){
int preValue = cutPoint.get(0);
int curValue = -1;
int minPart = Integer.MAX_VALUE;
int preIndex = -1;
int partWidth = -1;
for(int i = 1 ; i <= cutPoint.size() ; i++){
if(i == cutPoint.size()){
curValue = width;
}else{
curValue = cutPoint.get(i);
}
partWidth = curValue - preValue;
preValue = curValue;
if(partWidth < minPart){
minPart = partWidth;
preIndex = i - 1;
}
}
return preIndex;
}
/**
* 返回切割片段中最大的片段的起始下标
* @param cutPoint 图像上的切割点
* @param width 图像的宽度
* @return
*/
public static int maxChoicedPart(List<Integer> cutPoint , int width){
int preValue = cutPoint.get(0);
int curValue = -1;
int maxPart = Integer.MIN_VALUE;
int preIndex = -1;
int partWidth = -1;
for(int i = 1 ; i <= cutPoint.size() ; i++){
if(i == cutPoint.size()){
curValue = width;
}else{
curValue = cutPoint.get(i);
}
partWidth = curValue - preValue;
preValue = curValue;
if(partWidth > maxPart){
maxPart = partWidth;
preIndex = i - 1;
}
}
return preIndex;
}
/**
* 计算指定范围的List中大于avg的值的个数
* @param data
* @param start
* @param end
* @param avg
* @return
*/
public static int countLargeThanAvgInList(List<Integer> data, int start , int end , int avg){
if(start < 0 || start >= data.size() || end < start || end > data.size()){
throw new RuntimeException("参数不合法");
}
int count = 0;
for(int i = start ; i < end ; i++){
if(data.get(i) > avg){
count++;
}
}
return count;
}
}

View File

@ -0,0 +1,251 @@
package me.aias.util;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.Point;
import org.bytedeco.opencv.opencv_core.Scalar;
/**
* 降噪工具类
* Noise reduction utility class
*/
public class NoiseUtils {
private static final int WHITE = 255;
/**
* 作用给单通道的图像边缘预处理降噪(默认白底黑字)
* Function: Preprocess the edges of a single-channel image and reduce noise (default white background and black text)
*
* @param src Mat矩阵对象 - Mat matrix object
* @return
*/
public static Mat strokeWhite(Mat src) {
if (src.channels() != 1) {
throw new RuntimeException("不是单通道图,需要先灰度化 - It is not a single-channel image and needs to be grayscale first");
}
int i, width = GeneralUtils.getImgWidth(src), height = GeneralUtils.getImgHeight(src);
for (i = 0; i < width; i++) {
GeneralUtils.setPixel(src, i, 0, WHITE);
GeneralUtils.setPixel(src, i, height - 1, WHITE);
}
for (i = 0; i < height; i++) {
GeneralUtils.setPixel(src, 0, i, WHITE);
GeneralUtils.setPixel(src, width - 1, i, WHITE);
}
return src;
}
/**
* 8邻域降噪又有点像9宫格降噪;即如果9宫格中心被异色包围则同化 作用降噪(默认白底黑字)
* 8-neighborhood noise reduction, similar to 9-grid noise reduction; that is, if the center of the 9-grid is surrounded by different colors, it is homogenized. Function: Noise reduction (default white background and black text)
*
* @param src Mat矩阵对象 - Mat matrix object
* @param pNum 阀值 默认取1即可 - Threshold, the default value is 1
* @return
*/
public static Mat navieRemoveNoise(Mat src, int pNum) {
int i, j, m, n, nValue, nCount;
int width = GeneralUtils.getImgWidth(src), height = GeneralUtils.getImgHeight(src);
// 如果一个点的周围都是白色的自己确实黑色的同化
// If the surroundings of a point are all white and it is indeed black, homogenize
for (j = 1; j < height - 1; j++) {
for (i = 1; i < width - 1; i++) {
nValue = GeneralUtils.getPixel(src, j, i);
if (nValue == 0) {
nCount = 0;
// 比较(j , i)周围的9宫格如果周围都是白色同化
// Compare the 9-grid around (j, i), and homogenize if the surrounding is white
for (m = j - 1; m <= j + 1; m++) {
for (n = i - 1; n <= i + 1; n++) {
if (GeneralUtils.getPixel(src, m, n) == 0) {
nCount++;
}
}
}
if (nCount <= pNum) {
// 周围黑色点的个数小于阀值pNum,把自己设置成白色
// If the number of black points around is less than the threshold pNum, set it to white
GeneralUtils.setPixel(src, j, i, GeneralUtils.getWHITE());
}
} else {
nCount = 0;
// 比较(j , i)周围的9宫格如果周围都是黑色同化
// Compare the 9-grid around (j, i), and homogenize if the surrounding is black
for (m = j - 1; m <= j + 1; m++) {
for (n = i - 1; n <= i + 1; n++) {
if (GeneralUtils.getPixel(src, m, n) == 0) {
nCount++;
}
}
}
if (nCount >= 8 - pNum) {
// 周围黑色点的个数大于等于(8 - pNum),把自己设置成黑色
// If the number of black points around is greater than or equal to (8 - pNum), set it to black
GeneralUtils.setPixel(src, j, i, GeneralUtils.getBLACK());
}
}
}
}
return src;
}
/**
* 连通域降噪 作用降噪(默认白底黑字)
* Connected domain noise reduction Function: Noise reduction (default white background and black text)
*
* @param src Mat矩阵对象 - Mat matrix object
* @param pArea 阀值 默认取1即可 - Threshold, the default value is 1
* @return
*/
public static Mat connectedRemoveNoise(Mat src, double pArea) {
int i, j, color = 1;
int width = GeneralUtils.getImgWidth(src), height = GeneralUtils.getImgHeight(src);
Result result = floodFill(new Result(src), pArea);
src = result.mat;
// 二值化 - Binaryzation
for (i = 0; i < width; i++) {
for (j = 0; j < height; j++) {
if (GeneralUtils.getPixel(src, j, i) < GeneralUtils.getWHITE()) {
GeneralUtils.setPixel(src, j, i, GeneralUtils.getBLACK());
}
}
}
if (result.status == false && result.count <= 100) {
connectedRemoveNoise(src, pArea);
}
return src;
}
/**
* 连通域填充颜色
* Flood fill color of connected domains
*
* @param result
* @return
*/
public static Result floodFill(Result result, double pArea) {
Mat src = result.mat;
if (src == null) {
return null;
}
int i, j, color = 1;
int width = GeneralUtils.getImgWidth(src), height = GeneralUtils.getImgHeight(src);
for (i = 0; i < width; i++) {
for (j = 0; j < height; j++) {
if (GeneralUtils.getPixel(src, j, i) == GeneralUtils.getBLACK()) {
// 用不同的颜色填充连接区域中的每个黑色点
// Fill each black point in the connected area with a different color
// floodFill就是把与点(i , j)的所有相连通的区域都涂上color颜色
// floodFill is to color all areas that are connected with point (i, j) with color
int area = opencv_imgproc.floodFill(src, new Mat(), new Point(i, j), new Scalar(color));
if (area <= pArea) {
opencv_imgproc.floodFill(src, new Mat(), new Point(i, j), new Scalar(255));
} else {
color++;
}
if (color == 255) {
result.status = false; // 连通域还没填充完 - The connected area is not completely filled
result.mat = src;
result.count = result.count + 1;
return result;
}
}
}
}
result.mat = src;
result.status = true; // 表示所有的连通域都已填充完毕 - Indicates that all connected domains have been filled
return result;
}
/**
* 连通域填充颜色
* Flood fill color of connected domains
*
* @param src
* @return
*/
public static Mat floodFill(Mat src, double pArea) {
if (src == null) {
return null;
}
int i, j, color = 1;
int width = GeneralUtils.getImgWidth(src), height = GeneralUtils.getImgHeight(src);
for (i = 0; i < width; i++) {
for (j = 0; j < height; j++) {
if (GeneralUtils.getPixel(src, j, i) == GeneralUtils.getBLACK()) {
// 用不同的颜色填充连接区域中的每个黑色点
// Fill each black point in the connected area with a different color
// floodFill就是把与点(i , j)的所有相连通的区域都涂上color颜色
// floodFill is to color all areas that are connected with point (i, j) with color
int area = opencv_imgproc.floodFill(src, new Mat(), new Point(i, j), new Scalar(color));
if (area <= pArea) {
System.out.println(color);
opencv_imgproc.floodFill(src, new Mat(), new Point(i, j), new Scalar(255));
} else {
color++;
}
System.out.println(color);
}
}
}
return src;
}
// 只填充最大的连通域
// Only fill the largest connected area
public static Mat findMaxConnected(Mat src) {
int i, j, color = 127;
int width = GeneralUtils.getImgWidth(src), height = GeneralUtils.getImgHeight(src);
int maxArea = Integer.MAX_VALUE;
int maxI = -1, maxJ = -1;
for (i = 0; i < width; i++) {
for (j = 0; j < height; j++) {
if (GeneralUtils.getPixel(src, j, i) == GeneralUtils.getBLACK()) {
// 用不同的颜色填充连接区域中的每个黑色点
// Fill each black point in the connected area with a different color
// floodFill就是把与点(i , j)的所有相连通的区域都涂上color颜色
// floodFill is to color all areas that are connected with point (i, j) with color
int area = opencv_imgproc.floodFill(src, new Mat(), new Point(i, j), new Scalar(color));
if (maxI != -1 && maxJ != -1) {
if (area > maxArea) {
maxArea = area;
opencv_imgproc.floodFill(src, new Mat(), new Point(maxI, maxJ), new Scalar(255));
maxI = i;
maxJ = j;
} else {
opencv_imgproc.floodFill(src, new Mat(), new Point(i, j), new Scalar(255));
}
} else {
maxI = i;
maxJ = j;
maxArea = area;
}
}
}
}
return src;
}
private static class Result {
Mat mat; // Mat对象 - Mat object
boolean status; // 是否填充完毕 - Whether it is filled
int count; // 记录填充的次数 - Number of fillings
int height; // 记录上一次填充的height位置 - height position of the last filling
int width; // 记录上一次填充的width位置 - width position of the last filling
public Result() {
}
public Result(Mat src) {
this.mat = src;
}
}
}

View File

@ -0,0 +1,110 @@
package me.aias.util;
import org.bytedeco.opencv.opencv_core.*;
import static org.bytedeco.opencv.global.opencv_imgproc.minAreaRect;
/**
* 矩形框工具类
* Rectangle tool class
*/
public class RectUtils {
/**
* 返回边缘检测之后的最大矩形
* Returns the maximum rectangle after edge detection
*
* @param contours
* @return
*/
public static RotatedRect getMaxRect(MatVector contours) {
// 找出匹配到的最大轮廓 - Find the largest contour
Mat maxContour = ContourUtils.getMaxContour(contours);
RotatedRect rect = minAreaRect(maxContour);
return rect;
}
/**
* 返回边缘检测之后的最大矩形
* Returns the maximum rectangle after edge detection
*
* @param cannyMat Canny之后的mat矩阵 - Canny's mat matrix
* @return
*/
public static RotatedRect getMaxRect(Mat cannyMat) {
// 找出匹配到的最大轮廓 - Find the largest contour
Mat maxContour = ContourUtils.getMaxContour(cannyMat);
RotatedRect rect = minAreaRect(maxContour);
return rect;
}
/**
* 把矫正后的图像切割出来
* Cut the corrected image
*
* @param correctMat 图像矫正后的Mat矩阵 - The corrected Mat matrix of the image
*/
public static Mat cutRect(Mat correctMat, Mat nativeCorrectMat) {
// 获取所有轮廓 - Obtain all contours
MatVector contours = ContourUtils.getContours(correctMat);
// 获取最大矩形 - Obtain the largest rectangle
RotatedRect rect = getMaxRect(contours);
Point2f rectPoint = new Point2f(4);
rect.points(rectPoint);
for (int i = 0; i < rectPoint.limit(); i++) {
System.out.println(rectPoint.position(i).x() + " , " + rectPoint.position(i).y());
}
int x = rect.boundingRect().x();
int y = rect.boundingRect().y();
int width = rect.boundingRect().width();
int height = rect.boundingRect().height();
// int x = (int) Math.abs(rectPoint.position(2).x());
// int y = (int) Math.abs(rectPoint.position(2).y() < rectPoint.position(3).y() ?
// rectPoint.position(2).y() : rectPoint.position(3).y());
// int width = (int) Math.abs(rectPoint.position(3).x() - rectPoint.position(2).x());
// int height = (int) Math.abs(rectPoint.position(1).y() - rectPoint.position(2).y());
System.out.println("startLeft = " + x);
System.out.println("startUp = " + y);
System.out.println("width = " + width);
System.out.println("height = " + height);
Mat temp = new Mat(nativeCorrectMat, new Rect(x, y, width, height));
Mat t = new Mat();
temp.copyTo(t);
return t;
}
/**
* 把矫正后的图像切割出来--辅助函数(修复)
* Cut the corrected image -- auxiliary function (repair)
*
* @param rectPoint 矩形的四个点 - The four points of the rectangle
* @return int[startLeft , startUp , width , height]
*/
public static int[] cutRectHelp(Point2f rectPoint) {
double minX = rectPoint.position(0).x();
double maxX = rectPoint.position(0).x();
double minY = rectPoint.position(0).y();
double maxY = rectPoint.position(0).y();
for (int i = 1; i < 4; i++) {
minX = rectPoint.position(i).x() < minX ? rectPoint.position(i).x() : minX;
maxX = rectPoint.position(i).x() > maxX ? rectPoint.position(i).x() : maxX;
minY = rectPoint.position(i).y() < minY ? rectPoint.position(i).y() : minY;
maxY = rectPoint.position(i).y() > maxY ? rectPoint.position(i).y() : maxY;
}
int[] roi = {
(int) Math.abs(minX),
(int) Math.abs(minY),
(int) Math.abs(maxX - minX),
(int) Math.abs(maxY - minY)
};
return roi;
}
}

View File

@ -0,0 +1,200 @@
package me.aias.util;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.*;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.Rect;
import org.opencv.imgproc.Imgproc;
import java.util.List;
/**
* 归一化工具类
* Normalization utility class
*/
public class ResizeUtils {
// 设置归一化图像的固定大小
// Set the fixed size of the normalized image
private static final Size defaultDsize = new Size(32, 32);
/**
* 把图片归一化到相同的大小
* Normalize the image to the same size
* @param src Mat矩阵对象 - Mat matrix object
* @return
*/
public static Mat resize(Mat src) {
return resize(src, defaultDsize);
}
/**
* 把图片归一化到相同的大小
* Normalize the image to the same size
*
* @param src Mat矩阵对象 - Mat matrix object
* @return
*/
public static Mat resize(Mat src, Size dsize) {
src = trimImg(src);
Mat dst = new Mat();
// 区域插值(INTER_AREA):图像放大时类似于线性插值图像缩小时可以避免波纹出现
// Area interpolation (INTER_AREA): similar to linear interpolation when the image is enlarged, and can avoid ripples when the image is reduced.
opencv_imgproc.resize(src, dst, dsize, 0, 0, Imgproc.INTER_AREA);
return dst;
}
/**
* 去除图像中的空白
* Remove the blank space in the image
*
* @param src
* @return
*/
public static Mat trimImg(Mat src) {
List<Double> colList = MathUtils.avgColMat(src); // 每一列的平均值 - Average value of each column
List<Double> rowList = MathUtils.avgRowMat(src); // 每一行的平均值 - Average value of each row
double colAvg = MathUtils.getSumInList(colList) / colList.size();
double rowAvg = MathUtils.getSumInList(rowList) / rowList.size();
int blankCol1 = -1; // 空白列的关键分割点() - Key segmentation point (left) of blank column
int blankCol2 = -1; // 空白列的关键分割点() - Key segmentation point (right) of blank column
int blankRow1 = -1; // 空白行的关键分割点() - Key segmentation point (up) of blank row
int blankRow2 = -1; // 空白行的关键分割点() - Key segmentation point (down) of blank row
int preValue = -1;
int curValue = -1;
int count = 0;
boolean b = true;
for (int i = 0; i < colList.size(); i++) {
if (b == false) {
break;
}
if (colList.get(i) > colAvg) {
// 求空白列的关键分割点() - Calculate the key segmentation point (left) of the blank column
curValue = i;
if (preValue != -1) {
if (curValue - preValue == 1) {
// 连续 - Continuous
count++;
} else {
// 不连续 - Not continuous
if (count > 10) {
blankCol1 = 2 * i / 3;
b = false;
}
}
}
preValue = i;
}
}
preValue = -1;
curValue = -1;
count = 0;
b = true;
for (int i = colList.size() - 1; i >= 0; i--) {
if (b == false) {
break;
}
if (colList.get(i) > colAvg) {
// 求空白列的关键分割点()
// Calculate the key segmentation point (right) of the blank column
curValue = i;
if (preValue != -1) {
if (curValue - preValue == -1) {
// 连续 - Continuous
count++;
} else {
// 不连续 - Not continuous
if (count > 10) {
blankCol2 = i + (colList.size() - i) / 3;
b = false;
}
}
}
preValue = i;
}
}
preValue = -1;
curValue = -1;
count = 0;
b = true;
for (int i = 0; i < rowList.size(); i++) {
if (rowList.get(i) > rowAvg) {
// 空白行的关键分割点()
// Key segmentation point (up) of blank row
if (b == false) {
break;
}
if (rowList.get(i) > rowAvg) {
curValue = i;
if (preValue != -1) {
if (curValue - preValue == 1) {
// 连续 - Continuous
count++;
} else {
// 不连续 - Not continuous
if (count > 10) {
blankRow1 = i / 2;
b = false;
}
}
}
preValue = i;
}
}
}
preValue = -1;
curValue = -1;
count = 0;
b = true;
for (int i = rowList.size() - 1; i >= 0; i--) {
if (rowList.get(i) > rowAvg) {
// 空白行的关键分割点()
// Key segmentation point (down) of blank row
if (b == false) {
break;
}
if (rowList.get(i) > rowAvg) {
curValue = i;
if (preValue != -1) {
if (curValue - preValue == -1) {
// 连续 - Continuous
count++;
} else {
// 不连续 - Not continuous
if (count > 10) {
blankRow2 = i + 2 * (rowList.size() - i) / 3;
b = false;
}
}
}
preValue = i;
}
}
}
// int blankCol1 = -1; 空白列的关键分割点() - Key splitting point (left) of the blank column
// int blankCol2 = -1; 空白列的关键分割点() - Key splitting point (right) of the blank column
// int blankRow1 = -1; 空白行的关键分割点() - Key splitting point (top) of the blank row
// int blankRow2 = -1; 空白行的关键分割点() - Key splitting point (bottom) of the blank row
// Select the area of interest
blankCol1 = blankCol1 == -1 ? 0 : blankCol1;
blankCol2 = blankCol2 == -1 ? colList.size() : blankCol2;
blankRow1 = blankRow1 == -1 ? 0 : blankRow1;
blankRow2 = blankRow2 == -1 ? rowList.size() : blankRow2;
Mat temp =
new Mat(
src, new Rect(blankCol1, blankRow1, blankCol2 - blankCol1, blankRow2 - blankRow1));
Mat t = new Mat();
temp.copyTo(t);
return t;
}
}

View File

@ -0,0 +1,37 @@
package me.aias.util;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.Point2f;
import org.bytedeco.opencv.opencv_core.RotatedRect;
import org.bytedeco.opencv.opencv_core.Scalar;
import static org.bytedeco.opencv.global.opencv_imgproc.getRotationMatrix2D;
import static org.bytedeco.opencv.global.opencv_imgproc.warpAffine;
/**
* 旋转矩形工具类
* Rotation Rectangle Tool Class
*/
public class RotationUtils {
/**
* 旋转矩形 返回旋转后的Mat
* Rotate rectangle and return rotated Mat
* @param cannyMat mat矩阵 - matrix
* @param rect 矩形 - rectangle
* @return
*/
public static Mat rotation(Mat cannyMat, RotatedRect rect) {
double angle = rect.angle();
Point2f center = rect.center();
Mat correctImg = new Mat(cannyMat.size(), cannyMat.type());
cannyMat.copyTo(correctImg);
// 得到旋转矩阵算子 - Get the rotation matrix operator
Mat matrix = getRotationMatrix2D(center, angle, 0.8);
warpAffine(correctImg, correctImg, matrix, correctImg.size(), 1, 0, new Scalar(0, 0, 0, 0));
return correctImg;
}
}

View File

@ -0,0 +1,470 @@
package me.aias.util;
import org.bytedeco.opencv.opencv_core.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 图像处理工具类1.0.0(只针对几乎没有畸变的图像) 灰度话二值化降噪切割归一化
* Image processing utility class 1.0.0 (only for images with almost no distortion) Grayscale, binarization, denoising, cutting, normalization
*
* @author admin
*/
public class TableUtils {
private static final int BLACK = 0;
private TableUtils() {};
/**
* 统计图像每行/每列黑色像素点的个数
* Count the number of black pixels per row/column in the image
* (n1,n2)=>(height,width),
* b=true; 统计每行 - count per row
* (n1,n2)=>(width,height),
* b=false; 统计每列 - count per column
*
* @param src Mat矩阵对象 - Mat object
* @param n1
* @param n2
* @param b true表示统计每行;false表示统计每列 - true to count each row; false to count each column
* @return
*/
public static int[] countPixel(Mat src, int n1, int n2, boolean b) {
int[] xNum = new int[n1];
for (int i = 0; i < n1; i++) {
for (int j = 0; j < n2; j++) {
if (b) {
if (GeneralUtils.getPixel(src, i, j) == BLACK) {
xNum[i]++;
}
} else {
if (GeneralUtils.getPixel(src, j, i) == BLACK) {
xNum[i]++;
}
}
}
}
return xNum;
}
/**
* 压缩像素值数量即统计zipLine行像素值的数量为一行
* Compress the number of pixel values; count the number of pixel values of zipLine rows as one row
* @param num
* @param zipLine
*/
public static int[] zipLinePixel(int[] num, int zipLine) {
int len = num.length / zipLine;
int[] result = new int[len];
int sum;
for (int i = 0, j = 0; i < num.length && i + zipLine < num.length; i += zipLine) {
sum = 0;
for (int k = 0; k < zipLine; k++) {
sum += num[i + k];
}
result[j++] = sum;
}
return result;
}
/**
* 水平投影法切割适用于类似表格的图像(默认白底黑字) 改进
* Horizontal projection cutting, suitable for image like tables (default white background and black text) improvement
* @param src Mat矩阵对象 - Mat object
* @return
*/
public static List<Mat> cutImgX(Mat src) {
int i, j;
int width = GeneralUtils.getImgWidth(src), height = GeneralUtils.getImgHeight(src);
int[] xNum, cNum;
int average = 0; // 记录黑色像素和的平均值 - Record the average value of black pixels
int zipLine = 3;
// 压缩像素值数量即统计三行像素值的数量为一行
// Compress the number of pixel values;
// 统计出每行黑色像素点的个数
// count three rows of pixel values as one row
xNum = zipLinePixel(countPixel(src, height, width, true), zipLine);
// 排序 - Sort
cNum = Arrays.copyOf(xNum, xNum.length);
Arrays.sort(cNum);
for (i = 31 * cNum.length / 32; i < cNum.length; i++) {
average += cNum[i];
}
average /= (height / 32);
// 把需要切割的y轴点存到cutY中
// Store the y-axis points that need to be cut in cutY
List<Integer> cutY = new ArrayList<Integer>();
for (i = 0; i < xNum.length; i++) {
if (xNum[i] > average) {
cutY.add(i * zipLine + 1);
}
}
// 优化cutY,把距离相差在30以内的都清除掉
// Optimize cutY, remove all those whose distance is within 30
if (cutY.size() != 0) {
int temp = cutY.get(cutY.size() - 1);
// 因为线条有粗细优化cutY
// Optimize cutY because of the thickness of the line
for (i = cutY.size() - 2; i >= 0; i--) {
int k = temp - cutY.get(i);
if (k <= 30) {
cutY.remove(i + 1);
} else {
temp = cutY.get(i);
}
}
temp = cutY.get(cutY.size() - 1);
// 因为线条有粗细优化cutY
// Optimize cutY because of the thickness of the line
for (i = cutY.size() - 2; i >= 0; i--) {
int k = temp - cutY.get(i);
if (k <= 30) {
cutY.remove(i + 1);
} else {
temp = cutY.get(i);
}
}
}
// 把切割的图片保存到YMat中
// Store the cut images in YMat
List<Mat> YMat = new ArrayList<Mat>();
for (i = 1; i < cutY.size(); i++) {
// // 设置感兴趣区域 - Set the region of interest
int startY = cutY.get(i - 1);
int h = cutY.get(i) - startY;
Mat temp = new Mat(src, new Rect(0, startY, width, h));
Mat t = new Mat();
temp.copyTo(t);
YMat.add(t);
}
return YMat;
}
/**
* 垂直投影法切割适用于类似表格的图像(默认白底黑字) 改进
* Vertical projection cutting, suitable for image like tables (default white background and black text) improvement
*
* @param src Mat矩阵对象 - Mat object
* @return
*/
public static List<Mat> cutImgY(Mat src) {
int i, j;
int width = GeneralUtils.getImgWidth(src), height = GeneralUtils.getImgHeight(src);
int[] yNum, cNum;
int average = 0; // 记录黑色像素和的平均值 - Record the average value of black pixels
int zipLine = 2;
// 压缩像素值数量即统计三行像素值的数量为一行
// Compress the number of pixel values
// 统计出每列黑色像素点的个数
// count three rows of pixel values as one row
yNum = zipLinePixel(countPixel(src, width, height, false), zipLine);
// 经过测试这样得到的平均值最优平均值的选取很重要
// After testing, this is the optimal way to get the average value. The selection of the average value is very important.
cNum = Arrays.copyOf(yNum, yNum.length);
Arrays.sort(cNum);
for (i = 31 * cNum.length / 32; i < cNum.length; i++) {
average += cNum[i];
}
average /= (cNum.length / 32);
// 把需要切割的x轴的点存到cutX中
// Store the x-axis points that need to be cut in cutX
List<Integer> cutX = new ArrayList<Integer>();
for (i = 0; i < yNum.length; i++) {
if (yNum[i] >= average) {
cutX.add(i * zipLine + 2);
}
}
// 优化cutX - Optimize cutX
if (cutX.size() != 0) {
int temp = cutX.get(cutX.size() - 1);
// 因为线条有粗细优化cutX
// Optimize cutX because of the thickness of the line
for (i = cutX.size() - 2; i >= 0; i--) {
int k = temp - cutX.get(i);
if (k <= 100) {
cutX.remove(i);
} else {
temp = cutX.get(i);
}
}
temp = cutX.get(cutX.size() - 1);
// 因为线条有粗细优化cutX
// Optimize cutX because of the thickness of the line
for (i = cutX.size() - 2; i >= 0; i--) {
int k = temp - cutX.get(i);
if (k <= 100) {
cutX.remove(i);
} else {
temp = cutX.get(i);
}
}
}
// 把切割的图片都保存到XMat中
// Store the cut images in XMat
List<Mat> XMat = new ArrayList<Mat>();
for (i = 1; i < cutX.size(); i++) {
// 设置感兴趣的区域
// Set the region of interest
int startX = cutX.get(i - 1);
int w = cutX.get(i) - startX;
Mat temp = new Mat(src, new Rect(startX, 0, w, height));
Mat t = new Mat();
temp.copyTo(t);
XMat.add(t);
}
return XMat;
}
/**
* 切割 因为是表格图像采用新的切割思路中和水平切割和垂直切割一次性切割出所有的小格子
* Cutting. Because it is a table image, a new cutting idea is used, which cuts out all small cells in one step by combining horizontal and vertical cutting.
*
* @param src
* @return
*/
public static List<Mat> cut(Mat src) {
if (src.channels() == 3) {
// TODO
}
int i, j, k;
int width = GeneralUtils.getImgWidth(src), height = GeneralUtils.getImgHeight(src);
int[] xNum = new int[height], copy_xNum;
int x_average = 0;
int value = -1;
// 统计每行每列的黑色像素值
// Count the number of black pixels per row/column
for (i = 0; i < width; i++) {
for (j = 0; j < height; j++) {
value = GeneralUtils.getPixel(src, j, i);
if (value == BLACK) {
xNum[j]++;
}
}
}
int zipXLine = 3;
xNum = zipLinePixel(xNum, zipXLine);
// 排序 ............求水平切割点
// Sort ............ to get horizontal cutting points
copy_xNum = Arrays.copyOf(xNum, xNum.length);
Arrays.sort(copy_xNum);
for (i = 31 * copy_xNum.length / 32; i < copy_xNum.length; i++) {
x_average += copy_xNum[i];
}
x_average /= (height / 32);
// 把需要切割的y轴点存到cutY中
// Store the y-axis points that need to be cut in cutY
List<Integer> cutY = new ArrayList<Integer>();
for (i = 0; i < xNum.length; i++) {
if (xNum[i] > x_average) {
cutY.add(i * zipXLine + zipXLine / 2);
}
}
// 优化cutY,把距离相差在30以内的都清除掉
// Optimize cutY, remove all those whose distance is within 30
if (cutY.size() != 0) {
int temp = cutY.get(cutY.size() - 1);
// 因为线条有粗细优化cutY
// Optimize cutY because of the thickness of the line
for (i = cutY.size() - 2; i >= 0; i--) {
k = temp - cutY.get(i);
if (k <= 10 * zipXLine) {
cutY.remove(i + 1);
} else {
temp = cutY.get(i);
}
}
temp = cutY.get(cutY.size() - 1);
// 因为线条有粗细优化cutY
// Optimize cutY because of the thickness of the line
for (i = cutY.size() - 2; i >= 0; i--) {
k = temp - cutY.get(i);
if (k <= 10 * zipXLine) {
cutY.remove(i + 1);
} else {
temp = cutY.get(i);
}
}
}
// 把需要切割的x轴的点存到cutX中
// Store the x-axis points that need to be cut in cutX
// 新思路因为不是很畸变的图像y轴的割点还是比较好确定的 随机的挑选一个y轴割点用一个滑动窗口去遍历选中点所在直线确定x轴割点
// New idea, because it is not a very distorted image, the y-axis cutting point is still relatively easy to determine.
// Randomly select a y-axis cutting point, use a sliding window to traverse the straight line where the selected point is located, and determine the x-axis cutting point.
List<Integer> cutX = new ArrayList<Integer>();
int choiceY = cutY.size() > 1 ? cutY.get(1) : (cutY.size() > 0 ? cutY.get(0) : -1);
if (choiceY == -1) {
throw new RuntimeException("切割失败,没有找到水平切割点 - Cutting failed, no horizontal cutting point found");
}
int winH = 5;
List<Integer> LH1 = new ArrayList<Integer>();
List<Integer> LH2 = new ArrayList<Integer>();
if (choiceY - winH >= 0 && choiceY + winH <= height) {
// 上下 - Up and down
for (i = 0; i < width; i++) {
value = GeneralUtils.getPixel(src, choiceY - winH, i);
if (value == BLACK) {
LH1.add(i);
}
value = GeneralUtils.getPixel(src, choiceY + winH, i);
if (value == BLACK) {
LH2.add(i);
}
}
} else if (choiceY + winH <= height && choiceY + 2 * winH <= height) {
// - Down
for (i = 0; i < width; i++) {
value = GeneralUtils.getPixel(src, choiceY + 2 * winH, i);
if (value == BLACK) {
LH1.add(i);
}
value = GeneralUtils.getPixel(src, choiceY + winH, i);
if (value == BLACK) {
LH2.add(i);
}
}
} else if (choiceY - winH >= 0 && choiceY - 2 * winH >= 0) {
// - Up
for (i = 0; i < width; i++) {
value = GeneralUtils.getPixel(src, choiceY - winH, i);
if (value == BLACK) {
LH1.add(i);
}
value = GeneralUtils.getPixel(src, choiceY - 2 * winH, i);
if (value == BLACK) {
LH2.add(i);
}
}
} else {
throw new RuntimeException("切割失败,图像异常 - Cutting failed, image exception");
}
// 优化LH1LH2,把距离相差在30以内的都清除掉
// Optimize LH1 and LH2, removing all distances within 30
if (LH1.size() != 0) {
int temp = LH1.get(LH1.size() - 1);
// 因为线条有粗细优化cutY
// optimize cutY because of line thickness
for (i = LH1.size() - 2; i >= 0; i--) {
k = temp - LH1.get(i);
if (k <= 50) {
LH1.remove(i + 1);
} else {
temp = LH1.get(i);
}
}
temp = LH1.get(LH1.size() - 1);
// 因为线条有粗细优化cutY
// optimize cutY because of line thickness
for (i = LH1.size() - 2; i >= 0; i--) {
k = temp - LH1.get(i);
if (k <= 50) {
LH1.remove(i + 1);
} else {
temp = LH1.get(i);
}
}
}
if (LH2.size() != 0) {
int temp = LH2.get(LH2.size() - 1);
// 因为线条有粗细优化cutY
// optimize cutY because of line thickness
for (i = LH2.size() - 2; i >= 0; i--) {
k = temp - LH2.get(i);
if (k <= 50) {
LH2.remove(i + 1);
} else {
temp = LH2.get(i);
}
}
temp = LH2.get(LH2.size() - 1);
// 因为线条有粗细优化cutY
// optimize cutY because of line thickness
for (i = LH2.size() - 2; i >= 0; i--) {
k = temp - LH2.get(i);
if (k <= 50) {
LH2.remove(i + 1);
} else {
temp = LH2.get(i);
}
}
}
if (LH1.size() < LH2.size()) {
// 进一步优化LH1
// further optimize LH1
int avg = 0;
for (k = 1; k < LH1.size() - 2; k++) {
avg += LH1.get(k + 1) - LH1.get(k);
}
avg /= (LH1.size() - 2);
int temp = LH1.get(LH1.size() - 1);
for (i = LH1.size() - 2; i >= 0; i--) {
k = temp - LH1.get(i);
if (k <= avg) {
LH1.remove(i + 1);
} else {
temp = LH1.get(i);
}
}
cutX = LH1;
} else {
// 进一步优化LH2
// further optimize LH2
int avg = 0;
for (k = 1; k < LH2.size() - 2; k++) {
avg += LH2.get(k + 1) - LH2.get(k);
}
avg /= (LH2.size() - 2);
int temp = LH2.get(LH2.size() - 1);
for (i = LH2.size() - 2; i >= 0; i--) {
k = temp - LH2.get(i);
if (k <= avg) {
LH2.remove(i + 1);
} else {
temp = LH2.get(i);
}
}
cutX = LH2;
}
List<Mat> destMat = new ArrayList<Mat>();
for (i = 1; i < cutY.size(); i++) {
for (j = 1; j < cutX.size(); j++) {
// 设置感兴趣的区域
// set region of interest
int startX = cutX.get(j - 1);
int w = cutX.get(j) - startX;
int startY = cutY.get(i - 1);
int h = cutY.get(i) - startY;
Mat temp = new Mat(src, new Rect(startX + 2, startY + 2, w - 2, h - 2));
Mat t = new Mat();
temp.copyTo(t);
destMat.add(t);
}
}
return destMat;
}
}

View File

@ -0,0 +1,52 @@
package me.aias.util;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.Point2f;
import org.bytedeco.opencv.opencv_core.Scalar;
import org.opencv.imgproc.Imgproc;
/**
* 透视变换工具类
* Perspective transformation
*
*/
public class WarpPerspectiveUtils {
/**
* 透视变换
* Perspective transformation
*
* @param src
* @param srcPoints
* @param dstPoints
* @return
*/
public static Mat warpPerspective(Mat src, Mat srcPoints, Mat dstPoints) {
// srcPoints, dstPoints
// 点的顺序[左上 右上 右下 左下]
// Point order [top left, top right, bottom right, bottom left]
Mat perspectiveMmat = opencv_imgproc.getPerspectiveTransform(srcPoints, dstPoints);
Mat dst = new Mat();
opencv_imgproc.warpPerspective(
src,
dst,
perspectiveMmat,
src.size(),
Imgproc.INTER_LINEAR + Imgproc.WARP_INVERSE_MAP,
1,
new Scalar(0));
return dst;
}
public static Mat perspectiveTransform(
Mat src, Point2f srcPoints, Point2f dstPoints) {
Mat dst = src.clone();
Mat warp_mat = opencv_imgproc.getPerspectiveTransform(srcPoints.position(0), dstPoints.position(0));
opencv_imgproc.warpPerspective(src, dst, warp_mat, dst.size());
return dst;
}
}

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout
pattern="[%-5level] - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="info" additivity="false">
<AppenderRef ref="console"/>
</Root>
<Logger name="me.calvin" level="${sys:me.calvin.logging.level:-info}" additivity="false">
<AppenderRef ref="console"/>
</Logger>
</Loggers>
</Configuration>