[尝试开发]采用运动目标检测实现模拟翻书软件

实现功能:不用鼠标及键盘,只要在摄像头前挥动手,就可以翻页电脑中的书。
或者实现更多功能。
先看图:

有人说:书呢?
都说是模拟咯,当然没有书 -_-!!
左侧视频为分析图像,右侧为现实图像,加了红线及绿色矩形,便于测试
有4红线,分两个触发区域(1、2和3、4红线直间),从左到右,或者从右到左,要连续触发两个区域才能实现翻页。
外面两区域为无效区域,触发则所有值重置。
代码如下,注释看上一篇
//---------------------------------------------------------------------------
//=====================头文件=====================
#ifndef Unit1H
#define Unit1H
//#define Left 1
//#define Right 2
//#define None 3
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include 
<Controls.hpp>
#include 
<StdCtrls.hpp>
#include 
<Forms.hpp>
#include 
<cv.h>
#include 
<highgui.h>
#include 
<time.h>
#include 
<cxcore.h>
const double MHI_DURATION=0.5;
const double MAX_TIME_DELTA=0.5;
const double MIN_TIME_DELTA=0.005;
const int N=2;
const int CONTOUR_MAX_AERA=300;
static int lco=0;
static int rco=0;

IplImage 
**buf=0;
int last=0;
IplImage
* mhi=0;
bool flag;
bool star=false;
static int r_point=0;
static int l_point=0;
static int m_point=0;
static int x_point=0;
static int rInvalid=0;
static int lInvalid=0;
static String direct = "none";
double validTime = 0;
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    
// IDE-managed Components
        TButton *Button1;
        TLabel 
*Label1;
        TEdit 
*Edit1;
        TLabel 
*Label2;
        TEdit 
*Edit2;
    TButton 
*Button2;
    TLabel 
*Label3;
    TLabel 
*Label4;
    TLabel 
*Label5;
    TEdit 
*Edit3;
    TEdit 
*Edit4;
    TEdit 
*Edit5;
        
void __fastcall Button1Click(TObject *Sender);
    
void __fastcall Button2Click(TObject *Sender);
private:    // User declarations
public:        // User declarations
        __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif


//---------------------------------------------------------------------------
//=======================实现文件=====================
#include <vcl.h>
#pragma hdrstop

