www.pudn.com > ReadingPeopleTracker-1.28.rar > Region.cc


/*
 * Region.cc
 *
 * a Region is a rectangular subimage and
 * will in general contain one connected blob
 *
 * class created 2/3/93
 * author: Adam Baumberg
 *
 */

#include "Region.h"

#include 

#include "Image.h"
#include "BoundaryPoints.h"
// #include "XMLSource.h"
#include "Profile.h"
#include "Grey8Image.h"
#include "text_output.h"

#ifndef NO_DISPLAY
#ifdef USE_GL
#include 
#else
#include 
#endif
#endif   // #ifndef NO_DISPLAY

namespace ReadingPeopleTracker
{

// TDG 6/2/98  commented out so that model building uses
// vertical axis for alignment better for cars
// use principle axis for people
// TDG 15/12/98 added REGION_USE_HIGHEST_POINT option
// nts 25/10/00 changed to REGION_USE_PRINCIPAL_AXIS for people tracking

//#define REGION_USE_DIRECTION
#define REGION_USE_PRINCIPAL_AXIS
//#define REGION_USE_HIGHEST_POINT


// definition and initialisation of static member variables
const unsigned int Region::start_list[8] = {5,6,7,0,1,2,3,4};
const unsigned int Region::end_list[8] = {4,5,6,7,0,1,2,3};

const Point2 Region::directions[8] =
{
    Point2(-1,-1), Point2(-1,0) ,Point2(-1,1), 
    Point2(0,1), Point2(1,1), 
    Point2(1,0), Point2(1,-1), Point2(0,-1)
};


Region::~Region()
{
    if (region_img != NULL) delete region_img;
    if (region_boundary != NULL) delete region_boundary;
}

Region &Region::operator= (const Region &original)
{
    Observation::operator=(original);
    
    tracker = original.tracker;

    // copy over values for normal variables
    old_origin = original.old_origin;
    direction = original.direction;
    xml_blob_data = original.xml_blob_data;
    xml_blob_data_available = original.xml_blob_data_available;
    inv_grad = original.inv_grad;
    incorporated_into_background = original.incorporated_into_background;
 
    // instantiate new classes in order to copy *region_img and *region_boundary...
    if (original.region_img != NULL)
	region_img = original.region_img->copy();  // instantiates image class
    
    if (original.region_boundary != NULL)
    {
	region_boundary = new BoundaryPoints(original.region_boundary->get_no_points());
	*region_boundary = *original.region_boundary;
    }
    
    return *this;
};

void Region::trace()
{
    if (region_boundary == NULL)
	region_boundary = new BoundaryPoints();
    int imgwidth = region_img->get_width();
    int imgheight = region_img->get_height();
    bool found =  false;
    /*int x = imgwidth / 2;
      int y;
      for (y = 0; y < imgheight && !found; y++)
      if (*(region_img->get_pixel(x,y)) != CLEAR_MARK) found = true; */
    int x = 0;
    int y = 0;
    while ((y < imgheight) && (!found))
    {
	if (*(region_img->get_pixel(x,y)) != CLEAR_MARK)
	    found = true;
	else
	    if ((++x) >= imgwidth)
	    {
		x = 0;
		y++;
	    }
    }
    if (!found) 
    {
	cerror << " Region::trace(): cannot find starting point in region " << endl;
	exit(1);
    }
    
    region_boundary->add_point( Point2(x,y));
    int forward = 1;
    int old_tmp = forward;
    int tmp = old_tmp;
    bool flag;
    int loop1;
    unsigned char *lpix;
    do
    {
	flag = false;
//      forward = (forward+1) & 7;
	loop1 = start_list[forward];
	while ((loop1 != end_list[forward]) && (flag == false))
	{
	    Point2 look_dir = directions[(loop1+1)&7];

	    if ((region_img->check_coords(x + look_dir.x, y + look_dir.y) == false) ||
		*(lpix = region_img->get_pixel(x + (int) look_dir.x,
					       y + (int)look_dir.y)) == CLEAR_MARK)
		loop1 = (loop1+1) & 7;
	    else 
	    {
		lpix = region_img->get_pixel(x + (int) look_dir.x,
					     y + (int) look_dir.y);
	    
		x += (int) look_dir.x;
		y += (int) look_dir.y;
		region_boundary->add_point(Point2(x,y));
		flag = true;
		forward = loop1;
		tmp = (loop1+1) & 7;
	    }
	}
	
	if (flag == false)
	{
	    Point2 look_dir = directions[(loop1+1)&7];

	    if ((region_img->check_coords(x + look_dir.x, y + look_dir.y) == false) ||
		*(lpix = region_img->get_pixel(x + (int) look_dir.x,
					       y + (int) look_dir.y)) == CLEAR_MARK)
	    {
		region_boundary->pop();
		forward = old_tmp;
		Point2* endpoint = region_boundary->last();
		x = (int) endpoint->x;
		y = (int) endpoint->y;
	    }
	    else
	    {
		x += (int) look_dir.x;
		y += (int) look_dir.y;
		region_boundary->add_point(Point2(x,y));
		flag = true;
		forward = loop1;
		tmp = (loop1+1) & 7;
	    }
	}
	old_tmp = tmp;
    }
    while ((*(region_boundary->last()) != (*(region_boundary->first())))
	   && (region_boundary->get_no_points() < (768+576)*3)); // FIXME: how about a constant?
    region_boundary->pop();
    region_boundary->find_best_line(inv_grad, origin.x, origin.y);
    origin.x += xlo;
    origin.y += ylo;
}

istream &operator>> (istream &strmin, Region &r)
{ 
    char dummy[128];
    strmin >> dummy >> r.xlo >> r.xhi >> r.ylo >> r.yhi;
    strmin >> dummy >> r.direction;
    return strmin;
}

ostream &operator<< (ostream &strmout, const Region &r)
{ 
    strmout << "origin " << r.origin << endl;
    strmout << "old_origin " << r.old_origin << endl;
    strmout << "width " << r.width << endl;
    strmout << "height " << r.height << endl;
    strmout << "direction " << r.direction << endl;
    return strmout; 
}


//  will allocate memory for a new Profile and return pointer to it or NULL
Profile *Region::to_profile()
{
    // only use measurements, do not use predictions
    if (source != MEASUREMENT)
	return NULL;
    
    Profile *new_prf;
    PointVector tmp_pnts(0);
    if (region_boundary == NULL)
    {
	// region not traced -- use bounding box;
	Point2 centre = origin;
	realno p_grad = 0.0;
	
	new_prf = new Profile(centre, width, height, p_grad,
			   tmp_pnts, direction);
    }
    else
    {
	Point2 new_origin;
	region_boundary->find_best_line(inv_grad, new_origin.x, new_origin.y);
#ifdef REGION_USE_PRINCIPAL_AXIS
	Point2 p1 = Point2(inv_grad, 1);
	region_boundary->find_end(p1, new_origin);
#elif defined REGION_USE_HIGHEST_POINT
	region_boundary->find_end_highest(Point2(0,0), new_origin);
#elif defined REGION_USE_DIRECTION
	if (direction.length2() > 1)
	{
	    region_boundary->find_end(direction, new_origin);
#else
	    region_boundary->find_end(Point2(0,1), new_origin);
	    inv_grad = 0.0; 
#endif

	    Point2 *origin = new Point2(new_origin + Point2(xlo, ylo));
	    
		new_prf = new Profile(*origin, 
				   width, height,
				   inv_grad, tmp_pnts, direction);
		//region_boundary->find_optimal_spline(new_prf);
		region_boundary->convert_to_spline(new_prf);

#ifdef REGION_USE_DIRECTION
	}
#endif
	
    }
    if (new_prf != NULL)
    {
	// profile created.  copy over source of information
	new_prf->source = source;
    }
    
    return new_prf;
}

int Region::combine(void *pix1, void *pix2)
{
    return (int)
	((*((unsigned char*) pix1) * 10  + *((unsigned char*) pix2)) / 11);
}

int Region::and_pixels (void *pix1, void *pix2)
{
    return (int) (*((unsigned char*) pix1) & *((unsigned char*) pix2));
}

int Region::or_pixels (void *pix1, void *pix2)
{
    return (int) (*((unsigned char*) pix1) | *((unsigned char*) pix2));
}

void Region::draw_points()
{ 
#ifndef NO_DISPLAY    
    get_best_line();
    region_boundary->draw_points(xlo,ylo);
    move2((float) (-45 * inv_grad + origin.x + xlo), (float) (ylo + origin.y - 45));
    draw2((float) (65 * inv_grad + origin.x + xlo), (float) (origin.y + 65 + ylo));
#endif   // #ifndef NO_DISPLAY
}

void Region::merge(Region *reg2)
{
    int nxlo, nxhi, nylo, nyhi;
    nxlo = xlo; nxhi = xhi; nylo = ylo; nyhi = yhi;
    if (nxlo > (reg2->xlo))
	nxlo = reg2->xlo;
    if (nxhi < (reg2->xhi))
	nxhi = reg2->xhi;
    if (nylo > (reg2->ylo))
	nylo = reg2->ylo;
    if (nyhi < (reg2->yhi))
	nyhi = reg2->yhi;
    
    int nwidth = nxhi - nxlo + 1;
    int nheight = nyhi - nylo + 1;
    if (region_img != NULL)
    {
	Image *newimage = (Image*) new Grey8Image(nwidth,nheight);
	
	// because the subregions do not cover the whole newimage
	newimage->clear(0);
	
	newimage->paste_subimage(xlo - nxlo, xhi - nxlo, ylo - nylo,
				 yhi - nylo, region_img);
	newimage->paste_subimage(reg2->xlo - nxlo, reg2->xhi - nxlo,
				 reg2->ylo - nylo, reg2->yhi - nylo,
				 reg2->region_img);
	delete region_img;
	region_img = newimage;
    }
    ylo = nylo; yhi = nyhi;
    xlo = nxlo; xhi = nxhi;
    old_origin = (old_origin + reg2->old_origin) / 2;  // interpolate
    origin.x = (xlo + xhi) / 2.0;
    origin.y = (ylo + yhi) / 2.0;
    width = nwidth;
    height = nheight;
}

void Region::draw_box()
{
#ifndef NO_DISPLAY    
#ifdef USE_GL
    if (incorporated_into_background)
	setlinestyle(2);
    
    recti(xlo,ylo,xhi,yhi);

    setlinestyle(0);
#endif
#endif   // #ifndef NO_DISPLAY
}

void Region::draw_box_in_image(Image *canvas,
			       unsigned int line_width)
{
    bool dotted;
    
    if (incorporated_into_background)
	dotted = true;
    else
	dotted = false;

    // in the following we add something to image coordinates, so check
    assert (xlo < xhi);
    assert (ylo < yhi);
    
    for (unsigned int count = 0; count < line_width; count++)
    {
	canvas->draw_vertical(xlo + count, ylo, yhi, dotted);
	canvas->draw_vertical(xhi - count, ylo, yhi, dotted);
	
	canvas->draw_horizontal(ylo + count, xlo, xhi, dotted);
	canvas->draw_horizontal(yhi - count, xlo, xhi, dotted);
    }
}

} // namespace ReadingPeopleTracker