📄 humanmotion.cpp
字号:
// HumanMotion.cpp: implementation of the HumanMotion class.
//
//////////////////////////////////////////////////////////////////////
#ifdef _CH_
#pragma package <opencv>
#endif
#include "stdafx.h"
#include "cv.h"
#include "highgui.h"
#include <stdio.h>
#include <ctype.h>
#include "HumanMotion.h"
IplImage *image = 0, *grey = 0, *prev_grey = 0;
int add_remove_pt = 0;
int pause = 0;
int exit_flag = 0;
CvPoint pt;
CvMemStorage* storage = 0; // temporary storage
IplImage* abs_image = 0;
IplImage* add_abs_image = 0;
IplImage* add_abs_image2 = 0;
CvSeq* contour = 0;
IplConvKernel* element = 0;
int frame_count =0;
void on_mouse( int event, int x, int y, int flags, void *param )
{
if( !image )
return;
if( image->origin )
y = image->height - y;
if( event == CV_EVENT_LBUTTONDOWN )
{
pt = cvPoint(x,y);
add_remove_pt = 1;
}
}
HumanMotion::HumanMotion()
{
}
HumanMotion::~HumanMotion()
{
}
int HumanMotion::Start()
{
main_loop(1);
return 0;
}
int HumanMotion::main_loop( int useCAM)
{
CvCapture* capture = 0;
if( useCAM == 1)
capture = cvCaptureFromFile("lux_camsub_animation.avi");
//halfbody2.avi
//capture4.avi
else if( useCAM == 2 )
capture = cvCaptureFromCAM(-1);
if( !capture )
{
fprintf(stderr,"Could not initialize capturing...\n");
return -1;
}
printf( "Hot keys: \n"
"\tESC - quit the program\n"
"\tp - pause on/off\n"
"\n" );
cvNamedWindow( "LkDemo", 1 );
cvNamedWindow( "Contour", 1 );
cvSetMouseCallback( "LkDemo", on_mouse, 0 );
for(;;)
{
IplImage* frame = 0;
if(pause)
frame = image ;
else
frame = cvQueryFrame( capture );
if( !frame ) break;
if( !image )
{
/* allocate all the buffers */
CvSize image_sz;
image_sz = cvGetSize(frame) ;
image = cvCreateImage(image_sz , 8, 3 );
grey = cvCreateImage( image_sz, 8, 1 );
prev_grey = cvCreateImage( image_sz, 8, 1 );
image->origin = grey->origin = prev_grey->origin = frame->origin;
storage = cvCreateMemStorage(0);
}
cvCopy( frame, image, 0 );
cvCvtColor( image, grey, CV_BGR2GRAY );
analyze_contour(grey);
//记录前一帧的图像,方便差分
if(frame_count%2==0)
cvCopy(grey,prev_grey,0);
frame_count++;
//设置键盘控制
KeyControl();
if(exit_flag) break;
}
cvReleaseCapture( &capture );
cvDestroyWindow("LkDemo");
cvDestroyWindow("Contour");
return 0;
}
//分析轮廓
int HumanMotion::analyze_contour(IplImage* grey_image)
{
getContour(grey,prev_grey);
return 0;
}
CvPoint2D32f HumanMotion::Point_to_32f(CvPoint pt)
{
CvPoint2D32f pt32;
float zoom = 1.0f;
pt32.x = pt.x * zoom;
pt32.y = pt.y * zoom;
return pt32;
}
//得到轮廓信息
int HumanMotion::getContour(IplImage *imggrey, IplImage *pre_grey)
{
//执行透视变换
if(!pause) WarpPerspective(image);
//转换灰度模式
cvCvtColor( image, grey, CV_BGR2GRAY );
//阈值分割,这个阈值可用直方图自动调整
cvThreshold( grey, grey, 50, 255, CV_THRESH_BINARY_INV );
//寻找轮廓
cvFindContours( grey, storage, &contour, sizeof(CvContour),
CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) );
int ApproxCount = 1; //轮廓优化等级
contour = cvApproxPoly( contour, sizeof(CvContour), storage, CV_POLY_APPROX_DP,ApproxCount, 1 );
//cvDrawContours( image, contour, CV_RGB(255,0,0), CV_RGB(0,255,0), 7, 3, CV_AA, cvPoint(0,0) );
//绘制轮廓
drawContours(image);
cvShowImage( "Contour", image );
cvShowImage( "LkDemo", grey );
return 0;
cvAbsDiff( grey,pre_grey,abs_image );
cvThreshold( abs_image, abs_image, 10, 255, CV_THRESH_BINARY );
CvPoint top_pt,bottom_pt;
getActivityArea(abs_image,top_pt,bottom_pt);
cvRectangle( image, top_pt, bottom_pt, CV_RGB(155,151,255),1, CV_AA, 0 );
cvShowImage( "Contour", image );
cvShowImage( "LkDemo", abs_image );
//cvWaitKey(30);
return 0;
}
//根据输入图像活动区域得到最大的方形区域
inline int HumanMotion::getActivityArea(IplImage *grey, CvPoint &top_pt,CvPoint &bottom_pt)
{
CvMat mat;
CvMat *temp = cvGetMat(grey , &mat,0 ,2);
top_pt.x = mat.rows;
top_pt.y = mat.step;
bottom_pt.x = 0;
bottom_pt.y = 0;
//行遍历,寻找top pt
for(int x=0;x<mat.rows;x++)
{
int start_index = 0;
int end_index = 0;
//正向列遍历,寻找最左边的点
for(int y=0;y<mat.step;y++)
{
int index =mat.step*x + y;
int value = mat.data.ptr[index];
if(value==255)
{
start_index = y;
if (start_index < top_pt.x) top_pt.x = start_index;
break;
}
}
//反向列遍历,寻找最右边的点
for(int y=mat.step-1;y>0;y--)
{
int index =mat.step*x + y;
int value = mat.data.ptr[index];
if(value==255)
{
end_index = y;
if (end_index > bottom_pt.x) bottom_pt.x = end_index;
break;
}
}
}
//列行遍历
for(int y=0;y<mat.step;y++)
{
int start_index = 0;
int end_index = 0;
//行遍历,寻找最上边的点
for(int x=0;x<mat.rows;x++)
{
int index =mat.step*x + y;
int value = mat.data.ptr[index];
if(value==255)
{
start_index = x;
if (start_index < top_pt.y) top_pt.y = start_index;
break;
}
}
//寻找最下边的点
for(int x=mat.rows-1;x>0;x--)
{
int index =mat.step*x + y;
int value = mat.data.ptr[index];
if(value==255)
{
end_index = x;
if (end_index > bottom_pt.y) bottom_pt.y = end_index;
break;
}
}
}
return 0;
}
int HumanMotion::Test_cvMUL2(IplImage *grey)
{
/*
double bound;
double mean =0;
CvRNG rng_state = cvRNG(0xffffffff);
IplImage *image_noise = 0;
image_noise = cvCreateImage(cvGetSize(grey), grey->depth, 1);
bound = sqrt(3*1);
//cvRandArr(&rng_state, image_noise, CV_RAND_UNI, cvRealScalar(-bound + mean), cvRealScalar(bound + mean));
cvMul(grey, image_noise, grey);
*/
IplImage* src = cvCloneImage( grey );
float m[6];
int angle = frame_count%60 - 30;
CvMat M = cvMat( 2, 3, CV_32F, m );
int w = src->width;
int h = src->height;
m[0] = (float)(cos(angle*CV_PI/180.));
m[1] = (float)(sin(angle*CV_PI/180.));
m[2] = w*0.5f;
m[3] = -m[1];
m[4] = m[0];
m[5] = h*0.5f;
cvGetQuadrangleSubPix( src, grey, &M);
return 0;
}
//透视变换
//auto get points to do list
int HumanMotion::WarpPerspective(IplImage *grey)
{
IplImage* Img_old = cvCloneImage( grey );
int fix = 4.0f;
int w = Img_old->width + fix;
int h = Img_old->height + fix;
CvPoint2D32f src_point[4];
CvPoint2D32f dst_point[4];
/* //for small movie
src_point[0].x=4;
src_point[0].y=142;
src_point[1].x=238;
src_point[1].y=134;
src_point[2].x=25;
src_point[2].y=55;
src_point[3].x=209;
src_point[3].y=50;
*/
src_point[0].x=17;
src_point[0].y=475;
src_point[1].x=952;
src_point[1].y=449;
src_point[2].x=100;
src_point[2].y=128;
src_point[3].x=840;
src_point[3].y=110;
dst_point[0].x=-fix;
dst_point[0].y=h;
dst_point[1].x=w;
dst_point[1].y=h;
dst_point[2].x=-fix;
dst_point[2].y=-fix;
dst_point[3].x=w;
dst_point[3].y=-fix;
float newm[9];
CvMat newM = cvMat( 3, 3, CV_32F, newm );
//获得透视转换矩阵
cvWarpPerspectiveQMatrix(src_point,dst_point,&newM);
//透视转换
cvWarpPerspective(Img_old,grey,&newM,CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS, cvScalarAll(0) );
cvReleaseImage(&Img_old);
return 0;
}
int HumanMotion::KeyControl()
{
char c;
c = cvWaitKey(10);
//c = 'd';
//printf("%c,%d",c,c);
if( c == 27 )
exit_flag = 1;
switch( c )
{
case 'p':
pause ^= 1;
break;
default:
;
}
return c;
}
//绘制轮廓
int HumanMotion::drawContours(IplImage *dst)
{
CvSeqReader reader;
int i;
CvPoint pt,pt_pre;
for (; contour != NULL; contour = contour->h_next)
{
cvStartReadSeq(contour, &reader);
int N = contour->total;
for (i = 0; i < N+1; i++)
{
CV_READ_SEQ_ELEM(pt, reader);
if(i!=0) cvLine(dst,pt,pt_pre,CV_RGB(0,255,0),2,CV_AA, 0 );
pt_pre = pt;
}
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -