OpenCV是一个基于(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。

pcDuino是一款兼容Arduino接口的mini pc,A8架构1Ghz的CPU,计算能力不俗,用来跑OpenCV刚刚好。这里就用他们实现一个可以跟随人脸移动的摄像头。

在优酷里面有一个视频: OpenCV+pcDuino人脸跟踪
硬件清单
1、pcDuino一块;
2、传感器扩展板一块;
3、摄像头云台一个;
4、摄像头一个.

一、编译安装OpenCV:
1、先安装各种依赖库,根据你的环境不同,可能出现缺失,全都补上,以求OpenCV一次编译通过(因为编译过程耗时将近3小时)
sudo apt-get install build-essential libgtk2.0-dev libavcodec-dev
libavformat-dev libjpeg62-dev libtiff4-dev cmake libswscale-dev
libjasper-dev

2、下载解压OpenCV包,用cmake工具生成编译所需的信息,第四句说明编译成release版本,安装目录是/usr/local

cd ~/opencv
mkdir release
cd release
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ..

3、开始编译
make
make install

关于OpenCV的安装大家可以参照官方文档:http://docs.opencv.org/doc/tutorials/introduction/linux_install/linux_install.html#linux-installation

二、编译安装c_enviroment:

1、c_enviroment是Pcduino控制硬件I/O的库,从开头软件环境处给的链接下载c_enviroment的zip包,解压编译
cd c_enviroment
make
编译完后,我们可以进入output/test目录,测试一下点亮led的sample

三、编译安装Qt:

为了方便开发,我这里用了Qt creator作为IDE
1、安装Qt creator
sudo apt-get install qtcreator
现在已经可以在programing里运行Qt creator了,但是这时候它还不能用,还需要安装Qt library

2、安装Qt library
通过开头软件环境中的链接下载嵌入式版Qt library:Qt libraries 4.8.5 for embedded Linux
具体安装过程大家可以参照这个帖子,这里就不赘述了:
http://www.pcduino.org/forum.php?mod=viewthread&tid=21&highlight=%E5%9C%A8pcduino%E5%AE%89%E8%A3%85Qt

经过漫长的编译安装,Qt终于完成,至此环境算是搭好一大半了。

新建一个名为face_tracking_camera的C++项目,编辑face_tracking_camera.pro文件,加入OpenCV和
c_enviroment的源文件、头文件和类库路径,我这里OpenCV安装在/usr/local/,c_enviroment安装在/home
/ubuntu/c_enviroment/
expand source

到这里,环境就全部搭好了。

代码

#include <opencv2/opencv.hpp>

#include <Arduino.h>

#include <wiring_private.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <assert.h>

#include <math.h>

#include <float.h>

#include <limits.h>

#include <time.h>

#include <ctype.h>

#include <sys/time.h>

#include <signal.h>

//用于人脸识别的分类器特征库文件路径

constchar* cascade_name =”/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml”;

//定义了X轴(横向摆动),Y轴(纵向摆动)舵机的中心点

staticintcenterlevelX = ;

staticintcenterlevelY = ;

//定义了舵机的频率

constintfrequncy = ;

//用一个整数存储目前舵机摆动方向

staticintturningRight = ;

//函数的签名列表

voiddetect_and_draw( IplImage* image );

voidstart_pulse(intpwm_id,intfreq,intvalue);

voidsigroutine(intdunno);

voidreset();

longgetCurrentTime();

longstartTime;

longendTime;

//led指示灯pin脚

intpin_led = ;

//为OpenCV申请一块用于计算的内存

staticCvMemStorage* storage = ;

//声明一个haar分类器

staticCvHaarClassifierCascade* cascade = ;

voidsetup(){

//定义指示灯针脚为输出

pinMode(pin_led,OUTPUT);

//复位云台舵机

reset();

//监听中断信号

signal(SIGINT,sigroutine);

//建立一个名为result的窗口

cvNamedWindow(“result”,  );

//打开摄像头

CvCapture* capture = cvCaptureFromCAM(-);

//声明两个opencv图像类型

IplImage *img;

IplImage *newImg;

//加载分类器

cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, , ,  );

//检查分类器加载异常

if( !cascade ){

fprintf( stderr,”ERROR: Could not load classifier cascade\n”);

}

//定位内存块

storage = cvCreateMemStorage();

while() {

//由于pcduino的计算能力有限,为了保证帧率,把从摄像头采集来的画面缩小1/2

newImg = cvQueryFrame( capture );

if( !newImg )break;

img = cvCreateImage(cvSize(newImg->width/, newImg->height/), newImg->depth, newImg->nChannels);

cvResize(newImg, img);

//翻转图像

cvFlip(img, img, );

//调用识别和绘制图像的函数

detect_and_draw(img);

//释放图像使用的内存

cvReleaseImage(&img);

//监听esc键

intc = cvWaitKey();

if( c ==  )break;

}

//释放摄像头

cvReleaseCapture( &capture );

//销毁窗口

cvDestroyWindow(“result”);

}

