zoukankan      html  css  js  c++  java
  • 移植opencv到pcDuino

    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 = 110;
    
    staticintcenterlevelY = 60;
    
    //定义了舵机的频率
    
    constintfrequncy = 260;
    
    //用一个整数存储目前舵机摆动方向
    
    staticintturningRight = 1;
    
    //函数的签名列表
    
    voiddetect_and_draw( IplImage* image );
    
    voidstart_pulse(intpwm_id,intfreq,intvalue);
    
    voidsigroutine(intdunno);
    
    voidreset();
    
    longgetCurrentTime();
    
    longstartTime;
    
    longendTime;
    
    //led指示灯pin脚
    
    intpin_led = 3;
    
    //为OpenCV申请一块用于计算的内存
    
    staticCvMemStorage* storage = 0;
    
    //声明一个haar分类器
    
    staticCvHaarClassifierCascade* cascade = 0;
    
    voidsetup(){
    
    //定义指示灯针脚为输出
    
    pinMode(pin_led,OUTPUT);
    
    //复位云台舵机
    
    reset();
    
    //监听中断信号
    
    signal(SIGINT,sigroutine);
    
    //建立一个名为result的窗口
    
    cvNamedWindow(“result”, 1 );
    
    //打开摄像头
    
    CvCapture* capture = cvCaptureFromCAM(-1);
    
    //声明两个opencv图像类型
    
    IplImage *img;
    
    IplImage *newImg;
    
    //加载分类器
    
    cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
    
    //检查分类器加载异常
    
    if( !cascade ){
    
    fprintf( stderr,”ERROR: Could not load classifier cascade
    ”);
    
    }
    
    //定位内存块
    
    storage = cvCreateMemStorage(0);
    
    while(1) {
    
    //由于pcduino的计算能力有限,为了保证帧率,把从摄像头采集来的画面缩小1/2
    
    newImg = cvQueryFrame( capture );
    
    if( !newImg )break;
    
    img = cvCreateImage(cvSize(newImg->width/2, newImg->height/2), newImg->depth, newImg->nChannels);
    
    cvResize(newImg, img);
    
    //翻转图像
    
    cvFlip(img, img, 1);
    
    //调用识别和绘制图像的函数
    
    detect_and_draw(img);
    
    //释放图像使用的内存
    
    cvReleaseImage(&img);
    
    //监听esc键
    
    intc = cvWaitKey(33);
    
    if( c == 27 )break;
    
    }
    
    //释放摄像头
    
    cvReleaseCapture( &capture );
    
    //销毁窗口
    
    cvDestroyWindow(“result”);
    
    }
    
    voiddetect_and_draw( IplImage* img ){
    
    startTime = getCurrentTime();
    
    //清空使用过的内存空间
    
    cvClearMemStorage( storage );
    
    intscale = 1;
    
    inti;
    
    //声明一个中心点存储识别出来的人脸位置
    
    CvPoint ptcenter;
    
    //人脸识别
    
    if( cascade ){
    
    //逐帧检测人脸
    
    CvSeq* faces = cvHaarDetectObjects( img, cascade, storage,
    
    1.1, 2, CV_HAAR_DO_CANNY_PRUNING,
    
    cvSize(80, 80));
    
    //如果检测到多张脸,遍历取出
    
    for( i = 0; i < (faces ? faces->total : 0); i++ ){
    
    //创建人脸矩形
    
    CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
    
    //换算出人脸矩形的中心点
    
    ptcenter.x = (r->x+(r->width/2))*scale;
    
    ptcenter.y = (r->y+(r->height/2))*scale;
    
    //绘制一个圆形标识出人脸的位置
    
    cvCircle(img, ptcenter, (r->width+r->height)/4, CV_RGB(255,0,0), 3, 8, 0 );
    
    }
    
    }
    
    //显示图像
    
    cvShowImage(“result”, img );
    
    //计算帧率
    
    endTime = getCurrentTime();
    
    longtime= endTime-startTime;
    
    intframerate = 1000/time;
    
    //检查中心点是否为空
    
    if(ptcenter.x && ptcenter.y){
    
    //std::cout<<”center_point:(“<<ptcenter.x<<”,”<<ptcenter.y<<”)	frame_rate:”<<framerate<<”
    ”<<std::endl;
    
    //std::cout<<”x:”<<(ptcenter.x-img->width/2)<<”	y:”<<(ptcenter.y-img->height/2)<<std::endl;
    
    //向led指示灯引脚输出低电平,熄灭指示灯
    
    digitalWrite(pin_led,LOW);
    
    //驱动摄像头移动到人脸中心位置
    
    centerlevelX += (ptcenter.x-img->width/2)/110*2;
    
    if(centerlevelX <= 170 && centerlevelX >= 50)start_pulse(6,frequncy,centerlevelX);
    
    centerlevelY -= (ptcenter.y-img->height/2)/70;
    
    if(centerlevelY <= 90 && centerlevelY >= 45)start_pulse(5,frequncy,centerlevelY);
    
    //显示修正的X和Y轴幅度和帧率
    
    std::cout<<”X:”<<centerlevelX<<”	Y:”<<centerlevelY<<”	FrameRate:”<<framerate<<std::endl;
    
    }else{
    
    printf(“no face is detected in the image
    ”);
    
    //指示灯亮起
    
    digitalWrite(pin_led,HIGH);
    
    //如果没有检测到人脸则左右摇摆摄像头
    
    if(centerlevelX <= 170 && turningRight == 1){
    
    start_pulse(6,frequncy,centerlevelX+=2);
    
    if(centerlevelX > 170)turningRight = 0;
    
    //std::cout<<centerlevelX<<std::endl;
    
    }
    
    if(centerlevelX >= 50 && turningRight == 0){
    
    start_pulse(6,frequncy,centerlevelX-=2);
    
    if(centerlevelX < 50)turningRight =1;
    
    //std::cout<<centerlevelX<<std::endl;
    
    }
    
    }
    
    //防止摄像头下移过度
    
    if(centerlevelY < 45) centerlevelY = 45;
    
    }
    
    //复位函数,调整舵机X、Y轴到中心位置
    
    voidreset(){
    
    delay(50);
    
    start_pulse(5,frequncy,60);
    
    start_pulse(6,frequncy,110);
    
    delay(50);
    
    }
    
    longgetCurrentTime(){
    
    structtimeval tv;
    
    gettimeofday(&tv,NULL);
    
    longtime=  tv.tv_sec * 1000 + tv.tv_usec / 1000;
    
    returntime;
    
    }
    
    //舵机驱动函数
    
    voidstart_pulse(intpwm_id,intfreq,intvalue){
    
    intstep = 0;
    
    step = pwmfreq_set(pwm_id, freq);
    
    //printf(“PWM%d set freq %d and valid duty cycle range [0, %d]
    ”, pwm_id, freq, step);
    
    if(step > 0){
    
    //printf(“PWM%d test with duty cycle %d
    ”, pwm_id, value);
    
    analogWrite(pwm_id, value);
    
    delay(50);
    
    }
    
    }
    
    //signal回调函数,监听中断信号,做一些状态复位工作
    
    voidsigroutine(intdunno) {
    
    switch(dunno) {
    
    case2:
    
    printf(“Get a signal – SIGINT 
    ”);
    
    reset();
    
    analogWrite(6,0);
    
    analogWrite(5,0);
    
    digitalWrite(pin_led,LOW);
    
    exit(0);
    
    break;
    
    }
    
    }
    
    voidloop(){} 
  • 相关阅读:
    会议记录补充5月9日
    会议记录补充5月11日
    每日会议记录5月6日
    SQL Server 日期函数
    Jvascript运算符
    For循环
    JS数据类型
    初识Javascript
    检测浏览器版本(综合整理)
    自己实现一个数组的slice方法
  • 原文地址:https://www.cnblogs.com/zxouxuewei/p/4985005.html
Copyright © 2011-2022 走看看