移植OpenCV 3.1.0+FFMPEG到OMAPL138LCDK(交叉编译)

前言

这是我第一篇公开的文章,也是我第一次尝试交叉编译的成果,可能过程有不足,文章也可能写得不全面,请多见谅。不足请指出,我每天都会看的。希望大家多多交流学习。

环境与相关准备工作

主机平台:Ubuntu 16.04(64 bit)
硬件平台:TI公司的OMAPL138LCDK
交叉编译工具链:arm-linux-gnueabi-gcc-5(及其g++)
OpenCV源码:3.1.0版本(加contrib也可)及官网列出的依赖包
FFMPEG:2.8.17
CMAKE:cmake-qt-gui
注:

  1. 工具链可到linaro网站下载,也可apt-get install下载。TI的产品,官方都有提供对应的工具链,我图方便直接用apt-get install下载。交叉编译工具链应对应硬件平台arm芯片的架构。本平台为ARM9处理器,为V5架构,属于soft float类型。其他架构有对应的hf类型和64bit的工具链。
  2. OpenCV版本选太新,编译器有可能不支持(一开始直接上手4.5.1的教训),最好选择编译器发布日期比OpenCV版本发布晚的吧。已经测试过,最高支持版本3.4.1。
  3. FFMPEG版本,我是自己在Ubuntu上下了一个是2.8.17,因此采用2.8.17,其他尚未尝试。同时本次仅采取FFMPEG一个包,其他依赖包尚未加入,后续再添加功能。

编译FFMPEG

终端进入源码目录利用

#若需要xvid和x264
#编译x264
CC=arm-linux-gnueabi-gcc-5 ./configure --enable-shared \
 --host=arm-linux-gnueabi --disable-asm \
 --prefix=/usr/local/opencv_ffmpeg_arm
make 
sudo make install
#编译xvid
#进入xvid源码目录下的build/generic目录
CC=arm-linux-gnueabi-gcc-5 ./configure \
--prefix=/usr/local/opencv_ffmpeg_arm --host=arm-linux-gnueabi \
--disable-assembly

#编译ffmpeg
./configure --help #查看所有参数  以下为本人配置参数

./configure --prefix=/usr/local/opencv_ffmpeg_arm \
#opencv和ffmpeg的生成文件都放一个文件夹,方便后续工作
--enable-gpl --enable-nonfree --disable-static --enable-shared \
#建议都是用动态库 一开始觉得用静态库可以直接一个可执行程序拉到板子上方便
#实际上到后面编译应用程序时会一直失败,这是由于opencv中依赖很复杂
#除非你自己去修改后面配置文件,根据依赖关系调整静态库链接顺序吧
--enable-avresample #默认不生成的,但编译opencv需要这个
--arch=arm #直接写arm configure文件都可以识别到armv5架构,其他未知
--cross-prefix=arm-linux-gnueabi- --enable-cross-compile \
--target-os=linux --cc=arm-linux-gnueabi-gcc-5 
#ffmpeg是c代码,不用c++编译器
#曾出现过找不到nm的情况,后用--nm=arm-linux-gnueabi-nm解决
--disable-asm #交叉编译可能不支持某些代码的汇编优化
#以下为xvid和x264需要项
--enable-libx264 --enable-libxvid --disable-stripping \
--extra-cflags=-I/usr/local/opencv_ffmpeg_arm/include
--extra-ldflags=-L/usr/local/opencv_ffmpeg_arm/lib

FFMPEG的编译工作会比OpenCV顺利些。等一会configure,弹出很多配置信息后可下一步。有可能会有一些警告,除了上述关于nm的警告情况导致失败,别的警告都编译成功,因此我也没留意。

make #也可make -j2 数字代表调用cpu核数还是线程数没详细研究,反正快点

#编译完成后
sudo make install #生成文件会安装到prefix的目录下

编译OpenCV

准备工作

进入到/usr/local/opencv_ffmpeg_arm/lib目录下,执行以下命令

