ARM交叉编译OpenCV错误总结

11 篇文章 0 订阅
9 篇文章 6 订阅

ARM交叉编译OpenCV错误总结

最近尝试给两个ARM板子与用交叉编译配置OpenCV,为此查了很多资料,学了很多交叉编译的操作。
经过多次的交叉编译全都失败,都不能成功的在目标板上运行简单的OpenCV的Demo程序。最后都是在对板子失去希望的时候,破罐破摔的直接用ARM板自己编译。讽刺的是,这样虽然效率低到极致,但最后还真的成功了…… 在Demo程序在ARM板自行编译成功的OpenCV环境中顺利的跑起来的时候,笔者感觉茫然无措,根本没有什么开心的情绪,一是感觉终于解脱了,二是感觉自己学了这么长时间的交叉编译,最后还是没有用,还写了这么多技术博客,深深的无力感……
笔者决定还是痛定思痛,还是得总结一下这段时间交叉编译的错误所在。在中间的一些操作中,笔者总感觉自己交叉编译的过程中,就是还是那么差了一点点才导致失败。虽然已经没有精力再重新搞一遍交叉编译。这些疑点还是可以记录下来,以后有机会的时候,笔者会重新拿出来看,也许真的是这些原因导致我交叉编译错误呢?

笔者的两个ARM板配置如下:

  • 迅为i.MX6Q开发板
    • 操作系统:Linux
    • 发行版:Debian GNU/Linux (BeagleBoard.org Debian Image)
    • CPU:1GHz四核
    • 容量:16GBytes eMMC
  • BeagleBone Black
    • 操作系统:Linux
    • 发行版:Ubuntu 12.04
    • CPU:1GHz单核
    • 容量:4GBytes eMMC

之前笔者写的交叉编译相关技术博客地址如下:
《 Ubuntu 14.04 LTS下使用arm-linux-gcc交叉编译OpenCV 2.4.9》
《Windows系统下远程连接BeagleBone Black开源电路板桌面》
《Windows系统下通过PSCP传输文件至BeagleBone Black》
《交叉编译学习笔记(一)——交叉编译和交叉工具链》
《交叉编译学习笔记(二)——交叉编译器的命名规则》
《程序生成之编译、链接、加载浅析》

一. BeagleBone Black编译总结

BeagleBone Black(即BBB)上OpenCV的编译是真的痛苦。
主要原因是它的4GBytes的容量实在让我绝望,而且我拿到板子的时候基本上也只有1GBytes的剩余容量了,OpenCV编译过程中生成的中间文件大小都得有2GB啊…… 这导致笔者几乎从一开始就否定了直接用BBB编译的想法,一直在尝试交叉编译……

1. 编译成功方法

讽刺的是交叉编译一直失败,最后我还是直接在ARM上编译成功的,即先设置各项CMake选项,然后对OpenCV进行make操作,最后make install,并make clean清除中间文件。
为什么笔者能在1GBytes的剩余容量中编译出2GB的中间文件?这就是最蛋疼的地方所在…… 笔者OpenCV源码路径是/root/Desktop/opencv-2.4.9,编译生成路径是源码路径下的/build路径。在make过程中,中间文件基本存在于/root/Desktop/opencv-2.4.9/build/module中,所以在make过程中,笔者会在终端显示已经将上一个模块编译结束后,直接手动将对应模块路径下的中间文件删除……
笔者当时想反正make install指令的目标一般都是/include, /lib, /bin文件夹,这些中间文件占的空间又这么大,删除也不会对make install指令有什么影响……
事实证明我是正确的,但是过程很繁琐,不能像在PC机上编译时,只要放在那里编译就好,笔者可以去看电视剧…… 这种盯着终端输出信息,手动删除编译中间文件的操作,需要进行两遍:make一次,make install一次。如果中间跑神了,make过程中出现了错误提示说容量不够导致make失败,那就惨了,需要重新多来一次……

最后make, make install成功后,写了一个Demo文件test_opencv.cpp,内容如下:

#include <opencv2/opencv.hpp>
#include <stdio.h>
#include <iostream>
#include <vector>

using namespace std;
using namespace cv;

int main(int argc, char* argv[])
{
    const char* imagename = "/root/Desktop/miska.jpg";
    Mat img = imread(imagename);

    if(img.empty())
    {
        fprintf(stderr, "Can not load image %s\n", imagename);
        return -1;
    }
    else
        printf("Read Image Success.\n");

    Mat imgGray;
    cvtColor(img, imgGray, CV_BGR2GRAY);

    const char* imgGrayName = "/root/Desktop/miska_gray.jpg";
    vector<int> params;
    params.push_back(CV_IMWRITE_JPEG_QUALITY);
    params.push_back(90);
    imwrite(imgGrayName, imgGray, params);

    if(imgGray.empty())
    {
        fprintf(stderr, "Can not save image %s\n", imgGrayName);
        return -1;
    }
    else
        printf("Save Image Gray Success.\n");

    imshow("Image", imgGray);
    waitKey();

    return 0;
}

