www.pudn.com > hbp0.1.zip > classflow.cpp


/*************************************************************************** 
                          classflow.cpp  
 
    optical flow 
 
    begin                : Sun Nov 24 2002 
    copyright            : (C) 2002 by Bob Mottram 
    email                : fuzzgun@btinternet.com 
 ***************************************************************************/ 
 
/*************************************************************************** 
 *                                                                         * 
 *   This program is free software; you can redistribute it and/or modify  * 
 *   it under the terms of the GNU General Public License as published by  * 
 *   the Free Software Foundation; either version 2 of the License, or     * 
 *   (at your option) any later version.                                   * 
 *                                                                         * 
 ***************************************************************************/ 
 
#include "classimage.h" 
#include "classflow.h" 
 
///  
/// Constructor 
///  
classflow::classflow() 
{ 
  int i,j; 
 
  initialised=false; 
  motion_threshold = 20; 
  optical_flow_search_region = 5; 
  optical_flow_patch = 3; 
 
  //clear the optical flow history 
  noflow=0; 
  flowHistoryCtr=0; 
  for (i=0;i<100;i++) 
    for (j=0;j<7;j++) flowHistory[i][j]=0; 
} 
 
 
///  
/// Destructor 
///  
classflow::~classflow() 
{ 
} 
 
 
///  
/// Initialise 
///  
void classflow::init() 
{ 
  int x,y; 
 
  flow = new unsigned char**[width]; 
  for (x=0;x 
/// Calculates optical flow 
///  
/// A bitmap image 
/// Width of the bitmap 
/// Height of the bitmap 
void classflow::update(unsigned char ***img, int wdth, int hght) 
{ 
  int x,y,xx,yy,xxx,yyy,c; 
  int closest_x,closest_y; 
  int px,py,dx,dy; 
  long closest,dp; 
  long avflow_x,avflow_y,pixels; 
  int bin_x,bin_y; 
 
  width = wdth; 
  height = hght; 
  if (initialised==false) init(); 
 
  //enable secondary update of motion 
  motion->enableSecondaryUpdate=true; 
 
  //variables used to calculate average flow over the entire image 
  avflow_x=0; 
  avflow_y=0; 
  pixels=1; 
 
  if (motion->averageIntensity >= 0) 
  { 
 
    //clear the flow histogram votes and boxes 
    flowHistogramMax=1; 
    for (x=0;x<14;x++) 
    { 
      for (y=0;y<14;y++) 
        flowHistogram[x][y]=0; 
    } 
 
 
    //step through the image 
    //note that increasing the step size for x and y increases the speed (fewer calculations) 
    for (x = 0;ximage[x][y][0] > motion_threshold)  
			&& (x>optical_flow_search_region) && (xoptical_flow_search_region) && (y0) && (xx0) && (yy0) && (xxx0) && (yyy=0) && (px=0) && (pyimage2[px][py][c]); 
                          } 
                        } 
                      } 
                    } 
                  } 
 
                  //if this patch is the closest match then take note of its position 
                  if (dp0) && (xx0) && (yyflowHistogramMax) flowHistogramMax=flowHistogram[bin_x][bin_y]; 
        } 
      } 
    } 
  } 
 
  //perform secondary update of motion object 
  motion->update_secondary(img); 
   
  average_flow_x = (float)(avflow_x / pixels); 
  average_flow_y = (float)(avflow_y / pixels); 
 
} 
 
 
///  
/// Calculates optical flow 
///  
/// Image object 
void classflow::update(classimage *img) 
{ 
  update(img->image,img->width,img->height); 
} 
 
 
 