sudo ln -s ./libavcodec.so ./libavcodec-ffmpeg.so
sudo ln -s  ./libavformat.so ./libavformat-ffmpeg.so
sudo ln -s ./libavutil.so ./libavutil-ffmpeg.so
sudo ln -s ./libavresample.so ./libavresample-ffmpeg.so
sudo ln -s ./libswscale.so ./libswscale-ffmpeg.so

这一步是我搞了很多天才弄懂的操作,到csdn、opencv论坛和stackoverflow找了很多帖子也没有人提到,自己也发起帖子(虽然发布这篇文章时仍然没人回我)。

编译opencv时,链接器一直报错找不到以上带有"-ffmpeg"的库。但其实在安装opencv官网列出的依赖包后,这些库是连带安装在usr/lib/x86_64-linux-gnu目录下。尝试过复制这些库到查找路径下,opencv编译成功了,但是编译应用程序时会报错(文件格式不匹配)。

通过以下命令可了解到那些库都是基于x86或i386架构的,并不符合我们arm架构。同时以上也是64位库,我的硬件平台是32位。
objdump -f 文件名

但无论是ffmpeg官网还是别的地方,都没有提供这种带有"-ffmpeg"的库下载,可是你到usr/lib/x86_64-linux-gnu目录ls一下,会发现其实"-ffmpeg"库其实只是软链接文件,链接的都是如libavformat.so*(*代表版本号)的文件。这些文件恰恰就是我们编译ffmpeg所生成的文件。

因此就有了以上的建立软链接工作。

cmake-gui配置

终端输入cmake-gui打开cmake配置工具

  1. 分别指定源码目录和build的目录,两者不要相同。
  2. 点击configure。
  3. 选择Specify options for cross-compiling。
    在这里插入图片描述
    填好操作系统、处理器、C和C++编译器和编译器的目录。
    编译和链接时会采用编译器目录内对应文件和库。其实如果ffmpeg的生成文件目录指定为编译器目录的话,功夫会少一点,但就是不好移植。

在这里插入图片描述
得到这样的界面,这时我们根据需要选择组件,然后一直点configure,直到全部红色项变为白色即配置完毕。以下介绍我的配置项。

cmake-gui配置项

1.CMAKE_INSTALL_PREFIX
改为/usr/local/opencv_ffmpeg_arm

2.BUILD_SHARED_LIBS
与上面选择生成ffmpeg动态库同理

3.OPENCV_EXTRA_MODULES_PATH
contrib文件夹中modules文件夹的位置。
/home/rookie/opencv_contrib-3.1.0/modules

4.所有CXX_FLAGS
这里要加入-std=c++11,不然编译时会出现"exception_ptr"未定义的问题。是一些头文件包含问题,进入过相关.h文件中你会发现有个宏定义决定是否包含,一直不通过(我还试过直接包含…)。在stackoverflow上看到是与c++11相关,同时也有可能是编译器不支持对应一些代码的原因,因此才选择3.1.0版本(牛人还是多) 。至于编译器和板子是否支持c++11,可在网上找找测试代码,是通过输出c++11发布年份判断的。

还有-I/usr/local/opencv_ffmpeg_arm/include
和-L/usr/local/opencv_ffmpeg_arm/lib 。这个参数也要加在所有C_FLAGS上。编译器会去找对应头文件和以上"-ffmpeg"的库。

在所有C/CXX_FLAGS上加参数,我就是图方便。至于LINKER_FLAGS要不要加上库的路径,我忘了。可以试试。

5.组件配置
我是想用来处理图片、视频和摄像头。所以与图片格式相关选了,FFMPEG,然后WITH_V4L。(V4L暂时没有摄像头,测试不了)不过我发现选了FFMPEG和V4L,就编译失败。留下其中任何一个就能成功,目前就只留了FFMPEG版本OpenCV。同时选FFMPEG和V4L的话,会出现一个"impossible constraint in asm"这样的错误,目前我还无法解决,希望可以指教。应该可以编译一个带FFMEPG的,一个带V4L的,有摄像头后试试。
在这里插入图片描述
在这里插入图片描述
WITH_PTHREADS_PF,看官网描述是对应一些算法能加速处理。

