OpenCV ARM移植(交叉編譯opencv)
部分內容來自下面2編文章:
arm-oe-linux-gnueabi-gcc編譯opencv3.1.0
Cmake的安裝
OpenCV 2.2以後版本需要使用Cmake生成makefile檔案,因此需要先安裝cmake。
ubuntu下安裝cmake比較簡單,
apt-get install cmake
如果覺得自帶的版本不符合要求,可以下載安裝包。
下載最新版的安裝包:
這裡下載已經編譯好的,這樣只需要解壓至需要的目錄下即可使用:
tar zxvf cmake-2.8.10.2-Linux-i386.tar.gz –C /usr/local/
設定環境變數:
sudo gedit /home/emouse/.bashrc
在開啟的檔案後新增:
export PATH=$PATH:/usr/local/cmake-2.8.10.2-Linux-i386/bin
檢視版本,測試是否安裝成功:
[email protected]:/home# cmake --version
OpenCV 的交叉編譯
解壓OpenCV壓縮檔案,得到資料夾。
#cmake-gui 開啟cmake的gui介面,開始進行配置,配置過程如下圖所示:
首先電腦得先安裝arm-linux的交叉編譯環境,這裡就不介紹這個了,直接說重點。
方法一(編譯通過):
1、在終端視窗輸入sudo apt-get install cmake-qt-gui下載cmake圖形介面
2、安裝好後在終端視窗輸入cmake-gui開啟cmake的gui介面
3.在“where is the source code”中填入電腦中opencv原始碼的位置,“where to build the binaries”填入生成make編譯檔案的位置,然後點選configure按鈕,選擇最後一項
4.點選NEXT再跳出的介面中做如下設定
Operating System 選擇目標系統arm-linux
Compilers中選擇交叉編譯器的gcc和g++
這裡注意選擇用什麼編譯,根據不同的編譯選擇編譯命令的路徑。
我是使用的arm-oe-linux-gnueabi來編譯,找到編譯器的安裝路徑:/usr/local/oecore-i586/sysroots/i586-oesdk-linux/usr/bin/cortexa9hf-vfp-neon-oe-linux-gnueabi/
gcc:/usr/local/oecore-i586/sysroots/i586-oesdk-linux/usr/bin/cortexa9hf-vfp-neon-oe-linux-gnueabi/arm-oe-linux-gnueabi-gcc
g++:/usr/local/oecore-i586/sysroots/i586-oesdk-linux/usr/bin/cortexa9hf-vfp-neon-oe-linux-gnueabi/arm-oe-linux-gnueabi-g++
Target Root選擇交叉編譯器的路徑
5.點選Finish按鈕,開始生成配置檔案,但是這個時候會報錯。
6.此時主介面如下圖所示,這時Cmake會讀取程式的一些配置資訊,可以再下圖紅框中對每一個編譯選項進行修改,這裡去掉WITH_TIFF,修改CMAKE_FIND_ROOT_PATH安裝路徑::/usr/local/oecore-i586/sysroots/i586-oesdk-linux/usr/bin/cortexa9hf-vfp-neon-oe-linux-gnueabi/。
System is unknown to cmake, create:
Platform/arm-linux to use this system, please send your config file to [email protected] so it can be added to cmake
這個是因為Operating System填寫的arm-linux不算Cmake能識別的目標系統,這裡可以忽略這個錯誤。
但是這個時候還有其他錯誤,
CMake Error at cmake/FindCUDA.cmake:763 (if):
if given arguments:
"CUDA_VERSION" "VERSION_GREATER" "5.0" "AND" "CMAKE_CROSSCOMPILING" "AND" "MATCHES" "arm"
Unknown arguments specified
Call Stack (most recent call first):
cmake/OpenCVDetectCUDA.cmake:26 (find_package)
cmake/OpenCVFindLibsPerf.cmake:24 (include)
CMakeLists.txt:468 (include)
應該是我的電腦裡沒有安裝CUDA的庫,因為後面的開發中也不會用到CUDA,所以我將 WITH_CUDA的鉤去掉,然後再點選一次Configure按鈕,看看還有沒有提示缺少哪些第三方庫,網上其他文章說WITH_TIFF要去掉,但是這裡沒有報錯就不管它了。
7.同時可以將CMAKE_INSTALL_PREFIX改成你想要的路徑,這個路徑所opencv最後庫檔案和標頭檔案的安裝路徑。在不存在其他問題後點擊Generate生存Makefile檔案,如果前面第三方的問題沒有解決這裡是會報錯而無法生存Makefile。生成的Makefile檔案和Cmake配置檔案都在 Wher to build the binarier 中設定的資料夾下
8.
在終端視窗中進入 Wher to build the binarier 中設定的資料夾下執行make指令,make失敗提示如下
../../lib/libopencv_core.so: undefined reference to `pthread_spin_init'
../../lib/libopencv_core.so: undefined reference to `pthread_spin_unlock'
../../lib/libopencv_core.so: undefined reference to `pthread_spin_lock'
../../lib/libopencv_core.so: undefined reference to `pthread_spin_destroy'
../../lib/libopencv_core.so: undefined reference to `pthread_once'
../../lib/libopencv_core.so: undefined reference to `clock_gettime'
../../lib/libopencv_core.so: undefined reference to `pthread_spin_trylock'
//Flags used by the linker.
CMAKE_EXE_LINKER_FLAGS:STRING=-lpthread -lrt
lrt這個不知道是什麼,只是網上其他文章說要加上我就也加上了,然後再繼續編譯,編譯完成後執行指令make install安裝庫檔案和標頭檔案到CMAKE_INSTALL_PREFIX指定的資料夾下。雖然網上有很多文章寫的都是用這個方法,都是這個方法是有問題的,前面所提到的configure時提示的System is unknown to cmake,這個錯誤是直接被我忽略的,都是其實這個是很有問題的,因為CMake編譯過程中我們沒有告訴編譯器我們要用的是是哪個系統,那有些功能它就不知道是選擇編譯和window相容的程式碼,還是和linux相容的程式碼,比如我在後面用這個編譯好的opencv庫寫的程式放到210的板子上執行時,軟體自帶的函式cvCreatCamerCapture沒辦法識別板子上的usb攝像頭,在谷歌查了很久才發現是編譯的時候沒有支援V4L2,後來發現是目標系統選擇的問題,下面的另一種方法將解決這個問題。
方法二 (編譯不通過):
前面再configure時提示的System is unknown to cmake是被我忽略不管的下面介紹下不忽略這個錯誤的編譯過程。
出現這個錯誤的原因是Cmake不能識別arm-linux這種系統,所以我們把他改成Linux,注意第一個字母大寫,不能寫錯linux,否則還會出現那個錯誤
另外需要注意的是include Mode要選擇成Search only in Target Root這樣在後面opencv編譯時搜尋標頭檔案就只會在Target Root指定的資料夾下搜尋,而不會到你電腦的usr/include/下搜尋,如果這裡還是先前的search in Target Root, then native system則會到/usr/include/下搜尋標頭檔案,就會出現一些問題,在
10.我的電腦中出現了下面的問題
/usr/include/bits/mathinline.h:675:3: error: unknown register name 'st' in 'asm'
/usr/include/bits/mathinline.h:675:3: error: unknown register name 'st' in 'asm'
/usr/include/bits/mathinline.h:675:3: error: unknown register name 'st' in 'asm'
mathinline.h在/usr/include/bits/和/opt/FriendlyARM/toolschain/4.5.1/arm-none-linux-gnueabi/sys-root/usr/include/bits/目錄下都有,這個時候優先選擇了/usr/include下的mathinline.h,於是編譯就出錯了,那之前在Operating System為arm-linux時為什麼沒有這個錯誤呢?筆者認為可能是在arm-linux時會預設先搜尋電腦中配置的arm-linux的路徑也就是/opt/FriendlyARM/toolschain/4.5.1/下的include資料夾,而如果設定成Linux則優先搜尋/usr/include。因此要將include Mode選擇成Search only in Target Root,這樣編譯的時候就只會在/opt/FriendlyARM/toolschain/4.5.1/資料夾下搜尋標頭檔案了。
11.接著後面和前面一樣所去掉CUDA第三方庫,更改CMAKE_INSTALL_PREFIX,更改後記得再點選一次configure然後再點選Generate,進入資料夾修改CmakeCache.txt,make,這個時候又報錯了:
undefined reference to `dlopen'
沒有找到dl庫,繼續修改CmakeCache.txt
CMAKE_EXE_LINKER_FLAGS:STRING=-lpthread -lrt -ldl
編譯好後make install,這個時候其實大家會發現這個方法編譯出來的連結庫比第一種方法編譯出來的連結庫要多一些,在目前的嵌入式開發階段中使用這個連結庫還沒有發現什麼。其實我才移植了一個軟體而已,哈哈!
參考文件: