前言
最近有个我的项目须要对图片图像进行解决,应用到了开源框架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.10mkdir buildcd buildcmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -DBUILD_TESTS=OFF ..make -j8sudo make install
装置完之后能够在build/bin目录下找到opencv-3410.jar,在build/lib目录下找到libopencv_java3410.so
整合应用
两个平台别离装置完之后,获取了对应的dll和so文件;两个平台获取到的jar都是一样的,轻易用哪个都能够,上面看看如何应用
内部援用形式
通过把利用jar与本地库文件进行分隔开,而后在我的项目中进行援用
相对路径形式
能够通过System.loadLibrary来指定本地库文件,然而这种形式须要在运行时指定-Djava.library.path,具体能够提供配置类:
@Configurationpublic 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来指定本地库函数的绝对路径:
@Configurationpublic 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.jar!/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