zynq linux opencv效率,【NEU2012参赛手记(三)】ZYNQ平台OPENCV的移植(2)

接着上个博客,这次说说我本周的重点,就像标题说的,我在PC的QT上交叉编译了OPENCV,我的参考是官网上关于交叉编译的教程Cross compilation for ARM based Linux 。我照着弄,最后可以跑图片的算法了,但是问题出现了,官网的交叉编译是不带额外的库的,比如GTK就没有被交叉编译,上个博客中lena的例子的读显示图片就是基于GTK的,所以在ZYNQ上就会出现找不到库的错误。GTK库的交叉编译网上资料有点少,也没太看懂。我用了本地编译的方法解决了GTK的问题,实现了OPENCV在ZYNQ上的完整移植。下面我会一一详述。

1.OPENCV的交叉编译

这里我用cmake-gui生成配置文件makefile,配置和PC编译时类似,由官网的教程知道,在/opencv-2.4.5/platforms/linux下官方已经给我们写好了一个cmake的配置文件arm-gnueabi.toolchain.cmake,由于我armGCC的版本是4.7,所以需要在里面改下版本。

注意这里的默认是arm-linux-gnueabihf-gcc,g++的,若不是需要改动。

好了,终端输入

cmake-gui

这次选择第三项,因为官方已经给我们提供toolchain file-----arm-gnueabi.toolchain.cmake,下一步就是configure,generate生成makefile,然后make。这样make,我遇到了两个错误,都是关于python的,上图吧。

如果你是64位系统还会遇到下面的问题,可以通过在相应代码加入define解决,然后遇到上面的问题。

应该是交叉编译的问题,就是没有ARM的libpython2.7.so。另外我提一句,如果你没有像上一个博客中说的执行

apt-get insall python-dev,你就不会遇到这个问题,因为这样opencv的cmake检测不到python,不会对其编译就不会产生错误。

没方法了,交叉编译python不会,所以我选择了不编译python,这样生成的包对我们没太大的影响,因为我们也用不到python啊,但是我还是很不爽啊,希望高人指点。下面是我的配置,看不见的没变,就是无奈地勾掉了python。

这样,make,make install(cmake下prefix选项设置安装路径)。

应该没有问题了,想到再写吧,这样交叉编译OPENCV的库就生成了,会生成四个文件夹,分别是

bin、include、lib、share,是不是很熟悉啊(文件夹名),上个博客就想说,/root/opencv/opencv_arm

是我的安装目录(make install后会复制过来),其实编译pc库后,make install也会产生这四个文件夹,只不过

/usr/local 下就有这四个文件夹,所以,直接把内容放到相应的文件里了。这种方式,提醒我默认路径的安装,原来总是不知道apt-get install装到哪里去了,这是个很好的说明。

不扯了,回到OPENCV,这里生成的库除了GTK(其他的不知道,GTK比较明显,因为不能显示图片了),其他的还是可以用的。

2.QT上对OPENCV进行交叉编译

像QT编译PC上OPENCV一样,仍然需要库和头文件,但是需要重新指定,因为用到的库要能够交叉编译。QT自己的交叉编译需要指定交叉编译的QMAKE和ARM的GCC,这里我说下我对qmake的理解,qmake是一个可执行文件,通过执行qmake会生成一个qt的工程文件(.pro),还有会按照该qmake的配置生成makefile,交叉编译时就需要交叉编译的qmake(与PC的qmake名字相同,但是两个文件),该qmake会调用交叉编译后的qt库了。我们现在做的就是把交叉编译后OPENCV的库和头文件,放到交叉的qmake.conf中,这样在调用交叉编译的qmake时就会自动加载交叉的OPENCV库了。

在/usr/local/Trolltech/QtEmbedded-4.8.4-arm/mkspecs/qws/linux-arm-gnueabihf-g++/qmake.conf做修改。

INCLUDEPATH += /root/opencv/opencv_arm/include \

/root/opencv/opencv_arm/include/opencv \

/root/opencv/opencv_arm/include/opencv2

LIBS += /root/opencv/opencv_arm/lib/libopencv_highgui.so \

/root/opencv/opencv_arm/lib/libopencv_core.so \

/root/opencv/opencv_arm/lib/libopencv_imgproc.so \

