由於之前的幾篇文已經將命令行的概念和每一步的操作原理介紹地很詳細了,所以本文僅會對新出現的命令進行解釋,對重複的概念和相同的操作步驟只做簡要說明。
上圖是這個系列的索引目錄,下面3篇是OpenCV、VC++、Visual Studio以及安裝包中的文件介紹:
OpenCV配置攻略(一):OpenCV, VC++和VS
OpenCV配置攻略(二): 安裝包裡都有什麼(上)
OpenCV配置攻略(二): 安裝包裡都有什麼(下)
下面的1-6是OpenCV3.4.10+contrib的編譯過程,包括每一步驟的概念介紹、命令解釋、可能出現的問題及解決方法,第7篇是OpenCV4.5.3的編譯和配置過程:
Ubuntu下安裝OpenCV(一): 準備工作
Ubuntu下安裝OpenCV(二): CMake編譯(上)
Ubuntu下安裝OpenCV(七): 4.x的安裝與配置
如果用戶是在Ubuntu16.04下進行安裝,那麼可以直接參考OpenCV3.x的步驟,親測在安裝和配置過程中不會出現報錯,但如果用戶是在Ubuntu18.04下進行安裝,就會有許多警告和報錯出現。
出現問題的原因我目前還沒找到官方的答案,匯總各種帖子裡的回答,可以總結為:Ubuntu18.04默認使用的編譯工具、默認下載的安裝包版本都比較高,一些舊的API、使用的策略(Policies)在新版本中已經被棄用,某些函數、宏定義也有了變化。而OpenCV2.x中使用的大多是舊版的內容(已被棄用/更改的內容)。
所以,在低版本的Ubuntu下安裝OpenCV2.x時不會出現錯誤,但在高版本的系統下進行編譯和安裝時,就會出現版本不兼容、接口不一致、策略被棄用等問題。
安裝OpenCV2.x和3.x的第一個區別在於2.x版本無需配置額外算法模塊。因為在OpenCV2.x中,名為contrib的模塊下包含的就是額外算法。
contrib文件夾
從OpenCV3.0.0開始,開發者才將這些比較新的、沒有經過充分測試的額外算法匯總起來,單獨放在opencv_contrib分支中進行發布。
所以在OpenCV2.x中沒有核心算法和額外算法的區分,用戶只需下載一個核心算法的源碼包即可。在CMake編譯時,也無需設置變量OPENCV_EXTRA_MODULES_PATH的參數。
2.2 CMake編譯
第二個非常的大的區別在CMake編譯部分,由於版本不兼容等問題,我在編譯OpenCV2.x時修改了很多參數才不報錯:
2.x下的CMake編譯
這是OpenCV3.x下的編譯命令:
接下來從第四步CMake編譯開始,介紹安裝和配置OpenCV2.x的每一個步驟,並展示對應的截圖。前三步(安裝需要的包,下載OpenCV原始碼並解壓縮,創建構建目錄)見 Ubuntu下安裝OpenCV(一): 準備工作
我將構建目錄的名稱設置為build,用戶可以設置自己喜歡的目錄名稱,一般會以編譯模式release/debug或者build來命名。
如果在編譯過程中出現ippicv壓縮包或其他文件下載失敗的問題,原理解釋見 Ubuntu下安裝OpenCV(二): CMake編譯(上),解決方法見 Ubuntu下安裝OpenCV(三): CMake編譯(下)
3.1 安裝編譯器
在第一節提到過,使用高版本的編譯器進行CMake編譯時會出現許多問題,所以我在這裡安裝了低版本的gcc和g++編譯器來執行編譯任務。參照Ubuntu16.04中默認的編譯器版本,我下載了gcc和g++的5.5.0版本。
在計算機任意位置輸入命令sudo apt-get install gcc-5 g++-5即可進行安裝gcc5.5.0和g++5.5.0編譯器:
Ubuntu18.04默認安裝的編譯器版本為7.5.0,當我們使用gcc和g++命令時,系統默認的編譯器gcc7.5.0和g++7.5.0將會工作;而輸入命令gcc-5和g++-5時,我們剛剛安裝的gcc5.5.0和g++5.5.0編譯器將會工作。這相當於我們在計算機中安裝了兩個不同版本的編譯器。
在計算機任意位置輸入gcc/g++/gcc-5/g++-5 --version即可查詢編譯器的版本信息:
3.2 執行編譯任務
進入構建目錄下,輸入sudo cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local/opencv-2-4-10-release -D CMAKE_C_COMPILER=/usr/bin/gcc-5 -D CMAKE_CXX_COMPILER=/usr/bin/g++-5 -D CMAKE_CXX_FLAGS=-std=c++11 -D WITH_FFMPEG=OFF .. 即可執行編譯任務:
3.3 參數解釋
接下來介紹cmake命令行中的各個變量的含義,類似於-D選項,CMAKE_BUILD_TYPE這類OpenCV3.x編譯中也用到了的變量,都在 Ubuntu下安裝OpenCV(二): CMake編譯(上) 進行了詳細介紹,下面只針對新出現的4個變量進行解釋:
(1) CMAKE_C_COMPILER 和
CMAKE_CXX_COMPILER
這兩個變量都屬於變量CMAKE_<LANG>_COMPILER,<LANG>指的是編譯器的語言,C代表C語言,CXX代表C++。
在GNU/Linux系統下,C/C++編譯器本質上是名為gcc/g++的可執行程序,它們都存放在/usr/bin目錄下。變量CMAKE_<LANG>_COMPILER的參數就是<LANG>編譯器的完整路徑(https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER.html)
This is the command that will be used as the <LANG> compiler. Once set, you can not change this variable.兩個變量的默認值分別為/usr/bin/gcc和/usr/bin/g++,即gcc和g++編譯器的路徑,我們在這裡將參數設置為/usr/bin/gcc-5和/usr/bin/g++-5,意味著將默認的編譯器修改為我們新安裝的5.5.0版本編譯器。
(2) CMAKE_CXX_FLAGS
這個變量屬於CMAKE_<LANG>_FLAGS,它負責設置CMake的編譯選項。該變量的參數是一系列用空格分隔的字符片段(https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_FLAGS.html)
This value is a command-line string fragment. Therefore, multiple options should be separated by spaces, and options with spaces should be quoted.因為5.5.0版本的C++編譯器需要ISO C++ 2011標準的支持,所以我們需要為變量CMAKE_CXX_FLAGS手動添加參數-std=c++11或者-std=gnu++11。如果不添加這一參數的話,在下一步make編譯時會出現報錯:
有關ISO C++ 2011標準的更多內容可以見這篇博客:https://www.learncpp.com/cpp-tutorial/b-1-introduction-to-c11/這個變量在CMakeLists.txt中的注釋為Include FFMPEG support,也就是包含FFMPEG支持,參數值默認為ON。但是,如果使用默認參數ON進行編譯,在下一步make編譯時會出現如下報錯:
這裡的報錯信息非常長,報錯原因是某些宏定義沒有被聲明。由於FFMPEG模塊在升級的過程中棄用了一些宏定義和函數,並更換了一些API的名稱,而OpenCV2.x中依舊使用的是舊的內容,所以會出現接口不對應這類錯誤。
具體的API變更記錄見官方日誌: https://github.com/FFmpeg/FFmpeg/blob/master/doc/APIchanges
個人認為解決此問題的方法是下載舊版的ffmpeg支持包,但是我在嘗試了之後依舊是編譯失敗 到現在我也沒找到解決這個問題的方法。
所以我只能通過給變量WITH_FFMPEG設置參數OFF來跳過"包含FFMPEG支持"這一步,也就是說,讓編譯器不再編譯有關FFMPEG模塊的內容,編譯過程也就不會出現報錯了。
不過這樣做只是跳過了報錯,並沒有解決問題,如果讀者朋友們有好的解決方法,記得留言告訴我
3.3 編譯結果
在編譯過程中,CMAke會輸出很多棄用警告(CMake Deprecation Warning),主要是由於某些舊的策略(Policies)已經被棄用而導致的(https://cmake.org/cmake/help/v3.21/manual/cmake-policies.7.html)
CMake警告不會中斷編譯過程,所以我們可以忽略掉這些棄用警告:
編譯完成後,可以在輸出中查看編譯信息匯總:
編譯信息匯總從上圖可以看到,C和C++編譯器都使用了我們之前下載的5.5.0版本,在C++ flags中也已經添加了對C++11的支持。
在匯總信息的最後可以看到"Configuring done","Generating done"和"Build files have been written to <build directory>"三條語句。這說明CMake這一步已經全部完成,編譯生成的文件已經被保存在了構建目錄下。
接下來的所有步驟和OpenCV3.x完全相同,如果想看詳細的步驟、命令解釋的話可以查看之前的文章。
第5步進行make編譯,在構建目錄下輸入sudo make或者sudo make -j*進行單線程或多線程編譯,*代表計算機可用線程數。
我的計算機可用線程數為8,所以輸入sudo make -j8進行編譯:
在計算機任意位置輸入cat /proc/cpuinfo | grep "processor" | wc -l 可以查看自己計算機的可用線程數:
在使用make命令進行編譯的過程中,我們也會看到很多警告信息,這些同樣都屬於棄用警告,可以再次忽略掉:
make編譯完成後,OpenCV項目的目標文件都已經生成,接下來需要將這些目標文件打包生成庫文件,並連同頭文件、可執行程序和一些文本文件/數據一起安裝在CMake編譯時我們通過變量CMAKE_INSTALL_PREFIX設置的路徑下。
在構建目錄下輸入sudo make install執行這一步:
sudo make install
這一步的執行速度會很快,從輸出內容中,我們還能看到項目的編譯模式為"Release",並清楚的看到各個文件的安裝過程:
等待執行完成之後,使用cd命令進入之前設置的安裝路徑下(我設置的是/usr/local/opencv-2-4-10-release),可以看到4個新生成的文件夾:
其中,bin文件夾用來存放可執行程序、include存放算法的頭文件、lib存放.pc文件和Release版本的庫文件、share會存放一些文本文件以及XML格式的數據。接下來設置系統共享庫的路徑,在/etc/ld.so.conf.d/下輸入命令sudo touch <file name>新建一個指定名稱的文件,拓展名為.conf;之後使用命令sudo gedit <file name>在該文件中寫入OpenCV共享庫的路徑。
在這裡我將文件命名為opencv-2-4-10r.conf,在文件中寫入/usr/local/opencv-2-4-10-release/lib:
在/etc/ld.so.conf.d/中還能看到我之前設置的不同版本、不同編譯模式的.conf文件,設置規範的文件名有助於文件的歸檔整理與查找。
保存好文件之後,輸入sudo ldconfig命令更新系統動態庫的路徑緩存。
第8步和第9步也很簡單,第8步先設置OpenCV2.4.10的頭文件和共享庫選項,進入/usr/lib/pkgconfig文件夾下,使用cp命令將opencv.pc文件複製到該目錄下,並為文件重命名。
opencv.pc被安裝在<install directory>/lib/pkgconfig下,這裡的<install directory>指的是我們在CMake編譯時通過變量CMAKE_INSTALL_PREFIX設置的路徑。
下圖中我將文件重命名為opencv-2-4-10r.pc,從圖中同樣能看到我之前複製粘貼過來的不同版本、不同編譯模式生成的.pc文件:
複製完成後,使用pkg-config命令驗證一下是否設置成功。在命令行中輸入pkg-config --modversion opencv-2-4-10r、pkg-config --cflags opencv-2-4-10r和pkg-config --libs opencv-2-4-10r,如果正確輸出了.pc文件的內容,則這一步完成。
第9步更加簡單,在計算機任意位置輸入命令sudo updatedb,進行系統文件名資料庫的更新。
最後,用OpenCV自帶的樣例做一個測試,在OpenCV2.4.10源碼包下的samples/cpp文件夾中,挑選一個C++程序進行測試,我在這裡選擇的是squares.cpp,它實現了一個從圖片中尋找方框的算法。
在cpp文件夾下,輸入命令sudo g++ -o squares squares.cpp `pkg-config --cflags --libs opencv-2-4-10r`對原始碼進行編譯,並將生成的可執行程序命名為squares。之後輸入sudo ./squares運行該程序,如果成功出現圖片,則代表測試成功。
歷時一個半月,Ubuntu下安裝OpenCV系列終於完結了 如果從第一篇"OpenCV配置攻略"算起,已經過去四個月了。不過,整個OpenCV系列並沒有完結 我正在寫Windows下安裝OpenCV系列,計劃更新6-7篇,目前已經寫到了第3篇,希望春節前可以更新完吧 實在是寫不動了。
在我的待寫目錄中,還有2篇"基於Python的OCR實現",1篇"重裝Windows10攻略",1篇"Windows10下安裝Ubuntu雙系統攻略",以及2022年準備開始寫的長篇連載文"微信小程序全棧開發"系列(畫大餅),再加上我最近在做新的項目,估計後續還會有更多的內容可以寫,悄悄期待一下。
下一篇文大概率會是基於Python的OCR實現 應該會分成上下兩篇來發,主要內容是使用5種方法進行文字識別,目前我已經完成了其中的4種,快寫完啦
~END~