Skip to content

ARM交叉编译OpenCV错误总结 #17

Description

@upcAutoLang

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的总结……(原谅笔者的懒惰,一是因为错误情况少,二是因为时间稍微有点久远了……)

后记:

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions