共计 3261 个字符,预计需要花费 9 分钟才能阅读完成。
前言
最近有个我的项目须要对图片图像进行解决,应用到了开源框架 OpenCV 全称是 Open Source Computer Vision Library,是一个跨平台的计算机视觉库;而当初的我的项目都是基于 SpringBoot,须要把 OpenCv 整合进去,上面把在应用中遇到的问题进行一个汇总整顿。
下载安装
Opencv 官网提供了一个多个平台的版本包含:Windows,IOS,Android,地址如下:https://opencv.org/releases/;因为开发在 Windows 平台,公布在 Linux 平台,所以咱们这里至多须要两个版本;
windows 平台
间接能够在官网下载 opencv-3.4.10-vc14_vc15.exe 装置即可,装置完会呈现 opencv 文件夹在 buildjava 目录下有咱们须要的 opencv-3410.jar,x64/opencv_java3410.dll,x86/opencv_java3410.dll 文件;
Linux 平台
Linux 平台须要咱们手动编译,下载 opencv-3.4.10.zip,解压到 /user/local 目录下,而后编译装置,执行如下命令:
cd /usr/local/opencv-3.4.10
mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -DBUILD_TESTS=OFF ..
make -j8
sudo make install
装置完之后能够在 build/bin 目录下找到 opencv-3410.jar,在 build/lib 目录下找到 libopencv_java3410.so
整合应用
两个平台别离装置完之后,获取了对应的 dll 和 so 文件;两个平台获取到的 jar 都是一样的,轻易用哪个都能够,上面看看如何应用
内部援用形式
通过把利用 jar 与本地库文件进行分隔开,而后在我的项目中进行援用
相对路径形式
能够通过 System.loadLibrary 来指定本地库文件,然而这种形式须要在运行时指定 -Djava.library.path,具体能够提供配置类:
@Configuration
public class NativeConfig {
static {System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
}
}
运行时须要在 VM arguments 中增加 -Djava.library.path= 对应 dll 寄存的门路,不然会呈现如下谬误:
Caused by: java.lang.UnsatisfiedLinkError: no opencv_java3410 in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1860) ~[na:1.8.0_251]
at java.lang.Runtime.loadLibrary0(Runtime.java:870) ~[na:1.8.0_251]
at java.lang.System.loadLibrary(System.java:1122) ~[na:1.8.0_251]
at com.springboot.opencv.NativeConfig.<clinit>(NativeConfig.java:10) ~[classes/:na]
绝对路径形式
能够通过 System.load 来指定本地库函数的绝对路径:
@Configuration
public class NativeConfig {
static {System.load("C:\\Users\\opencv\\build\\java\\x64\\opencv_java3410.dll");
}
}
踩坑 1
在 IDE 中运行应用 Opencv 性能的时候,呈现如下谬误:
java.lang.UnsatisfiedLinkError: org.opencv.imgcodecs.Imgcodecs.imread_1(Ljava/lang/String;)J
at org.opencv.imgcodecs.Imgcodecs.imread_1(Native Method) ~[opencv-3.4.10.jar:unknown]
at org.opencv.imgcodecs.Imgcodecs.imread(Imgcodecs.java:332) ~[opencv-3.4.10.jar:unknown]
at com.springboot.opencv.OpenCVController.testOpenCV(OpenCVController.java:13) ~[classes/:na]
很显著是在应用 jar 包外面的办法时没有找到对应的本地库函数,也就是说 loadLibrary 没有胜利,然而之前其实在本地 Java 我的项目中是有进行测试的,能够通过的,猜想是不是应用了什么工具导致加载失败,最终锁定在 spring-boot-devtools 工具包,提供了动静加载等性能,间接移除此工具包,或者配置如下开关:
System.setProperty("spring.devtools.restart.enabled", "false");
外部援用形式
为了更加简略部署,能够把本地库文件和我的项目文件打成一个 jar 包,能够把本地库文件放在 resources 目录下,这样能够打成一个 jar 包,当初的次要问题就是如何加载 jar 包外面的本地库文件,通过测试发现能够读取到 resources 目录下的库文件,然而通过 system.load 并不能去加载胜利,对应的是一个相似如下的门路:
file:/C:/Users/Administrator.SKY-20170404CXG/Desktop/springboot-0.0.1-SNAPSHOT.j
ar!/BOOT-INF/classes!/opencv
最初采纳的形式是把读取的库文件,寄存到零碎的一个长期文件夹下,而后拿到库文件的绝对路径,这样就能够通过 system.load 间接去加载,具体实现代码能够参考 Github
踩坑 2
在执行 maven 编译打包的时候,发现本地库文件 (dll 或者 so 文件) 体积会变大,猜想 maven 在编译的时候对本地库文件也进行了编译,具体如何禁用指定的文件格式编译,而只须要拷贝即可:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
<!-- maven 编译上面扩大类型文件的时候间接复制原文件,而不会进行二次编码 -->
<nonFilteredFileExtensions>dll,so</nonFilteredFileExtensions>
</configuration>
</plugin>
第三方 Jar 包
除了以上两种须要咱们本人去实现加载的形式,其实还能够间接应用第三方提供的 jar 包 OpenPnp,外面蕴含了 OpenCV.jar,对应各个平台的本地库,以及加载本地库的封装类;查看其源码能够发现,其实也是通过判断以后零碎,而后将对应的本地库文件拷贝到零碎的长期文件夹下,最初通过 system.load 去加载:
Files.createTempDirectory(`opencv_openpnp`);
因为此包兼顾了所有平台,所以整个包有点大,一百多 M,如果部署的零碎确定,其实能够本人去加载指定库文件就能够了,而后以雷同的形式打成一个公共包供各个系统应用;
总结
本文尽管介绍的是在我的项目中应用 OpenCV 的一些总结,但其实其余的本地库也能够应用雷同的形式;本文重点记录一下在应用过程中遇到的那些坑,以及加载库文件的形式。
代码地址
Github