然后在cpp文件所在目录下,输入指令如下:

arm-linux-gnueabihf-g++ `pkg-config --cflags --libs opencv` test_opencv.cpp -lpthread -lrt -o test_opencv_g++_show

然后就生成了test_opencv_g++_show的可执行文件。这时候输入指令:

./test_opencv_g++_show

便出现如图所示:
这里写图片描述

除了显示出图片之外,在桌面上还存储了相应的灰度图.jpg文件miska_gray.jpg。

这就是笔者愚蠢但有效的移植方法……

2. 错误情况总结与猜想

(1) error while loading shared libraries: libopencv_highgui.so.2.4

其实上面成功的内容并不是在make install之后直接就完成的。
笔者对test_opencv.cpp进行编译指令如下:

arm-linux-gnueabihf-g++ `pkg-config --cflags --libs opencv` test_opencv.cpp -lpthread -lrt -o test_opencv_g++_show

却出现如下错误提示:
error while loading shared libraries: libopencv_highgui.so.2.4
后来笔者参考了网上的资料,原来是笔者的OpenCV路径没有设置。
参考地址:
http://blog.csdn.net/gaobobo138968/article/details/24253703
http://blog.csdn.net/fangquan1980/article/details/49363173

首先,笔者在进行make install命令之前,设定的install路径为/usr/local/arm/opencv-install/,生成的库文件都是动态链接库。而在Linux系统中,文件/etc/ld.so.conf中记录着动态函数库所在目录。所以笔者需要在/etc/ld.so.conf中将路径/usr/local/arm/opencv-install/添加进去。
然后就需要执行指令:

ldconfig

这样就将/etc/ld.so.conf中的内容读入了高速缓存,同时/etc/ld.so.cache文件中开始记录数据。
重新用arm-linux-gnueabihf-g++编译Demo程序,就编译成功,且能成功运行了。

(2) file not recognized

之前笔者的OpenCV是交叉编译的,且交叉编译的过程已经在我之前的博客中《 Ubuntu 14.04 LTS下使用arm-linux-gcc交叉编译OpenCV 2.4.9》有过记录。
笔者把编译后的目录opencv-install放置在和PC机相同的路径(即/usr/local/arm/opencv-install/
之后使用arm-linux-gnueabihf-g++编译Demo程序,然而出现错误:
/usr/local/arm/opencv-install/lib/libopencv_calib3d.so: flie not recognized: File format not recognized
collect2: ld returned 1 exit status

也就是因为这个原因,笔者放弃了用PC机交叉编译……

网上查了查原因,有人出现这样的问题,但却是因为文件格式,或者是x86的32/64位系统版本,或者是直接就没有用arm-linux-gcc系列的编译器之类的原因,况且我用的也是arm平台的编译器(笔者在PC机端用的编译器是arm-none-linux-gcc-4.3.2,在BeagleBone Black板上的编译器是4.6.3版本的arm-linux-gnueabihf-gcc),虽然版本不同,但笔者认为在PC机上用的编译器应该是被BBB的编译器向下兼容的。

对于这种情况,笔者感觉只有两种操作可能解决:
1、用4.6.3版本的arm-linux-gnueabihf-gcc编译相关库;(其实也尝试过,但是在编译ffmpeg源码时貌似出了问题…… )
2、当时确实没有用过ldconfig命令,也可能是这个原因?……

(3) 使用错误的编译器

这个本来都不想回忆的,因为实在太低级失误了…… 笔者曾经用了gcc的编译器编译Demo程序,然而库文件是交叉编译的arm-linux-gcc版本,结果肯定是运行不了的…… 具体什么情况忘了,记着这个教训就好了……

二. 迅为i.MX6Q开发板编译总结

1. 编译成功方法

虽然交叉编译失败,但是ARM本机编译方面,相比起来迅为的ARM开发板比BBB简单的多了。毕竟i.MX6Q的CPU可以使用多核编译,而且eMMC容量也大得多,所以不需要盯着终端输出信息各种手动删除中间文件腾空间,只需要简单的cmake, make, make install,之后就可以编译运行了……
其他的基本可以参照BBB的成功范例。

2. 错误情况总结与猜想

i.MX6Q的系统是和PC机一样的Ubuntu,所以错误情况比较少,基本上还是可以参考BBB的总结……(原谅笔者的懒惰,一是因为错误情况少,二是因为时间稍微有点久远了……)

后记:

笔者真的是已经没有精力再专门重新编译了……所以只有在此处记录为博客,以后如果真有重新交叉编译的情况,再重新尝试。
希望个人的错误总结也可以有点价值吧。

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值