最近在Ubuntu 14.04上编译安装了OpenCV的源码,中间经历了许多曲折,网上找资料发现大家遇到的问题五花八门,不过总算也有能帮助到我的,所以我也把我的经验记录下来,希望能帮助到有需要的人。
按照官网的教程,先要安装编译工具和依赖库。
sudo apt-get install build-essential
sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev
这是官网上提供的三条命令行,这里面比如git和python工具我的Ubuntu环境本身就具备了,而且我想知道每个安装步骤的结果或者将会出现什么具体问题,所以我把上面的指令拆分了,一条一条地执行。
这个过程我遇到的问题是,我的Ubuntu的软件源有一些库找不到,比如libgtk2.0-dev,提示如下。所以我需要寻找别的源,最后我在阿里云服务器上搜索到这个库,对应地在Ubuntu的软件与更新里面切换到aliyun软件源,剩下的软件包再也没有出现找不到的错误。
sudo apt-get install libgtk2.0-dev
正在读取软件包列表... 完成
正在分析软件包的依赖关系树
正在读取状态信息... 完成
E: 未发现软件包 libgtk2.0-dev
E: 无法按照正则表达式 libgtk2.0-dev 找到任何软件包
所以总体上在这个过程我执行了以下命令:
sudo apt-get install libgtk2.0-dev
sudo apt-get install build-essential
sudo apt-get install pkg-config
sudo apt-get install libavcodec-dev
sudo apt-get install libavformat-dev
sudo apt-get install libswscale-dev
sudo apt-get install python-dev
sudo apt-get install python3-dev
sudo apt-get install python-numpy
sudo apt-get install python3-numpy
sudo apt-get install libtbb2
sudo apt-get install libtbb-dev
sudo apt-get install libjpeg-dev
sudo apt-get install libpng-dev
sudo apt-get install libtiff-dev
sudo apt-get install libjasper-dev
sudo apt-get install libdc1394-22-dev
解压源码,源码根目录下有CMakeList文件,CMAKE是个跨平台工具,这里我们使用CMAKE得到make file,才能进一步使用make指令编译源码。
我的源码路径是/local/sdb/tools/opencv-4.1.2。
user@SWD:/local/sdb/tools/opencv-4.1.2$ mkdir build
user@SWD:/local/sdb/tools/opencv-4.1.2$ cd build
我创建了/usr/local/opencv_4.1.2作为OpenCV的安装路径,单独一个目录比较方便管理。
user@SWD:/local/sdb/tools/opencv-4.1.2/build$ cd /usr/local
user@SWD:/usr/local$ sudo mkdir opencv_4.1.2
我目前没有安装ffmpeg,因为花了不少时间都没搞定,我估计好久都用不上它,就不必跟它耗时间了,所以我把OpenCV的ffmpeg配置项关闭了,如下:
user@SWD:/usr/local/opencv_4.1.2$ cd /local/sdb/tools/opencv-4.1.2/build
user@SWD:/local/sdb/tools/opencv-4.1.2/build$ cmake -D WITH_FFMPEG=OFF -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local/opencv_4.1.2 ..
这个过程在下载IPPICV软件包的地方卡了许久,网上许多同学都遇到这个问题了,还有许多妙招,可我太懒,宁愿干等也不想去研究(折腾)。我想大家普遍卡很久,这是个国外的资源吗?所以我连接了网络,把build目录的东西删掉重新来一遍,差不多喝杯水的功夫真的就搞定了。
这一步很顺利,耐心等待就是。
user@SWD:/local/sdb/tools/opencv-4.1.2/build$ sudo make
user@SWD:/local/sdb/tools/opencv-4.1.2/build$ sudo make install
完成以后,到我的安装目录去查看安装好的文件,然后我把lib和bin里面的文件分别创建了软链接放到/usr/lib和/usr/bin里面,没有为什么,我只是觉得可能需要,于是如此这般地操作:
user@SWD:/usr/bin$ sudo ln -s /usr/local/opencv_4.1.2/bin/opencv_annotation opencv_annotation
user@SWD:/usr/bin$ sudo ln -s /usr/local/opencv_4.1.2/bin/opencv_interactive-calibration opencv_interactive-calibration
user@SWD:/usr/bin$ sudo ln -s /usr/local/opencv_4.1.2/bin/opencv_version opencv_version
user@SWD:/usr/bin$ sudo ln -s /usr/local/opencv_4.1.2/bin/opencv_visualisation opencv_visualisation
user@SWD:/usr/bin$ sudo ln -s /usr/local/opencv_4.1.2/bin/setup_vars_opencv4.sh setup_vars_opencv4.sh
那些个so库也类似这样创建了软链接(可能不是必须,因为我的OpenCV Hello-World 程序一直报链接不到opencv_xxx.so的问题,所以我这么干了,后面找到原因了、是配置文件的问题,这个操作不是必要的,此处只是为了记录我完整的安装(踩坑)过程。
user@SWD:/usr/lib$ sudo ln -s /usr/local/opencv_4.1.2/lib/libopencv_calib3d.so.4.1.2 libopencv_calib3d.so
user@SWD:/usr/lib$ sudo ln -s /usr/local/opencv_4.1.2/lib/libopencv_calib3d.so.4.1.2 libopencv_calib3d.so.4.1.2
user@SWD:/usr/lib$ sudo ln -s /usr/local/opencv_4.1.2/lib/libopencv_calib3d.so.4.1.2 libopencv_calib3d.so.4.1
... ...
还是在官网的教程里找到的Hello-World程序,在本地创建C++文件StartWithOpenCV.cpp:
// /local/sdb/Book_Master_OpenCV_191203/C++/EclipseWorkSpace/src/StartWithOpenCV.cpp
#include
#include;
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
if (argc != 2) {
cout << "illegal arguments" << endl;
return -1;
}
Mat image;
// IMREAD_COLOR: 3 channels
image = imread(argv[1], IMREAD_COLOR);
if (!image.data) {
printf("No image data \n");
return -1;
}
namedWindow("Display Image", WINDOW_NORMAL);
imshow("Display Image", image);
cout << "channels=" << image.channels() << ",(h,w)=" << image.size << endl;
waitKey();
return 0;
}
某位热心小伙伴给我分享了这个编译指令:
user@SWD:/local/sdb/Book_Master_OpenCV_191203/C++/EclipseWorkSpace/src$ g++ -std=c++11 `pkg-config --cflags opencv` -o StartWithOpenCV StartWithOpenCV.cpp `pkg-config --libs opencv`
这条指令在小伙伴手上身经百战,然而,在我这里夭折了。对此我还是用了拆分指令的办法,单独运行其中一个指令,观其运行结果,如下。我看到这么详尽的信息是非常高兴的,离成功更近一步了,赶紧百度一下找资料,创建pc文件和配置环境变量的方法在这里:【Ubuntu 环境配置】(1)Ubuntu安装opencv-4.1.0+opencv_contrib-4.1.0(c++,py2,py3 皆可运行)。
user@SWD:/usr/local/opencv_4.1.2/lib$ pkg-config --cflags opencv
Package opencv was not found in the pkg-config search path.
Perhaps you should add the directory containing `opencv.pc'
to the PKG_CONFIG_PATH environment variable
No package 'opencv' found
按照这位网友的指示,我在本地创建了opencv.pc文件和opencv4.pc文件(其实一个也足够了,没有原因地,我只是觉得未来可能需要opencv4.pc来区分不同的版本),这是个模板,往里面按实际情况填写即可,尤其要注意的是:库的名字不要带lib或.so字样,比如~~-lopencv_imgproc.so~~ 或 -lopencv_imgproc.so,而应该是**-lopencv_imgproc**。
# /usr/local/opencv_4.1.2/lib/pkgconfig/opencv.pc
prefix=/usr/local/opencv_4.1.2
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir_old=${prefix}/include/opencv4/opencv
includedir_new=${prefix}/include/opencv4
Name: OpenCV
Description: Open Source Computer Vision Library
Version: 4.1.2
Libs: -L${exec_prefix}/lib -lopencv_imgproc -lopencv_calib3d -lopencv_ml -lopencv_core -lopencv_objdetect -lopencv_dnn -lopencv_photo -lopencv_features2d -lopencv_stitching -lopencv_flann -lopencv_videoio -lopencv_gapi -lopencv_video -lopencv_highgui -lopencv_imgcodecs
Libs.private: -ldl -lm -lpthread -lrt
Cflags: -I${includedir_old} -I${includedir_new}
此时再次运行pkg-config指令,正确的结果就有了:
user@SWD:/usr/local/opencv_4.1.2/lib/pkgconfig$ pkg-config --libs opencv
-L/usr/local/opencv_4.1.2/lib -lopencv_imgproc -lopencv_calib3d -lopencv_ml -lopencv_core -lopencv_objdetect -lopencv_dnn -lopencv_photo -lopencv_features2d -lopencv_stitching -lopencv_flann -lopencv_videoio -lopencv_gapi -lopencv_video -lopencv_highgui -lopencv_imgcodecs
pkg-config的环境变量配置好以后,再次运行4.2的编译指令,如下又出现新的问题,似乎是链接的问题,但其实只是我犯的低级错误,不过也多了解了一些东西。
user@SWD:/local/sdb/Book_Master_OpenCV_191203/C++/EclipseWorkSpace/src$ g++ -std=c++11 `pkg-config --cflags opencv` -o StartWithOpenCV StartWithOpenCV.cpp `pkg-config --libs opencv`
/usr/bin/ld: cannot find -llibopencv_imgproc.so
/usr/bin/ld: cannot find -llibopencv_ml.so
/usr/bin/ld: cannot find -llibopencv_core.so
/usr/bin/ld: cannot find -llibopencv_objdetect.so
/usr/bin/ld: cannot find -llibopencv_dnn.so
ld看起来像是load的意思,我想知道怎么就找不到库了,毕竟我还创建了软链接放到/usr/lib目录了,这个目录不可能不去查询的呀。网上找了找资料,在StackOverflow:usr/bin/ld: cannot find -l找到了一些相关信息,如下可以知道ld指令的执行过程。
ld --help
ld -lxxxlib --verbose
ld -llibopencv_imgproc --verbose
试图打开 /usr/x86_64-linux-gnu/lib64/liblibopencv_imgproc.so 失败
试图打开 /usr/x86_64-linux-gnu/lib64/liblibopencv_imgproc.a 失败
... ...
试图打开 //usr/lib/liblibopencv_imgproc.so 失败
试图打开 //usr/lib/liblibopencv_imgproc.a 失败
ld: cannot find -llibopencv_imgproc
这样执行过程就很清晰了,//usr/lib/这样两个斜杠开头的我虽然感觉很不对,不过暂时也没有管它,因为我发现了我自己的低级错误:我在/usr/lib/和opencv.pc里面配置的库名字是不同的,名字不匹配当然找不到,修正以后就没有问题了,Hello-World终于运行起来了。
试图打开 //usr/lib/libopencv_imgproc.so 成功
-lopencv_imgproc (//usr/lib/libopencv_imgproc.so)
官网有非常详细的教程:Using OpenCV with Eclipse (plugin CDT),然而在我的环境中,还是出现了新的问题。
**** Build of configuration Debug for project StartWithOpenCV ****
make all
Building target: StartWithOpenCV
Invoking: GCC C++ Linker
g++ -nodefaultlibs -L/usr/lib/x86_64-linux-gnu -lstdc++ -o "StartWithOpenCV" ./src/StartWithOpenCV.o -lopencv_imgproc -lopencv_calib3d -lopencv_core -lopencv_ml -lopencv_dnn -lopencv_objdetect -lopencv_features2d -lopencv_photo -lopencv_flann -lopencv_stitching -lopencv_gapi -lopencv_videoio -lopencv_highgui -lopencv_video -lopencv_imgcodecs
/usr/bin/ld: ./src/StartWithOpenCV.o: undefined reference to symbol '__cxa_pure_virtual@@CXXABI_1.3'
/usr/lib/gcc/x86_64-linux-gnu/4.8/libstdc++.so: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
make: *** [StartWithOpenCV] 错误 1
**** Build Finished ****
libstdc++.so是标准库,我前面在终端可以运行成功,说明标准库没有大问题,而且这里还是和ld有关,标准库没有链接到,最后我在以下路径找到了配置:
Project –> Properties –> C/C++ Build –> Settings –> Tool Settings –> GCC C++ Linker –> General
这里Eclipse默认给我勾选了Do not use default libraries,取消勾选即可。
至此,终端和Eclipse环境都准备完成了。
新手先仔细研究官方教程
像OpenCV这样广泛使用的开源库,它的文档支持是非常完善的,与其百度/Google找安装教程,不如先研究官方文档。
起于教程,不止于教程
官方教程准备的指令都非常理想化,而开发者实际遇到的问题层出不穷,所以我用了最朴实的办法一道一道地执行指令,对安装过程有个感性的认识,问题发生时才能比较准确地感知可能的根源。