voiddetect_and_draw( IplImage* img ){

startTime = getCurrentTime();

//清空使用过的内存空间

cvClearMemStorage( storage );

intscale = ;

inti;

//声明一个中心点存储识别出来的人脸位置

CvPoint ptcenter;

//人脸识别

if( cascade ){

//逐帧检测人脸

CvSeq* faces = cvHaarDetectObjects( img, cascade, storage,

1.1, , CV_HAAR_DO_CANNY_PRUNING,

cvSize(, ));

//如果检测到多张脸,遍历取出

for( i = ; i < (faces ? faces->total : ); i++ ){

//创建人脸矩形

CvRect* r = (CvRect*)cvGetSeqElem( faces, i );

//换算出人脸矩形的中心点

ptcenter.x = (r->x+(r->width/))*scale;

ptcenter.y = (r->y+(r->height/))*scale;

//绘制一个圆形标识出人脸的位置

cvCircle(img, ptcenter, (r->width+r->height)/, CV_RGB(,,), , ,  );

}

}

//显示图像

cvShowImage(“result”, img );

//计算帧率

endTime = getCurrentTime();

longtime= endTime-startTime;

intframerate = /time;

//检查中心点是否为空

if(ptcenter.x && ptcenter.y){

//std::cout<<”center_point:(“<<ptcenter.x<<”,”<<ptcenter.y<<”)\tframe_rate:”<<framerate<<”\n”<<std::endl;

//std::cout<<”x:”<<(ptcenter.x-img->width/2)<<”\ty:”<<(ptcenter.y-img->height/2)<<std::endl;

//向led指示灯引脚输出低电平,熄灭指示灯

digitalWrite(pin_led,LOW);

//驱动摄像头移动到人脸中心位置

centerlevelX += (ptcenter.x-img->width/)/*;

if(centerlevelX <=  && centerlevelX >= )start_pulse(,frequncy,centerlevelX);

centerlevelY -= (ptcenter.y-img->height/)/;

if(centerlevelY <=  && centerlevelY >= )start_pulse(,frequncy,centerlevelY);

//显示修正的X和Y轴幅度和帧率

std::cout<<”X:”<<centerlevelX<<”\tY:”<<centerlevelY<<”\tFrameRate:”<<framerate<<std::endl;

}else{

printf(“no face is detected in the image\n”);

//指示灯亮起

digitalWrite(pin_led,HIGH);

//如果没有检测到人脸则左右摇摆摄像头

if(centerlevelX <=  && turningRight == ){

start_pulse(,frequncy,centerlevelX+=);

if(centerlevelX > )turningRight = ;

//std::cout<<centerlevelX<<std::endl;

}

if(centerlevelX >=  && turningRight == ){

start_pulse(,frequncy,centerlevelX-=);

if(centerlevelX < )turningRight =;

//std::cout<<centerlevelX<<std::endl;

}

}

//防止摄像头下移过度

if(centerlevelY < ) centerlevelY = ;

}

//复位函数,调整舵机X、Y轴到中心位置

voidreset(){

delay();

start_pulse(,frequncy,);

start_pulse(,frequncy,);

delay();

}

longgetCurrentTime(){

structtimeval tv;

gettimeofday(&tv,NULL);

longtime=  tv.tv_sec *  + tv.tv_usec / ;

returntime;

}

//舵机驱动函数

voidstart_pulse(intpwm_id,intfreq,intvalue){

intstep = ;

step = pwmfreq_set(pwm_id, freq);

//printf(“PWM%d set freq %d and valid duty cycle range [0, %d]\n”, pwm_id, freq, step);

if(step > ){

//printf(“PWM%d test with duty cycle %d\n”, pwm_id, value);

analogWrite(pwm_id, value);

delay();

}

}

//signal回调函数,监听中断信号,做一些状态复位工作

voidsigroutine(intdunno) {

switch(dunno) {

case2:

printf(“Get a signal – SIGINT \n”);

reset();

analogWrite(,);

analogWrite(,);

digitalWrite(pin_led,LOW);

exit();

break;

}

}

voidloop(){} 

移植opencv到pcDuino的更多相关文章

  1. zedboard上移植OPENCV库

    zedboard上移植OPENCV库 之前做了很多移植OPENCV库的工作,但是需要包含的各种库,需要交叉编译,X264 ,JPGE ,FFMPGE等等 注意:在<嵌入式系统软硬件协同设计实战指 ...

  2. [OpenCV][ARM9下移植OpenCV]

    [OpenCV][ARM9下移植OpenCV]   安装环境 宿主机: Red Hat Enterprise Linux Server 6.3 开发板: mini2440 相关软件: cmake-3. ...

  3. zedboard开发板上移植opencv代码(立体匹配)

    前言 公司要做立体匹配相关的项目,已有matlab和c++版本,可是不能做到实时显示立体信息,想要硬件实现实时,无奈本渣也是个硬件的新手,先按照实验室lyq同学的思路在zedboard开发板的纯ARM ...

  4. [学习OpenCV攻略][017][ARM9下移植OpenCV]

    安装环境 宿主机: Red Hat Enterprise Linux Server 6.3 开发板: mini2440 相关软件: cmake-3.5.1.tar.gz.OpenCV-2.3.1a.t ...

  5. imx8移植opencv(3.0以上版本)笔记

    基本步骤参考我同事的博客:https://blog.csdn.net/hunzhangzui9837/article/details/89846928 以下是在移植到imx8平台时的笔记和遇到的问题及 ...

  6. Ubuntu下移植OpenCv

    通过近一周的时候终于成功交叉编译opencv成功了,真心不容易.有一句话乃真理也,凡事贵在坚持.过程总是痛苦的,因为不懂得很多问题但是又需要面对很多问题,最大的收获就是耐心解决所有问题后就懂得这些了. ...

  7. 移植opencv库到zedboard(制作运行库镜像) 分类: OpenCV ZedBoard ubuntu shell Eye_Detection 2014-11-08 18:48 172人阅读 评论(0) 收藏

    主要参考rainysky的博客 http://ledage.eefocus.com/sj229335457/blog/13-06/295352_ad954.html opencv的话只需要将lib这个 ...

  8. 嵌入式开发之移植OpenCv可执行程序到arm平台

    0. 序言 PC操作系统:Ubuntu 16.04 OpenCv版本:4.0 交叉工具链:arm-linux-gnueabihf,gcc version 5.4.0 目标平台:arm 编译时间:201 ...

  9. arm linux 移植 OpenCV

    背景: 由于学习了摄像头有关的开发,顺理成章地接触了这个部分. 搭建环境 openCV 2.2以后版本需要使用Cmake生成makefile文件,因此需要先安装cmake. OpenCV : v4.2

随机推荐

  1. 每日英语:China Overtakes U.S. in Number of Diabetes Cases

    China is now home to the world's largest diabetes population. The number of people who have diabetes ...

  2. AAuto 快速开发win32小程序

    AAuto编程语言 AAuto是专用于桌面软件快速开发的新一代混合型编程语言 -  具有动态语言轻便.灵活.快速开发的特性,而且又可以同时支持静态类型开发,象静态语言那样使用.AAuto可以直接支持原 ...

  3. vue前端导出zip包

    1. npm install jszip  /npm install script-loader / npm install file-saver 2.功能代码 require('script-loa ...

  4. eclipse 集成 github

    1.eclipse markketplace 搜索 egit 安装 next next ........  安装好之后restart   2.开始配置git插件 配置git有2中方式 1.使用http ...

  5. Linux基础之 ---目录结构

    类Unix系统目录结构ubuntu没有盘符这个概念,只有一个根目录/,所有文件都在它下面/ 根目录bin //系统可执行程序,如命令boot //内核和启动程序,所有和启动相关的文件都保存在这里gru ...

  6. Java并发(二)多线程的好处

    即使编写多线程程序具有挑战性,但它仍在使用中,是因为它可以带来如下的好处: 更好的资源利用 在某些场景下程序的设计会更简单 提升程序的响应性 更好的资源利用 假设一个应用会从本地文件系统中读取和处理文 ...

  7. Android——列表视图 ListView(三)BaseAdapter

    activity_activitybase.xml <?xml version="1.0" encoding="utf-8"?> <ListV ...

  8. Cocos2d-x 3.0final 终结者系列教程06-Director和场景跳转

    这些天互联网大事不少呀 1.逻辑思维分家(所谓合久必分,分久必合,实属正常.切行切珍惜吧) 2. 锤子手机开卖  (无论你买没买,反正我没买,作为多年Android开发的我深知说的亮点事实上在我看来都 ...

  9. 隐藏的Swiper显示后无法获取正确的宽度和高度

    今天在使用swiper的时候,元素默认是显示的时候没毛病,但是默认是隐藏的状态,再显示的时候发现滑动的时候宽度计算有误,如下图所示: 正确的显示如下: 隐藏的元素再次显示如下: 宽度计算有误 解决方案 ...

  10. thinkPHP的优缺点

    适合大量重复的工作,但不太灵活...