medianfiltersource.cc

来自「VC视频对象的跟踪提取原代码(vc视频监控源码)」· CC 代码 · 共 446 行

CC
446
字号
/* * MedianFilterSource.cc   ---  a class for a median-filtered background image *  * median filter (over time) to extract background *  * defined as a PipeSource */////////////////////////////////////////////////////////////////////////////////                                                                          //// CONCEPT                                                                  ////                                                                          //// The algorithm is a much faster replacement for a median filter.  It      //// looks for runs of pixels above or below previous reference, rather than  //// computing a median.  The rationale is that outdoor lighting changes      //// usually create monotonically increasing or decreasing intensity values.  //// Therefore, alternating changes are ignored.                              ////                                                                          ////                                                                          //// HISTORY                                                                  ////                                                                          //// The algorithm was taken from the file brg.c                              //// (/home/views/d1/src/fb/brg.c on the CVG file system) which was part of   //// code generated within the VIEWS project.  The authors were Anthony       //// Worrall (The University of Reading) and John Hyde (The Marconi Co Ltd).  //// The date the algorithm was created cannot be established beyond doubt;   //// revision 1.1 of Sat Oct 17 20:39:06 1992 already featured the            //// algorithm, but the file was originally created in July 1990.             ////                                                                          //// source of information: personal communication with Anthony Worrall on    //// Wed Oct 23 2002                                                          ////                                                                          ////////////////////////////////////////////////////////////////////////////////#include "PipeSource.h"#include "MedianFilterSource.h"namespace ReadingPeopleTracker{// definition and initialisation of static member variablesconst unsigned char MedianFilterSource::ZERO = 128;// The variable *counts contains the counter for consecutive increases or// decreases of pixel values.// use byte mask, motion mask imagevoid MedianFilterSource::update_median(unsigned char *image, unsigned char *median,			  unsigned char *nearest, unsigned char *counts,			  unsigned char *enddat, int rl, unsigned char mask,			  unsigned char *motion, int mskip_h,			  int mskip_v, int mwidth){    if (motion == NULL)     {	(update_median(image, median, nearest, counts, enddat, rl, mask));	return;    }        unsigned char pix, med;    int mcount1 = mskip_h;    int mcount2 = mskip_v;    unsigned char *old_motion = motion;    unsigned char *new_motion = motion + mwidth;    for (; image < enddat; image++)    {	if (*motion == MARK)	{ 	    pix = *image & mask;	    med = *median & mask;	    if (pix == *median) (*counts = ZERO);	    else {		if (*counts < ZERO)		{		    if (pix < med)		    {			(*counts)++;			if (pix > (*nearest & mask)) 			    *nearest = (*nearest & ~mask) | pix;						if (*counts == ZERO)			    *median = (*median & ~mask) | *nearest;		    }		    else *counts = ZERO;		}		else if (*counts > ZERO)		{		    if (pix > med)		    {			(*counts)--;			if (pix < (*nearest & mask)) 			    *nearest = (*nearest & ~mask) | pix;			if (*counts == ZERO)			    *median = (*median & ~mask) | *nearest;		    }		    else  *counts = ZERO;		}		else 		{		    if (pix < med)		    {			*counts = ZERO - rl;			*nearest = (*nearest & ~mask) | pix;		    }		    else if (pix > med)		    {			*counts = rl + ZERO;			*nearest = (*nearest & ~mask) | pix;		    }		}	    }	}	counts++;	median++;	nearest++;		if (--mcount1 == 0)	{	    mcount1 = mskip_h;	    if (++motion == new_motion)	    {		if (--mcount2 == 0)		{		    mcount2 = mskip_v;		    old_motion = motion;		    new_motion = motion + mwidth;		}		else motion = old_motion;	    }	}	    }}// use byte mask void MedianFilterSource::update_median(unsigned char *image, unsigned char *median,				       unsigned char *nearest, unsigned char *counts,				       unsigned char *enddat, int rl, unsigned char mask){    unsigned char pix, med;    for (; image < enddat; image++)    {	pix = *image & mask;	med = *median & mask;	if (pix == *median) (*counts = ZERO);	else {	    if (*counts < ZERO)	    {		if (pix < med)		{		    (*counts)++;		    if (pix > (*nearest & mask)) *nearest = (*nearest & ~mask) | pix;		    if (*counts == ZERO) *median = (*median & ~mask) | *nearest;		}		else *counts = ZERO;	    }	    else if (*counts > ZERO)	    {		if (pix > med)		{		    (*counts)--;		    if (pix < (*nearest & mask)) *nearest = (*nearest & ~mask) | pix;		    if (*counts == ZERO) *median = (*median & ~mask) | *nearest;		}		else  *counts = ZERO;	    }	    else 	    {		if (pix < med)		{		    *counts = ZERO - rl;		    *nearest = (*nearest & ~mask) | pix;		}		else if (pix > med)		{		    *counts = rl + ZERO;		    *nearest = (*nearest & ~mask) | pix;		}	    }	}	counts++;	median++;	nearest++;    }}////////   this one is called by recalc()   /////////// no byte mask, use motion maskvoid MedianFilterSource::update_median(unsigned char *image, unsigned char *median,				       unsigned char *nearest, unsigned char *counts,				       unsigned char *enddat, int rl, 				       unsigned char *motion, int mskip_h,				       int mskip_v, int mwidth){        if (motion == NULL)    {	update_median(image, median, nearest, counts, enddat, rl);	return;    }    unsigned char pix, med;    int mcount1 = mskip_h;    int mcount2 = mskip_v;    unsigned char *old_motion = motion;    unsigned char *new_motion = motion + mwidth;    for (; image < enddat; image++)    {	if (*motion == MARK)	{	    pix = *image;	    med = *median;	    if (pix == *median) (*counts = ZERO);	    else {		if (*counts < ZERO)		{		    if (pix < med)		    {			(*counts)++;			if (pix > *nearest) *nearest = pix;			if (*counts == ZERO) *median = *nearest;		    }		    else *counts = ZERO;		}		else if (*counts > ZERO)		{		    if (pix > med)		    {			(*counts)--;			if (pix < *nearest) *nearest = pix;			if (*counts == ZERO) *median = *nearest;		    }		    else  *counts = ZERO;		}		else 		{		    if (pix < med)		    {			*counts = ZERO - rl;			*nearest = pix;		    }		    else if (pix > med)		    {			*counts = rl + ZERO;			*nearest = pix;		    }		}	    }	}	counts++;	median++;	nearest++;  	if (--mcount1 == 0)	{	    mcount1 = mskip_h;	    if (++motion == new_motion)	    {		if (--mcount2 == 0)		{		    mcount2 = mskip_v;		    old_motion = motion;		    new_motion = motion + mwidth;		}		else motion = old_motion;	    }	}    }}// no byte mask, no motion maskvoid MedianFilterSource::update_median(unsigned char *image, unsigned char *median,			  unsigned char *nearest, unsigned char *counts,			  unsigned char *enddat, int rl){    unsigned char pix, med;    for ( ; image < enddat; image++)    {	pix = *image;	med = *median;	if (pix == med)	    *counts = ZERO;	else	{	    if (*counts < ZERO)	    {		if (pix < med)		{		    (*counts)++;		    if (pix > *nearest)			*nearest = pix;		    if (*counts == ZERO)			*median = *nearest;		}		else		    *counts = ZERO;	    }	    else		if (*counts > ZERO)		{		    if (pix > med)		    {			(*counts)--;						if (pix < *nearest)			    *nearest = pix;						if (*counts == ZERO)			    *median = *nearest;		    }		    else			*counts = ZERO;		}		else  //  (*counts == ZERO)		{		    if (pix < med)		    {			*counts = ZERO - rl;			*nearest = pix;		    }		    else  //  (pix > med)		    {			*counts = rl + ZERO;			*nearest = pix;		    }		}	}	counts++;	median++;	nearest++;    }}MedianFilterSource::MedianFilterSource(ImageSource *s,				       unsigned int the_run_length,				       Image *initial_background_image) : PipeSource(s){    //in_source = s;    run_length = the_run_length;    counts_red = counts_green = counts_blue  = nearest = NULL;    //(put into PipeSource)   motion_mask = NULL;    if (initial_background_image != NULL)    {	current = initial_background_image->copy();//  nts: replaced the following hack with the above --- should do the same?!  Feb 2002//  	ImageSource in2(background_image);//  	in = &in2;//  	refresh();//  	in = s; //  	in2.set_current(NULL);	// prevent back from being deleted	counts_red = current->copy_type();	nearest = current->copy_type();	counts_red->clear(ZERO);    }    refresh();}void MedianFilterSource::restart(){        if (counts_green != NULL) counts_green->clear(ZERO);    if (counts_blue != NULL) counts_blue->clear(ZERO);    if (counts_red != NULL) counts_red->clear(ZERO);        Image *in_curr = in->get_current();    if (in_curr != NULL)	current = in_curr->copy(current);    }Image *MedianFilterSource::recalc(){    Image *in_curr = in->get_current();    if (in_curr == NULL)	return NULL;    unsigned int w = in_curr->get_width();    unsigned int h = in_curr->get_height();     unsigned int mskip_h = 0;    unsigned int mskip_v = 0;    unsigned int mwidth = 0;    unsigned char *motion = NULL;        if (motion_mask != NULL)     {	motion = motion_mask->get_data();	mwidth = motion_mask->get_width() * motion_mask->get_bytes_per_pixel();	mskip_h = (w * in_curr->get_bytes_per_pixel()) / mwidth;	mskip_v = h / motion_mask->get_height();    }        switch(in_curr->get_image_type())    {    case GREY8:    case RGB32:    case HSV32:   // added by nts 03/05/01    {	if (current == NULL)	{	    current = in_curr->copy();	    counts_red = in_curr->copy_type();	    nearest = in_curr->copy_type();	    counts_red->clear(ZERO);		}    	else	{	    // no byte mask, use motion mask	    update_median (in_curr->get_data(), current->get_data(),			   nearest->get_data(), counts_red->get_data(),			   in_curr->get_end_data(), run_length,			   motion, mskip_h,			   mskip_v, mwidth);	}	break;    }    case BASE:	cerror << "MedianFilterSource::recalc:  Warning:  BASE pixel encountered." << endl;    }    return current;}// Image *MedianFilterSource::get_next()// {//   frame_count++;//   if (in->get_next() != NULL) return refresh();//   else return NULL;// }MedianFilterSource::~MedianFilterSource(){    delete counts_red;    if (counts_green != NULL) delete counts_green;    if (counts_blue != NULL) delete counts_blue;    delete nearest;    delete current;}} // namespace ReadingPeopleTracker

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?