关于BUILD_opencv_*这些选项,可以先去官网看看哪些是你需要的,然后进行选择。要留意configure后出现的信息,会出现一些not found,或者Build_opencv无法生成(因为你没选它所依赖的build_opencv项,根据警告选上就可以解决了)。信息中那一栏应该像下图。在这里插入图片描述
在这里插入图片描述
比如这个not found问题,要是C_FLAGS部分没指定include目录就会出现。

编译

同样

makemake -j2

sudo make install

/usr/local/opencv_ffmpeg_arm目录复制到/usr/local/下

测试

CMakeLists.txt

程序都是通过cmake生成Makefile来生成可执行文件的。
因此还要写CMakeLists.txt文件。

  1 set(tool_path "/usr/bin")
  2 set(CMAKE_C_COMPILER ${tool_path}/arm-linux-gnueabi-gcc-5)
  3 set(CMAKE_CXX_COMPILER ${tool_path}/arm-linux-gnueabi-g++-5)
  4 set(CMAKE_CXX_FLAGS "-std=c++11")
  5 #指定编译器
  6 
  7 
  8 
  9 #以下是参考OpenCV官网的
 10 cmake_minimum_required(VERSION 2.8)
 11 project( video_frame )  #跟随工程改名
 12 find_package(OpenCV REQUIRED)
 13 include_directories( ${OpenCV_INCLUDE_DIRS} )
 #link这一行一定要加 官网是没有的 不然找不到所需要的库
 14 link_directories("/usr/local/opencv_ffmpeg_arm/lib") 
 #add_executable(可执行文件名 源文件名)
 15 add_executable( video_frame video_frame.cpp )  
 #target_link_libraries( 可执行文件名 ${OpenCV_LIBS} )
 16 target_link_libraries( video_frame ${OpenCV_LIBS} )

在应用程序目录下写好CMakeLists.txt文件后

cmake .  #有个点跟在cmake后 输出信息应该是交叉编译工具链

make

file 可执行文件 #看看是不是32bit的ARM架构

图片处理

选了WITH_JPEG,才可处理".jpeg"文件。能生成变灰的图就成功。

  1 #include <opencv2/opencv.hpp>
  2 
  3 using namespace cv;
  4 
  5 int main(int argc,char** argv)
  6 {
  7         char* imageName=argv[1];
  8         Mat image;
  9         printf("imageName:%s\n",imageName);
 10         image=imread(imageName,1);
 11         if(!image.data){
 12                 printf("read error\n");
 13                 return -1;
 14         }
 15 
 16         Mat gray_image;
 17         cvtColor(image,gray_image,COLOR_BGR2GRAY);
 18         imwrite("./gray.jpeg",gray_image);
 19 
 20         return 0;
 21 }

读取视频

检验我们的FFMPEG。能生成视频中第一帧的图片就成功。

  1 #include <iostream>
  2 #include <string>
  3 #include <iomanip>
  4 #include <sstream>
  5 
  6 #include <opencv2/core/core.hpp>
  7 #include <opencv2/imgproc/imgproc.hpp>
  8 #include <opencv2/videoio/videoio.hpp>
  9 #include <opencv2/highgui/highgui.hpp>
 10 #include <opencv2/opencv.hpp>
 11 
 12 using namespace std;
 13 using namespace cv;
 14 
 15 int main(int argc,char** argv)
 16 {
 17         if(argc != 2){
 18                 cout<<"parameter not enough"<<endl;
 19                 return -1;
 20         }
 21         const string video_name=argv[1];
 22         VideoCapture video(video_name);
 23       

总结

  1. 在实验和测试前,应先写清楚方案并记录实验结果,不然会做很多重复的无用功。
  2. 沉下心去看文档,练好英语。
  3. 搜索资料平台要多渠道,csdn、官方论坛、stackoverflow、google、bing,对百度凉了心。
  4. 如果不是很喜欢嵌入式,就不要选嵌入式。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值