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]);
}