树莓派3b+ubuntu MATE18.04编译opencv4.1.2实例

上一篇博客在wsl里交叉编译了aarch64的opencv,然后移植到了树莓派上,这篇博客继续,就该编译运行实例了,过程中遇到的问题及解决办法如下。

question 1

首先来看一下移植过来的opencv到底是否可用,找到了官方例程里的一个opencv_version.cpp,如下

#include 
#include 
static const std::string keys = "{ b build | | print complete build info }"
                                "{ h help  | | print this help           }";
int main(int argc, const char* argv[])
{
    cv::CommandLineParser parser(argc, argv, keys);
    parser.about("This sample outputs OpenCV version and build configuration.");
    if (parser.has("help"))
    {
        parser.printMessage();
    }
    else if (!parser.check())
    {
        parser.printErrors();
    }
    else if (parser.has("build"))
    {
        std::cout << cv::getBuildInformation() << std::endl;
    }
    else
    {
        std::cout << "Welcome to OpenCV " << CV_VERSION << std::endl;
    }
    return 0;
}

好,把它上传到树莓派$HOME目录下,修改权限,开始编译,这里直接用g++可能不会成功,会出现
一堆undefined reference to “cv::……”的错误,这里需要编译的时候加参数:
g++ opencv_version.cpp -o opencv_version pkg-config opencv --cflags --libs(注意:pkg-config opencv --cflags --libs两边需要加反引号)
然后又报错了,这次是undefined reference to “pthread……”和“dl……”,(如果这里是pkg-config和opencv的问题的话请看question 2)那我们继续加参数:
g++ opencv_version.cpp -o opencv_version pkg-config opencv --cflags --libs -pthread -ldl
好,成功编译,运行出现:
Welcome to OpenCV 3.2.0
ok,运行成功了,可是问题出现了,我交叉编译的是opencv4.1.2啊,为什么出来的版本是3.2.0???
在解决新的问题之前先回顾一下这个问题到底是怎么解决的,来看以下几点:

  • pkg-config是一个linux下的命令,用于获得某一个库/模块的所有编译相关的信息。(要用pkg-config的参数的话,得设置xxx.pc文件,见question 2)
  • 在交叉编译移植了opencv之后,需要解决的问题首先是动态链接库的问题,教程里有几种方法,如下:
    • 修改/etc/ld.so.conf.d/opencv.conf文件,在里面加入移植后的opencv里的lib目录,然后ldconfig
    • 直接修改/etc/ld.so.conf文件,同样加入lib目录,然后ldconfig
    • 编辑~/.bashrc文件,设置变量LD_LIBRAY_PATH,然后ldconfig
    • 上面这几种,最后都要ldconfig,归根结底就是在修改了动态链接库的路径后,把路径内的.so文件更新到/etc/ld.so.cache 内,可以cat一下,总之通过这样的方式使动态链接器能够找到相应的.so文件
  • 然后就是刚刚遇到的“pthread……”和“dl……”未定义引用的error,这里其实也是动态链接的问题,所以在g++后加参数-pthread和-ldl就好了。

question 2

编译运行成功了,但是突然发现版本不一致是什么原因???
上一步解决问题的过程中我们用到了ld-config命令,还提到了可以cat一下/etc/ld.so.cache文件,打开了但是太多看不懂啊,这时候我们用这个命令ldconfig -p | less,然后在里面寻找我们交叉编译得到的libopencv_.so文件,找到了之后发现同一个.so文件竟然有多个,在不同的目录下,这时候就清楚了,版本不一致的原因是因为树莓派里已经有3.2.0版本的opencv并且配置过了,那我把这个目录下的libopencv_.so删掉,这时候opencv的动态链接库就成功变成我们交叉编译后的库了。好,我们重新编译opencv_version.cpp,又出问题了!
error while loading shared libraries: libopencv_core.so.3.2: cannot opesuch file or directory
动态链接失败了,这个3.2是刚刚已经删掉的啊,这时候想起了咱们的pkg-config,它是通过xxx.pc文件生效的,既然之前可以用,说明之前配置过该文件,find找到opencv*.pc文件,重新编辑,配置环境变量,参见1,参见2。
配好之后,重新编译,再次运行,出现Welcome to OpenCV 4.1.2,成功。

question 3

经过测试,在树莓派上编译运行调用opencv库的程序已经成功了,不过如果直接在树莓派上编译源程序的话,在碰到比较大的工程的时候还是会比较慢,所以交叉编译就又派上用场了,可以减短本来所需的编译时间,直接把可执行文件从pc上传到树莓派上运行。
那么我们再次测试:
在wsl下g++ -L -I直接指定库和头文件是行不通的,和一开始遇到的问题一样,
然后配置pkgconfig,加上-pthread -ldl参数就成功了
aarch64-linux-gnu-g++ pkg-config opencv-aarch64 --cflags --libs opencv_version.cpp -o opencv_version -pthread -ldl(记得加反引号,我配置的是opencv-aarch64.pc文件)
但是这样操作会遇到很多not found的warning,排除了好多其他的影响后也没有解决这个问题,等以后知识储备够了再解决这个问题。
然后把opencv_version传到树莓派$HOME上,运行,会发现找不到.so文件,而且所提示的路径就是刚刚报warning的路径,也就是…/…/lib/*.so not found,
解决办法很随性,既然程序要去前两级目录找/lib/.so文件,那我就在lib的上一级目录新建两级目录,把这个目录当成工作目录,把调用opencv库的交叉编译后的文件都放到工作目录下再执行就可以了。
好的,执行,出现Welcome to OpenCV 4.1.2
不过这并不算彻底解决问题,问题应该产生在pc上交叉编译的环节,等日后解决了再更新。

你可能感兴趣的:(树莓派)