查看: 20483|回复: 79

[分享] 海思移植opencv+人脸检测+速度优化

    [复制链接]
发表于 2014-12-25 19:01:54 | 显示全部楼层 |阅读模式
本帖最后由 9crk 于 2014-12-25 22:32 编辑

1.确保ubuntu能上网

2.安装cmake
代码: 全选
sudo apt-get install cmake-gui

3.下载opencv2.4.9 Linux版源码,不要用最新的3.0.0
http://opencv.org/downloads.html

4.解压opencv源码
代码: 全选
unzip opencv-2.4.9.zip

5.创建一个build目录用于编译和一个output目录
用于存放编译完成后的海思平台的opencv:
代码: 全选
xlab@xlab-dev:~/zhouhua/opencv/opencv-2.4.9$ ls
3rdparty        LICENSE    apps   data  include    modules    samples
CMakeLists.txt  README.md  cmake  doc   index.rst  platforms
xlab@xlab-dev:~/zhouhua/opencv/opencv-2.4.9$ cd ..   
xlab@xlab-dev:~/zhouhua/opencv$ ls
build  opencv-2.4.9  opencv-2.4.9.zip  output
xlab@xlab-dev:~/zhouhua/opencv$ mkdir build
xlab@xlab-dev:~/zhouhua/opencv$ mkdir output

6.执行cmake-gui
代码: 全选
xlab@xlab-dev:~/zhouhua/opencv/opencv-2.4.9$ cmake-gui

点击Browse Source选择~/zhouhua/opencv/opencv-2.4.9
点击Browse Build选择~/zhouhua/opencv/build
然后点击Configure

此时出现的对话框选择最后一项:Specify options for cross-compiling
下一步
Operating System填写 arm-hisiv100nptl-linux
C填写arm-hisiv100nptl-linux-gcc
C++填写arm-hisiv100nptl-linux-g++

下一步,然后等待Configuration done
然后在出现的列表中修改CMAKE_INSTALL_PREFIX为~/zhouhua/opencv/output
然后点击Generate
等待Generation done
即可关闭cmake软件。

7.进入build目录执行make
代码: 全选
xlab@xlab-dev:~/zhouhua/opencv/build$ make

提示出错:
代码: 全选
../../lib/libopencv_core.so: undefined reference to `pthread_once'
../../lib/libopencv_core.so: undefined reference to `pthread_spin_lock'
../../lib/libopencv_core.so: undefined reference to `pthread_spin_unlock'
../../lib/libopencv_core.so: undefined reference to `pthread_spin_init'
../../lib/libopencv_core.so: undefined reference to `pthread_spin_trylock'
../../lib/libopencv_core.so: undefined reference to `pthread_spin_destroy'

修改CMakeCache.txt大约200行处
//Flags used by the linker.
CMAKE_EXE_LINKER_FLAGS:STRING= -lpthread -lrt
继续make
可能出现如下错误
代码: 全选
CMake Error at /home/xlab/zhouhua/opencv/opencv-2.4.9/cmake/cl2cpp.cmake:50 (string):
  string does not recognize sub-command MD5


make[2]: *** [modules/ocl/opencl_kernels.cpp] Error 1
make[1]: *** [modules/ocl/CMakeFiles/opencv_ocl.dir/all] Error 2
make: *** [all] Error 2

删除/home/xlab/zhouhua/opencv/opencv-2.4.9/cmake/cl2cpp.cmake的第50行的内容即可。
继续make
完成后执行make install
代码: 全选
xlab@xlab-dev:~/zhouhua/opencv/output$ ls
LICENSE  bin  include  lib  share