/root/opencv/opencv_arm/lib/*.so

注意与上篇PC编译时的博客不同啊。位置(qws/linux-arm-gnueabihf-g++)是在Qtcreator中设的,不会设的话,就在上个文件里的default里改。

这样其余的与QT的交叉编译的过程相同了,相当于你可以在QT中调用OPENCV的函数了。不能跑GTK,例子就不举了。注意,这样设可以编译带GTK的代码,就是跑不了。

3.ZYNQ板上的本地编译

为了可以在ZYNQ上跑GTK,查了查文档,都说需要交叉编译GTK源码,又找了找,没找到相应的文档,请大神们不吝赐教。

这里我说说我的方法,就是本地编译,听起来很陌生是不,对于嵌入式系统,由于内存的大小、CPU的速度等问题,没有办法将代码的编译以及生成可执行文件放在板上进行,所以我们需要有更大的硬盘、更快的CPU来编译,在我们本地进行编译,比如我们PC的ubuntu12.10 64位(宿主机),属于x86-64体系结构,我们的ZYNQ(目标板)是ARMV7体系结构,不同体系之间的编译就是交叉编译。那我们可不可以将编译移到ZYNQ上呢,是不是可以克服上面提到的困难呢。

当我看到那熟悉的ubuntu的时候,我就认定“你行的!”。实验证明,ZYNQ(cortex A9 ,500M内存,相当于4G的硬盘),可以编译opencv,照着在PC上编译OPENCV的步骤(把它当做PC),上篇博客在ZYNQ上走了一遍,花了3个小时,终于搞定了。本地编译最大的优势就是不用配复杂的路径以及config文件了(交叉编译时我认为最大的问题也在于./config 后的选项,没文档就不会选)。真爽啊,除了慢一点,一点错都没有,并且编译出了我梦寐以求的GTK库(我现在还不知道它在哪,可能编译进OPENCV的某个so了吧),其实我们就是要这些so啊。这回好,库都不用拷贝过去了,就在板上。编译的时间还是可以容忍的,就是容量没用了(这个opencv编译后占1.7G),看来还得换个SD卡啊。

下面是本地生成的库的位置。

先跑个上个博客中lena的例子,代码以前的博客有。

最后给大家一个QT,OPENCV共同应用的例子,就是用QT做界面然后打开关闭图片。

新建一个GUI application,往上面拖两个按钮就行了,不知道怎么传附件,之间粘了。

界面如下图:

这个是main.cpp

#include "mainwindow.h"

#include

int main(int argc, char *argv[])

{

QApplication a(argc, argv);

MainWindow w;

w.show();

return a.exec();

}

mainwindows.cpp

#include "mainwindow.h"

#include "ui_mainwindow.h"

#include

#include

#include

#include

#include

#include

#include

using namespace cv;

MainWindow::MainWindow(QWidget *parent) :

QMainWindow(parent),

ui(new Ui::MainWindow)

{

ui->setupUi(this);

}

MainWindow::~MainWindow()

{

delete ui;

}

void MainWindow::on_pushButton_clicked()

{

//第3个参数表示查找文件时从哪个目录开始,如果为"."的话,表示从该工程目录开始查找,最后那个参数的过滤器的名字之间

//要用空格,否则识别不出来

QString img_name = QFileDialog::getOpenFileName( this, tr("Open Image"), ".",tr("Image Files(*.png *.jpg *.jpeg *.bmp)"));

//toAscii()返回8位描述的string,为QByteArray,data()表示返回QByteArray的指针,QByteArray为字节指针

// Mat src = imread(img_name.toAscii().data() );

Mat src = imread(img_name.toLatin1().data() );

cvtColor( src, src, CV_BGR2RGB );

QImage img = QImage( (const unsigned char*)(src.data), src.cols, src.rows, QImage::Format_RGB888 );

// namedWindow( "Image_Show", WINDOW_AUTOSIZE );

// imshow( "Image_Show", src );

ui->label->setPixmap( QPixmap::fromImage(img) );

// ui->label->resize( ui->label->pixmap()->size() );

}

void MainWindow::on_pushButton_2_clicked()

{

close();

}

mainwindows.h

#ifndef MAINWINDOW_H

#define MAINWINDOW_H

#include

namespace Ui {

class MainWindow;

}

class MainWindow : public QMainWindow

{

Q_OBJECT

public:

explicit MainWindow(QWidget *parent = 0);

~MainWindow();

private slots:

void on_pushButton_clicked();

void on_pushButton_2_clicked();

private:

Ui::MainWindow *ui;

};

#endif // MAINWINDOW_H

代码就这些了,这个例子是我网上找的,谢谢作者了。

编译运行,结果如下图。

好了,经过三篇博客,这个星期的事就说完了,如果有进展下个星期见吧。

你可能感兴趣的:(zynq,linux,opencv效率)