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 + -
显示快捷键?