8.得到了include和lib目录就可以编写程序了,来试试最常用的人脸检测吧
编写如下代码
代码: 全选
/***********Author:9crk 2014-12-24*****************************/
#include "cv.h"
#include "highgui.h"
#include "stdio.h"
/******************for time mesurement*************************/
#include <sys/time.h>
struct timeval tpstart,tpend;
unsigned long timeuses;
void timeRec()
{
    gettimeofday(&tpstart,0);
}
int timeRep()
{
    gettimeofday(&tpend,0);
    timeuses=(tpend.tv_sec-tpstart.tv_sec)*1000000+tpend.tv_usec-tpstart.tv_usec;
    printf("use time: %uus\n",timeuses);
    return timeuses;
}
/********************end**************************************/

int main(int argc, char* argv[])
{
   IplImage* img = NULL;
   IplImage* cutImg = NULL;
   CvMemStorage* storage = cvCreateMemStorage(0);
   CvHaarClassifierCascade* cascade = (CvHaarClassifierCascade*)cvLoad("./haarcascade_frontalface_alt2.xml", 0, 0, 0);
   CvSeq* faces;
      
    img = cvLoadImage(argv[1], 0);
   timeRec();
    faces = cvHaarDetectObjects(img, cascade,  storage, 1.2, 2, 0, cvSize(25,25) );
    timeRep();
    if (faces->total == 0){
        printf("no face!\n");
    }
    cvSetImageROI(img, *((CvRect*)cvGetSeqElem( faces, 0)));
    cvSaveImage("face.bmp", img);   
    cvResetImageROI(img);
    printf("face detected! in face.bmp!\n");
}