///  
/// segment the image based upon optical flow 
///  
/// Image object 
/// Distance 
void classflow::segment(classimage *img, int distance) 
{ 
  int x,y,xx,disp,disp2,c,i,j; 
  int start_pos,hits,pixels; 
  int max_segwidth = width/2; 
  long cx; 
 
  for (y=1;yimage[x][y][0]>10) hits++; 
 
	  if ((((image[x][y][0]>0) && (image[x-1][y][0]==0)) || ((image[x][y][0]==0) && (image[x-1][y][0]>0))) 
		  //(((image[x][y][0]>0) && (image[x-1][y-1][0]==0)) || ((image[x][y][0]==0) && (image[x-1][y-1][0]>0))) || 
		  //(((image[x][y][0]>0) && (image[x-1][y+1][0]==0)) || ((image[x][y][0]==0) && (image[x-1][y+1][0]>0))) 
		  ) 
	  { 
 
          if (xboundingbox_bx) boundingbox_bx=x; 
          if (yboundingbox_by) boundingbox_by=y; 
 
 
		if ((start_pos>-1) && (hits>-1) && (x-start_posimage[x][y][0]>10) hits++; 
 
	  if (((image[x][y][0]>0) && (image[x][y-1][0]==0)) || ((image[x][y][0]==0) && (image[x][y-1][0]>0))) 
	  { 
		if ((start_pos>-1) && (hits>-1) && (y-start_pos0) 
		  image[x][y][c] = img->image[x][y][c]; 
		  else 
		  image[x][y][c] = img->image[x][y][c]/3; 
	  } 
    } 
  } 
 
 
  if ((pixels>1) && (boundingbox_bx>boundingbox_tx+1) && (boundingbox_by>boundingbox_ty+1)) 
  { 
    centre_x = (centre_x + ((cx/pixels) + (boundingbox_tx + ((boundingbox_bx-boundingbox_tx)/2)))/2)/2; 
    centre_y = boundingbox_ty + ((boundingbox_by-boundingbox_ty)/2); 
    aspectRatio = (boundingbox_by-boundingbox_ty) / (float)(boundingbox_bx-boundingbox_tx) * width / height; 
  } 
  else 
  aspectRatio = 0; 
 
 
  //store the optical flow history, for possible gesture recognition 
  if ((pixels>1) && ((abs((int)average_flow_x)>=1) || (abs((int)average_flow_y)>=1))) 
  { 
	noflow=0; 
    flowHistory[flowHistoryCtr][0] = (int)average_flow_x; 
	flowHistory[flowHistoryCtr][1] = (int)average_flow_y; 
	flowHistory[flowHistoryCtr][2] = boundingbox_tx; 
	flowHistory[flowHistoryCtr][3] = boundingbox_ty; 
	flowHistory[flowHistoryCtr][4] = boundingbox_bx; 
	flowHistory[flowHistoryCtr][5] = boundingbox_by; 
	flowHistory[flowHistoryCtr][6] = distance; 
 
    flowHistoryCtr++; 
	if (flowHistoryCtr>99) flowHistoryCtr=0; 
  } 
  else 
  { 
	//if there has been no movement for a while then erase the optical flow history 
    noflow++; 
	if (noflow==10) 
	{ 
      flowHistoryCtr=0; 
      for (i=0;i<100;i++) 
        for (j=0;j<6;j++) flowHistory[i][j]=0; 
	} 
	if (noflow>11) noflow=11; 
  } 
 
} 
 
 
 
///  
/// Update stereo disparity - this function is not presently used 
///  
/// Optical flow object 
void classflow::updateDisparity(classflow *f) 
{ 
  int x,y,max; 
 
  averageDisparity = abs(centre_x - f->centre_x) * 4; 
  if (averageDisparity > 255) averageDisparity=255; 
 
  //show a bar indicating distance from the object 
  max=(height*averageDisparity)/255*1; 
  if (max>height-1) max=height-1; 
  for (y=0;y 
/// match the flow with another image - this function is not presently used 
///  
/// Image object 
/// Object storing the left image 
/// Object storing the right image 
void classflow::matchFlow(classimage *img, classimage *rawimgLeft, classimage *rawimgRight) 
{ 
  int x,y,p1[2],p2[2],r1[3],xx,yy,c; 
  int max_disparity = width/4; 
  int similarity,min,disp; 
 
  for (y=1;yimage[x][y][c]; 
	  if (p1[0]>0) 
	  { 
		min=99999; 
		disp=0; 
        for (xx = x-max_disparity;xx0) && (xximage[xx][yy][0]; 
			  p2[1] = img->image[xx][yy][1]; 
			  if (p2[0]>0) 
			  { 
                //compare the optical flow vectors 
				similarity = abs(p1[0]-p2[0]) + abs(p1[1]-p2[1]); 
 
				//include some colour information to improve matching 
				for (c=0;c<3;c++) similarity += abs(r1[c] - rawimgRight->image[xx][yy][c])/2; 
 
				//bias depending upon distance from the current x position 
				//this prevents a lot of spurious high disparity matches by making 
				//smaller disparities more probable 
				similarity += abs(xx-x)*1; 
 
				//square 
				similarity *= similarity; 
 
                //if the match is close store the disparity value 
				if (similarity255) disp=255; 
 
		image[x][y][0]=disp; 
		image[x][y][1]=disp; 
		image[x][y][2]=disp; 
		segmented[x][y][1]=disp; 
 
	  } 
 
 
	} 
  } 
} 
 
 
 
///  
/// Returns the optical flow history 
///  
/// Time 
/// Index 
int classflow::getFlowHistory(int t, int index) 
{ 
  int i; 
   
  if (t>99) t=99; 
  i = flowHistoryCtr - t; 
  if (i<0) i += 100; 
 
  return(flowHistory[i][index]); 
}