#include 
"Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 
*Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void update_mhi3(IplImage *img,IplImage *dst,int diff_threshold)
{
    
int w    = img->width;
    r_point  
= w*3/5;       //右端有效临界线
    rInvalid = w*4/5;       //右端无效临界线
    l_point  = w*2/5;       //左端有效临界线
    lInvalid = w*1/5;       //左端无效临界线
    m_point  = w/2;         //中线(暂时没用)
    double timestamp=clock()/100.;
    
double angle;
    CvSize size 
= cvSize(img->width,img->height);
    
int i,idx1=last,idx2;
    IplImage
* silh;
    IplImage
* pyr=cvCreateImage(cvSize((size.width&-2)/2,(size.height&-2)/2),8,1);
    CvMemStorage 
*stor;
    CvSeq 
*cont;

    
if(!mhi||mhi->width!=size.width||mhi->height!=size.height)
    {
        
if(buf==0)
        {
            buf
=(IplImage**)malloc(N*sizeof(buf[0]));
            memset(buf,
0,N*sizeof(buf[0]));
        }
        
for(i=0;i<N;i++)
        {
            cvReleaseImage(
&buf[i]);
            buf[i]
=cvCreateImage(size,IPL_DEPTH_8U,1);
            cvZero(buf[i]);
        }
        cvReleaseImage(
&mhi);

        mhi
=cvCreateImage(size,IPL_DEPTH_32F,1);
        cvZero(mhi);
    }
    cvCvtColor(img,buf[last],CV_BGR2GRAY);
    idx1
=last;
    idx2
=(last+1)%N;
    last
=idx2;
    silh
=buf[idx2];
    cvAbsDiff(buf[idx1],buf[idx2],silh);
    cvThreshold(silh,silh,
30,255,CV_THRESH_BINARY);
    cvUpdateMotionHistory(silh,mhi,timestamp,MHI_DURATION);
    cvCvtScale(mhi,dst,
255./MHI_DURATION,0);
    cvSmooth(dst,dst,CV_MEDIAN,
3,0,0,0);
    cvPyrDown(dst,pyr,
7);
    cvDilate(pyr,pyr,
0,25);
    cvErode(pyr,pyr,
0,25);
    cvPyrUp(pyr,dst,
7);

    cvNamedWindow(
"dst",1);
    cvShowImage(
"dst",dst);

    stor
=cvCreateMemStorage(0);
    cont
=cvCreateSeq(CV_SEQ_ELTYPE_POINT,sizeof(CvSeq),sizeof(CvPoint),stor);

    cvFindContours(dst,stor,
&cont,sizeof(CvContour),CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE,cvPoint(0,0));
    
//CvRect r;
    
//r.x = 0;
    for(;cont;cont=cont->h_next)
    {
        CvRect r
=((CvContour*)cont)->rect;
        
/*
        if(direct == "right" && t.x < r.x )
            r = t;
        else if(t.x > r.x)
            r = t;
        
*/
        
if(r.height*r.width>100)
        {
        cvRectangle(img,cvPoint(r.x,r.y),cvPoint(r.x
+r.width,r.y+r.height),
        CV_RGB(
0,255,0),3,CV_AA,0);
        }
    
//}
        x_point=r.width/2+r.x;
        
if(!star)
        {
            
if(x_point >= r_point && x_point <= rInvalid)
            {
                star
=true;
                direct
="right";
                validTime 
= clock()/1000.0;
            }
            
else if(x_point <= l_point && x_point > lInvalid)
            {
                star
=true;
                direct
="left";
                validTime 
= clock()/1000.0;
            }
            
else
                direct
="none";
        }
        
else
        {
            
if(x_point < lInvalid || x_point > rInvalid)
            {
                star 
= false;   direct = "none";
            }
            
else if(direct == "left" && x_point>= r_point)
            {
                    star
=false;
                    rco
++;
            }
            
else if(direct == "right" && x_point<=l_point)
            {
                    star
=false;
                    lco
++;
            }
            
else if(direct == "none")
                
break;
        }

    }
    cvReleaseMemStorage(
&stor);
    cvReleaseImage(
&pyr);
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    IplImage
* motion=0;
    CvCapture
* capture=0;
    capture
=cvCaptureFromCAM(0);
    
if(capture)
    {
        cvNamedWindow(
"Motion",1);
        
for(;;)
        {
        
//检测有效时间
        if(star && (clock()/1000.0 - validTime) > 3)
        {
            star 
= false;
            direct 
= "none";
        }
        IplImage 
*image;
        
if(!cvGrabFrame(capture))
        
break;
        image
=cvRetrieveFrame(capture);
        
if(image)
        {
            
if(!motion)
            {
                motion
=cvCreateImage(cvSize(image->width,image->height),8,1);
                cvZero(motion);
                motion
->origin=image->origin;
            }
        }
        update_mhi3(image,motion,
60);
        cvLine(image,cvPoint(r_point,
0),cvPoint(r_point,image->height),
                CV_RGB(
255,0,0));
        cvLine(image,cvPoint(l_point,
0),cvPoint(l_point,image->height),
                CV_RGB(
255,0,0));
        
//cvLine(image,cvPoint(m_point,0),cvPoint(m_point,image->height),
        
//        CV_RGB(255,0,0));
        cvLine(image,cvPoint(rInvalid,0),cvPoint(rInvalid,image->height),
                CV_RGB(
255,0,0));
        cvLine(image,cvPoint(lInvalid,
0),cvPoint(lInvalid,image->height),
                CV_RGB(
255,0,0));
        
this->Edit3->Text = (int)star;
        
this->Edit4->Text = x_point;
        
this->Edit5->Text = direct;
        
this->Edit1->Text=lco;
        
this->Edit2->Text=rco;
        cvShowImage(
"Motion",image);
        
if(cvWaitKey(5== 27)
            
break;
        }
        cvReleaseCapture(
&capture);
        cvDestroyWindow(
"Motion");
    }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button2Click(TObject *Sender)
{
    lco 
= 0;  rco = 0;
    direct
="none";
    star 
= false;
}
//---------------------------------------------------------------------------

posted @ 2009-07-21 01:11  mxm  阅读(193)  评论(0)    收藏  举报