[尝试开发]采用运动目标检测实现模拟翻书软件
实现功能:不用鼠标及键盘,只要在摄像头前挥动手,就可以翻页电脑中的书。
或者实现更多功能。
先看图:
![]()
有人说:书呢?
都说是模拟咯,当然没有书 -_-!!
左侧视频为分析图像,右侧为现实图像,加了红线及绿色矩形,便于测试
有4红线,分两个触发区域(1、2和3、4红线直间),从左到右,或者从右到左,要连续触发两个区域才能实现翻页。
外面两区域为无效区域,触发则所有值重置。
代码如下,注释看上一篇
或者实现更多功能。
先看图:

有人说:书呢?
都说是模拟咯,当然没有书 -_-!!
左侧视频为分析图像,右侧为现实图像,加了红线及绿色矩形,便于测试
有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
//=====================头文件=====================
#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;
}
//---------------------------------------------------------------------------
//=======================实现文件=====================
#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;
}
//---------------------------------------------------------------------------
浙公网安备 33010602011771号