背景:html
最近,在Nvidia的GPU嵌入式開發板Jetson TX1(簡稱TX1)上移植深度學習目標檢測算法YOLO。在TX1上安裝了官方提供的opencv版本——OpenCV4Tegra(OpenCV-2.4.12),可是使用該版本opencv VideoCapture在讀取攝像頭數據時出錯,顯示錯誤:linux
Unable to stop the stream.: Device or resource busy Unable to stop the stream.: Bad file descriptor
使用Google試圖找到解決方法,最後發現官方給出答案,只能從新安裝Opencv3.0以上的 版本。我使用Nvidia論壇jkjung提供的方法安裝OpenCV3.1.0。安裝完成後,我使用的TX1 Ubuntu14.04上安裝了兩個版本的OpenCV, Opencv-2.4.12和Opencv-3.1.0。所以,我面臨着如何在程序中指定使用指望版本的OpenCV,即Ubuntu下多個版本Opencv管理的問題。算法
解決方案:ubuntu
如今討論Ubuntu14.04下分別使用CMake和Makefile編譯運行帶Opencv程序的兩種解決方案。ide
1. CMake下指定Opencv版本post
關鍵文件:OpenCVConfig.cmake。在opencv編譯好後,所在目錄中通常會有一個叫OpenCVConfig.cmake的文件,這個文件中指定了CMake要去哪裏找OpenCV,其.h文件在哪裏等,好比其中一行:學習
# Provide the include directories to the caller set(OpenCV_INCLUDE_DIRS "/home/ubuntu/src/opencv-3.1.0/build" "/home/ubuntu/src/opencv-3.1.0/include" "/home/ubuntu/src/opencv-3.1.0/include/opencv")
只要讓CMake找到這個文件,這個文件就指定了Opencv的全部路徑,所以設置OpenCV_DIR爲包含OpenCVConfig.cmake的目錄,如在個人C++工程CMakeLists.txt中添加ui
set(OpenCV_DIR "/home/ubuntu/src/opencv-3.1.0/build")
個人OpenCVConfig.cmake在spa
/home/ubuntu/src/opencv-3.1.0/build
注意,將其添加在project(MyProjectName)以前。3d
如CMakeLists.txt內容以下:
cmake_minimum_required(VERSION 2.8) set(OpenCV_DIR "/home/ubuntu/src/opencv-3.1.0/build") project( camera ) find_package( OpenCV REQUIRED ) add_executable( camera camera.cpp ) target_link_libraries( camera ${OpenCV_LIBS} )
所以,咱們指望使用哪一個版本的Opencv,只要找到對應的OpenCVConfig.cmake文件,而且將其路徑添加到工程的CMakeLists.txt中便可了。
2. Makefile下指定Opencv版本
關鍵文件:opencv.pc 。在Makefile下,應該是能夠在其中詳細設定Opencv路徑,要使用到哪些庫等等(我沒有仔細學習過Makefile的使用)。在此,我想介紹一種簡單的在Makefile下指按期望使用的Opencv版本的方法,該方法藉助linux下pkg-config命令。
咱們經常使用pkg-config --modversion 來查看指定庫的版本,好比查看opencv版本pkg-config --modversion opencv。其實pkg-config顯示的信息來自於這個庫對應的.pc文件,好比安裝了opencv後,咱們能夠在/usr/lib/pkg-config/ 文件夾下找到opencv.pc,內容以下:
# Package Information for pkg-config prefix=/usr exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir_old=${prefix}/include/opencv includedir_new=${prefix}/include Name: OpenCV Description: Open Source Computer Vision Library Version: 2.4.12.2 Libs: -L${exec_prefix}/lib -lopencv_calib3d -lopencv_contrib -lopencv_core -lopencv_features2d -lopencv_flann -lopencv_gpu -lopencv_highgui -lopencv_imgproc -lopencv_legacy -lopencv_ml -lopencv_objdetect -lopencv_photo -lopencv_stitching -lopencv_superres -lopencv_ts -lopencv_video -lopencv_videostab -lopencv_detection_based_tracker -lopencv_esm_panorama -lopencv_facedetect -lopencv_imuvstab -lopencv_tegra -lopencv_vstab -L/usr/local/cuda-7.0/targets/armv7-linux-gnueabihf/lib -lcufft -lnpps -lnppi -lnppc -lcudart -ltbb -lrt -lpthread -lm -ldl Cflags: -I${includedir_old} -I${includedir_new}
固然,咱們也可使用
pkg-config --cflags opencv
pkg-config --libs opencv
分別查看opencv庫的包含目錄(include/, .h)和庫名稱(.so)。在Makefile中,能夠經過以上命令設定opencv庫相關目錄。以下:
COMMON+= -DOPENCV CFLAGS+= -DOPENCV LDFLAGS+= `pkg-config --libs opencv` COMMON+= `pkg-config --cflags opencv`
此時Makefile對應的工程使用的opencv庫即爲opencv.pc文件中所指的版本。本例中爲2.4.12.2。
那麼能夠容易想到,若是我在/usr/lib/pkgconfig文件夾目錄下添加opencv-3.1.0.pc文件,是否就能夠將版本指向opencv-3.1.0l了呢?答案是確定的。
我在編譯opencv-3.1.0的編譯目錄下/home/ubuntu/src/opencv-3.1.0/build/目錄下找到了unix-install/opencv.pc文件,其內容以下:
# Package Information for pkg-config prefix=/home/ubuntu/opencv-3.1.0 exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir_old=${prefix}/include/opencv includedir_new=${prefix}/include Name: OpenCV Description: Open Source Computer Vision Library Version: 3.1.0 Libs: -L${exec_prefix}/lib -lopencv_cudabgsegm -lopencv_cudaobjdetect -lopencv_cudastereo -lopencv_shape -lopencv_stitching -lopencv_cudafeatures2d -lopencv_superres -lopencv_cudacodec -lopencv_videostab -lopencv_cudaoptflow -lopencv_cudalegacy -lopencv_calib3d -lopencv_features2d -lopencv_objdetect -lopencv_highgui -lopencv_videoio -lopencv_photo -lopencv_imgcodecs -lopencv_cudawarping -lopencv_cudaimgproc -lopencv_cudafilters -lopencv_video -lopencv_ml -lopencv_imgproc -lopencv_flann -lopencv_cudaarithm -lopencv_core -lopencv_cudev
我發現其中的路徑是不太準確的,更正爲:
# Package Information for pkg-config prefix=/home/ubuntu/src/opencv-3.1.0 exec_prefix=${prefix}/build libdir=${exec_prefix}/lib includedir_old=${prefix}/include/opencv includedir_new=${prefix}/include Name: OpenCV Description: Open Source Computer Vision Library Version: 3.1.0 Libs: -L${exec_prefix}/lib -lopencv_cudabgsegm -lopencv_cudaobjdetect -lopencv_cudastereo -lopencv_shape -lopencv_stitching -lopencv_cudafeatures2d -lopencv_superres -lopencv_cudacodec -lopencv_videostab -lopencv_cudaoptflow -lopencv_cudalegacy -lopencv_calib3d -lopencv_features2d -lopencv_objdetect -lopencv_highgui -lopencv_videoio -lopencv_photo -lopencv_imgcodecs -lopencv_cudawarping -lopencv_cudaimgproc -lopencv_cudafilters -lopencv_video -lopencv_ml -lopencv_imgproc -lopencv_flann -lopencv_cudaarithm -lopencv_core -lopencv_cudev
並將其拷貝到/usr/lib/pkgconfig目錄下,並重命名爲opencv-3.1.0.pc,將原來的opencv.pc重命名爲opencv-2.4.12.pc。
那麼當我指望使用opencv-3.1.0時,Makefile中爲:
COMMON+= -DOPENCV CFLAGS+= -DOPENCV LDFLAGS+= `pkg-config --libs opencv-3.1.0` COMMON+= `pkg-config --cflags opencv-3.1.0`
當我指望使用opencv-2.4.12時,Makefile中爲:
COMMON+= -DOPENCV CFLAGS+= -DOPENCV LDFLAGS+= `pkg-config --libs opencv-2.4.12` COMMON+= `pkg-config --cflags opencv-2.4.12`
從而實現了多個版本OpenCV的使用。
備註:
運行make以後,運行可執行程序時,可能會提示找不到庫的錯誤(not find libopencv-core.so.3.1之類),那時由於動態庫目錄不在程序搜索庫目錄的路徑下,系統默認的動態庫搜索路徑有/usr/local/lib等,OpenCV4Tegra(opencv-2.4.12)生成的庫都在/usr/local/lib目錄,但opencv-3.1.0的庫在/home/ubuntu/src/opencv-3.1.0/build/lib中,不在搜索路徑中,所以,只須要添加其爲搜索路徑便可。添加方法爲/etc/ld.so.conf.d/libc.conf中添加/home/ubuntu/src/opencv-3.1.0/build/lib。libc.conf文件內容以下:
# libc default configuration /usr/local/lib /home/ubuntu/src/opencv-3.1.0/build/lib