SpringBoot使用OpenCV總結

前言

最近有個項目須要對圖片圖像進行處理,使用到了開源框架OpenCV全稱是Open Source Computer Vision Library,是一個跨平臺的計算機視覺庫;而如今的項目都是基於SpringBoot,須要把OpenCv整合進去,下面把在使用中遇到的問題進行一個彙總整理。html

下載安裝

Opencv官網提供了一個多個平臺的版本包括:Windows,IOS,Android,地址以下:https://opencv.org/releases/;由於開發在Windows平臺,發佈在Linux平臺,因此咱們這裏至少須要兩個版本;java

windows平臺

直接能夠在官網下載opencv-3.4.10-vc14_vc15.exe安裝便可,安裝完會出現opencv文件夾在buildjava目錄下有咱們須要的opencv-3410.jar,x64/opencv_java3410.dll,x86/opencv_java3410.dll文件;git

Linux平臺

Linux平臺須要咱們手動編譯,下載opencv-3.4.10.zip,解壓到/user/local目錄下,而後編譯安裝,執行以下命令:github

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.sospring

整合使用

兩個平臺分別安裝完以後,獲取了對應的dll和so文件;兩個平臺獲取到的jar都是同樣的,隨便用哪一個均可以,下面看看如何使用apache

外部引用方式

經過把應用jar與本地庫文件進行分隔開,而後在項目中進行引用windows

相對路徑方式

能夠經過System.loadLibrary來指定本地庫文件,可是這種方式須要在運行時指定-Djava.library.path,具體能夠提供配置類:springboot

@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來指定本地庫函數的絕對路徑:maven

@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

相關文章
相關標籤/搜索