为了方便,直接将库和头文件拷贝到编译器的目录下去
代码: 全选
xlab@xlab-dev:~/zhouhua/opencv/mytest$ sudo cp ../output/lib/* /opt/hisi-linux-nptl/arm-hisiv100-linux/arm-hisiv100-linux-uclibcgnueabi/lib/
xlab@xlab-dev:~/zhouhua/opencv/mytest$sudo cp ../output/include/* /opt/hisi-linux-nptl/arm-hisiv100-linux/arm-hisiv100-linux-uclibcgnueabi/include/ -r

然后编译:(由于版本比较高,用了opencv2的头文件,因此需要额外增加一个-I参数指定头文件目录)
代码: 全选
arm-hisiv100nptl-linux-g++ face.cpp -I/home/xlab/zhouhua/opencv/output/include/opencv -lopencv_highgui -lopencv_core -lopencv_imgproc -lpthread -lrt -lopencv_objdetect -o face

会提示一些warning,不用管。
编译成功,然后拷贝人脸分类器文件过来。
代码: 全选
xlab@xlab-dev:~/zhouhua/opencv/mytest$ cp ../output/share/OpenCV/haarcascades/haarcascade_frontalface_alt2.xml ./

再找个图片过来,我这里就用lena.jpg了。
然后nfs挂到开发板
到开发板端做软连接库到/lib目录下
代码: 全选
ln -s /mnt/nfs/zhouhua/opencv/output/lib/libopencv_imgproc.so /lib/libopencv_imgproc.so
ln -s /mnt/nfs/zhouhua/opencv/output/lib/libopencv_objdetect.so /lib/libopencv_objdetect.so
ln -s /mnt/nfs/zhouhua/opencv/output/lib/libopencv_highgui.so /lib/libopencv_highgui.so
ln -s /mnt/nfs/zhouhua/opencv/output/lib/libopencv_core.so /lib/libopencv_core.so

然后到face所在的nfs目录去执行即可:
# ./face lena.jpg
use time: 31532724us
face detected! in face.bmp!
由于参数没有优化,用了31秒才找到lena的脸。。


9.速度优化
先修改一下图片长、宽为之前的1/4试试
# ./face lena.jpg
smallImg w=128 h=128
use time: 1179871us
face detected! in face.bmp!
这次用了1.1秒

再修改检测参数
faces = cvHaarDetectObjects(smallImg, cascade,  storage, 1.5, 4, 0, cvSize(25,25) );
# ./face lena.jpg
smallImg w=128 h=128
use time: 578169us
face detected! in face.bmp!
这次用了578ms,检测出来的人脸大小是44x44的。

一般的应用应该够了,注意,此测试是在nfs下,如果拷贝到板子,速度会更快,当然,修改参数后的漏检率还需要测试。

下面贴出最后的代码(ps:之前的代码没有释放内存)

/***********Author:9crk 2014-12-24*****************************/
#include "cv.h"
#include "highgui.h"
#include "stdio.h"
/******************for time mesurement*************************/
#include <sys/time.h>
struct timeval tpstart,tpend;
unsigned long timeuses;
void timeRec()
{
    gettimeofday(&tpstart,0);
}
int timeRep()
{
    gettimeofday(&tpend,0);
    timeuses=(tpend.tv_sec-tpstart.tv_sec)*1000000+tpend.tv_usec-tpstart.tv_usec;
    printf("use time: %uus\n",timeuses);
    return timeuses;
}
/********************end**************************************/
int main(int argc, char* argv[])
{
   IplImage* img = NULL;
   IplImage* cutImg = NULL;

   CvMemStorage* storage = cvCreateMemStorage(0);
   CvHaarClassifierCascade* cascade = (CvHaarClassifierCascade*)cvLoad("./haarcascade_frontalface_alt2.xml", 0, 0, 0);
   CvSeq* faces;
    //加载图像
    img = cvLoadImage(argv[1], 0);
    //缩放到1/4大小
    IplImage *smallImg = cvCreateImage(cvSize(img->width/4, img->height/4), 8, img->nChannels);
    printf("smallImg w=%d h=%d\n", smallImg->width, smallImg->height);
    cvResize(img, smallImg);
    //检测并计时
    timeRec();
    faces = cvHaarDetectObjects(smallImg, cascade,  storage, 1.5, 4, 0, cvSize(25,25) );
    timeRep();
   
    if (faces->total == 0){
        printf("no face!\n");
    }
    //切取出头像
    cvSetImageROI(smallImg, *((CvRect*)cvGetSeqElem( faces, 0)));
    cvSaveImage("face.bmp", smallImg);   
    cvResetImageROI(smallImg);
    //释放内存
    cvReleaseImage(&img);
    cvReleaseImage(&smallImg);
    printf("face detected! in face.bmp!\n");
}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
楼主热帖
发表于 2015-1-29 21:33:27 | 显示全部楼层
9crk 发表于 2015-1-18 21:33
我用的也是uclibc
注意,编译命令是g++,一般地,如果明明加了那个库,也存在那个库(可以用arm-linux-o ...

大神能否私信一个QQ号?最近被安装opencv虐哭了,求解救
发表于 2014-12-25 19:19:36 | 显示全部楼层
回头参考移植到全志平台上去。
发表于 2014-12-29 21:46:09 | 显示全部楼层
本帖最后由 fox-cool 于 2014-12-29 21:47 编辑

不知道这个做到 人脸识别还有多少路? 作疑犯特征对比。
发表于 2015-1-16 14:29:11 | 显示全部楼层
还是找不到pthread_spin_init啊,看pthread.h里面pthread_spin_init相关函数都被注释掉了啊
 楼主| 发表于 2015-1-16 16:49:22 | 显示全部楼层
drafour 发表于 2015-1-16 14:29
还是找不到pthread_spin_init啊,看pthread.h里面pthread_spin_init相关函数都被注释掉了啊

lpthread是海思编译器自带的库,这个不需要头文件的,只需要库就行了,所以不用看头文件。是不是你没有加上 -lpthread ?
发表于 2015-1-18 12:33:18 | 显示全部楼层
9crk 发表于 2015-1-16 16:49
lpthread是海思编译器自带的库,这个不需要头文件的,只需要库就行了,所以不用看头文件。是不是你没有加 ...

加了啊,按照你上面说的加了。我使用的是3515的sdk。是ulibc的。估计你的海思sdk交叉编译器是glibc的吧
 楼主| 发表于 2015-1-18 21:33:05 | 显示全部楼层
drafour 发表于 2015-1-18 12:33
加了啊,按照你上面说的加了。我使用的是3515的sdk。是ulibc的。估计你的海思sdk交叉编译器是glibc的吧

我用的也是uclibc
注意,编译命令是g++,一般地,如果明明加了那个库,也存在那个库(可以用arm-linux-objdump -t查看那个库中是否有此函数),就是c++和c不兼容的问题。
发表于 2015-1-29 21:21:59 | 显示全部楼层
本帖最后由 zhuifengsn 于 2015-1-29 21:32 编辑

我按你这个教程来做,在make阶段出现了很多错误。楼主编译过程真的有这么顺利?
我测试过centos的虚拟机和ubuntu系统,使用的是hisiV100,GCC版本是3.4.3
这是opencv2.4.9的错误

这是2.3.1的错误,提示wchar.h找不到

这是编译2.2的错误,还是提示wchar找不到。我尝试过直接复制Linux /usr/include下的wchar.h到编译器的include目录下,还是会出错


最后,我用了2.0版本,没有用到cmake,最后在ubuntu下编译成功了。我在想,是不是因为海思的SDK用的GCC版本太旧了?怎么我一个版本都没成功编译?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
 楼主| 发表于 2015-1-29 23:53:28 | 显示全部楼层
zhuifengsn 发表于 2015-1-29 21:33
大神能否私信一个QQ号?最近被安装opencv虐哭了,求解救

把每一步,详细截图吧。每个版本都是可以编译成功的。错误信息用文字贴出来,方便复制。
发表于 2015-1-30 09:30:24 | 显示全部楼层
我用2.0移植海思3515成功了,但参数像你那么配置,在海思3515上单独运行图片人脸接侧,检测一张得要7,8秒。参数再调小一点就得20多秒了。没你说的那么快啊。我再研究一下移植一下2.4.9的,
发表于 2015-1-30 09:46:43 | 显示全部楼层
9crk 发表于 2015-1-18 21:33
我用的也是uclibc
注意,编译命令是g++,一般地,如果明明加了那个库,也存在那个库(可以用arm-linux-o ...

2.4.9还是编不过去。3515的编译器库里面根本就没有这几个函数
 楼主| 发表于 2015-1-30 13:03:10 | 显示全部楼层
drafour 发表于 2015-1-30 09:46
2.4.9还是编不过去。3515的编译器库里面根本就没有这几个函数

这几个函数应该是写多线程函数很常用的吧。。那你用3515编译器写多线程的时候,怎么链接的lpthread ?
 楼主| 发表于 2015-1-30 13:06:53 | 显示全部楼层
drafour 发表于 2015-1-30 09:30
我用2.0移植海思3515成功了,但参数像你那么配置,在海思3515上单独运行图片人脸接侧,检测一张得要7,8秒 ...

这个跟版本关系应该不大。我的代码只是做一个优化的思路,通过缩小图片、增加步进检测倍数等方法。具体的时间不好说,我用的是3518。
发表于 2015-1-30 13:48:44 | 显示全部楼层
9crk 发表于 2015-1-30 13:03
这几个函数应该是写多线程函数很常用的吧。。那你用3515编译器写多线程的时候,怎么链接的lpthread ?

makefile里连接lpthread的。我的程序用不上pthread_spin一系列函数。另外我把2.4.9里面pthread_spin相关函数注释掉,还有其他很多非lpthread的编译错误。可能是arm-hismall-linux-g++和你用的arm-hisiv100nptl-linux-g++差别大吧
您需要登录后才可以回帖 登录 | 注册

本版积分规则

© 2008-2017 当前位置 易百纳技术社区论坛 返回 易百纳技术社区 ( 苏ICP备14036084 )   Powered by Discuz! X3.1
快速回复 返回顶部 返回列表