ARM交叉编译OpenCV错误总结

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 条评论
登录 后参与评论

相关文章

来自专栏数据和云

【视频】In Memory的内部结构和实现机制

小编寄语 罗马不是一日建成的。新特性5分钟系列视频,带你循序渐进学习Oracle12.2的最新特性,相约成长的路上,不见不散! { 本期话题 } In ...

3196
来自专栏Brian

Linux网络工具之Ping命令

---- Ping用法 之前一直在用Ping,再仔细深入之后才发现自己只是了解皮毛。下面我把一些Ping的常用用法都记录下来,对于我来说今天又学了一个”神技”,...

3307
来自专栏Linyb极客之路

灰度发布方案

灰度发布(又名金丝雀发布)是指在黑与白之间,能够平滑过渡的一种发布方式。在其上可以进行A/B testing,即让一部分用户继续用产品特性A,一部分用户开始用产...

6972
来自专栏coding

swoole框架-swoft实现程圣母与云天明对话功能启动ws服务创建http服务的聊天控制器创建视图文件创建ws控制器结果演示

当万有引力号启动广播按钮,向宇宙发送三体星的坐标时,地球已经失去了任何侵略价值。三体人将所有在地球的资源全部撤走,但在临别时,安排了程圣母与云天明的远程会话。接...

1322
来自专栏企鹅号快讯

可编程逻辑控制器PLC

PLC代表可编程逻辑控制器。它们基本上用于控制工业中的自动化系统。它们是最先进和最简单的控制系统之一,现在正在大规模地取代硬连线逻辑继电器。 ? 在详细介绍PL...

2197
来自专栏企鹅号快讯

如何选择TensorFlow安装环境

许多软件都会使用一些库和独立维护的软件包。对于开发者而言,这是一件好事,因为这种做法有利于代码复用,而且他们 可专注于创建新的功能,而无需重复造轮。然而,这种做...

3625
来自专栏瓜大三哥

块RAM的Verilog HDL调用

(1)单端口RAM 模式 单端口RAM的模型如图所示,只有一个时钟源CLK,WE为写使能信号,EN为单口RAM使能信号,SSR为清零信号,ADDR为地址信号,D...

3458
来自专栏蓝天

提高 Linux 上 socket 性能

在开发 socket 应用程序时,首要任务通常是确保可靠性并满足一些特定的需求。利用本文中给出的 4 个提示,您就可以从头开始为实现最佳性能来设计并开发 soc...

983
来自专栏SDNLAB

【连载-5】数据中心网络虚拟化 网关及服务接入

网络虚拟化网关技术 虚拟网络中的虚拟机与外部网络通信的需求催生了网络虚拟化中网关(Gateway)技术的出现。现有虚拟化平台网关产品有:IBM SDN VE G...

3408
来自专栏张善友的专栏

利用 Microsoft StreamInsight 控制较大数据流

原文地址:http://msdn.microsoft.com/zh-cn/magazine/hh205648.aspx 下载代码示例 生产线的产量下降后,将...

2046

扫码关注云+社区