Merged in alarm checking scope feature.

git-svn-id: http://svn.zoneminder.com/svn/zm/trunk@855 e3e1d417-86f3-4887-817a-d78f3d33393f
This commit is contained in:
stan 2004-02-15 20:02:41 +00:00
parent 626d91fd29
commit 571798f879
9 changed files with 314 additions and 245 deletions

View File

@ -3,6 +3,7 @@
--
-- Make changes to Filter table
--
alter table Zones add column CheckMethod enum('AlarmedPixels','FilteredPixels','Blobs') NOT NULL default 'Blobs' after AlarmRGB;
alter table Filters drop column MonitorId;
alter table Filters drop index FilterIDX;
--

View File

@ -204,6 +204,7 @@ CREATE TABLE Zones (
HiX smallint(5) unsigned NOT NULL default '0',
HiY smallint(5) unsigned NOT NULL default '0',
AlarmRGB int(10) unsigned default NULL,
CheckMethod enum('AlarmedPixels','FilteredPixels','Blobs') NOT NULL default 'Blobs',
MinPixelThreshold smallint(5) unsigned default NULL,
MaxPixelThreshold smallint(5) unsigned default NULL,
MinAlarmPixels int(10) unsigned default NULL,

View File

@ -51,6 +51,7 @@ public:
inline const Coord &Size() const { return( size ); }
inline int Width() const { return( size.X() ); }
inline int Height() const { return( size.Y() ); }
inline int Area() const { return( size.X()*size.Y() ); }
inline bool Inside( const Coord &coord ) const
{

View File

@ -133,7 +133,7 @@ public:
inline int Width() { return( width ); }
inline int Height() { return( height ); }
JSAMPLE *Buffer( unsigned int x=0, unsigned int y= 0 ) { return( &buffer[colours*((y*width)+x)] ); }
inline JSAMPLE *Buffer( unsigned int x=0, unsigned int y= 0 ) { return( &buffer[colours*((y*width)+x)] ); }
inline void Assign( int p_width, int p_height, int p_colours, unsigned char *new_buffer )
{

View File

@ -244,7 +244,7 @@ void Monitor::Setup()
{
n_zones = 1;
zones = new Zone *[1];
zones[0] = new Zone( this, 0, "All", Zone::ACTIVE, Box( width, height ), RGB_RED );
zones[0] = new Zone( this, 0, "All", Zone::ACTIVE, Box( width, height ), RGB_RED, Zone::BLOBS );
}
start_time = last_fps_time = time( 0 );

View File

@ -26,7 +26,7 @@
bool Zone::initialised = false;
bool Zone::record_diag_images;
void Zone::Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Box &p_limits, const Rgb p_alarm_rgb, int p_min_pixel_threshold, int p_max_pixel_threshold, int p_min_alarm_pixels, int p_max_alarm_pixels, const Coord &p_filter_box, int p_min_filter_pixels, int p_max_filter_pixels, int p_min_blob_pixels, int p_max_blob_pixels, int p_min_blobs, int p_max_blobs )
void Zone::Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Box &p_limits, const Rgb p_alarm_rgb, CheckMethod p_check_method, int p_min_pixel_threshold, int p_max_pixel_threshold, int p_min_alarm_pixels, int p_max_alarm_pixels, const Coord &p_filter_box, int p_min_filter_pixels, int p_max_filter_pixels, int p_min_blob_pixels, int p_max_blob_pixels, int p_min_blobs, int p_max_blobs )
{
if ( !initialised )
Initialise();
@ -39,6 +39,7 @@ void Zone::Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_
type = p_type;
limits = p_limits;
alarm_rgb = p_alarm_rgb;
check_method = p_check_method;
min_pixel_threshold = p_min_pixel_threshold;
max_pixel_threshold = p_max_pixel_threshold;
min_alarm_pixels = p_min_alarm_pixels;
@ -51,7 +52,7 @@ void Zone::Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_
min_blobs = p_min_blobs;
max_blobs = p_max_blobs;
Info(( "Initialised zone %d/%s - %d - %dx%d - Rgb:%06x, MnAT:%d, MxAT:%d, MnAP:%d, MxAP:%d, FB:%dx%d, MnFP:%d, MxFP:%d, MnBS:%d, MxBS:%d, MnB:%d, MxB:%d", id, label, type, limits.Width(), limits.Height(), alarm_rgb, min_pixel_threshold, max_pixel_threshold, min_alarm_pixels, max_alarm_pixels, filter_box.X(), filter_box.Y(), min_filter_pixels, max_filter_pixels, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs ));
Info(( "Initialised zone %d/%s - %d - %dx%d - Rgb:%06x, CM:%d, MnAT:%d, MxAT:%d, MnAP:%d, MxAP:%d, FB:%dx%d, MnFP:%d, MxFP:%d, MnBS:%d, MxBS:%d, MnB:%d, MxB:%d", id, label, type, limits.Width(), limits.Height(), alarm_rgb, check_method, min_pixel_threshold, max_pixel_threshold, min_alarm_pixels, max_alarm_pixels, filter_box.X(), filter_box.Y(), min_filter_pixels, max_filter_pixels, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs ));
alarmed = false;
alarm_pixels = 0;
@ -88,15 +89,19 @@ bool Zone::CheckAlarms( const Image *delta_image )
ResetStats();
delete image;
// Get the difference image
Image *diff_image = image = new Image( *delta_image );
alarm_pixels = 0;
int alarm_lo_x = 0;
int alarm_hi_x = 0;
int alarm_lo_y = 0;
int alarm_hi_y = 0;
// Get the difference image
int lo_x = limits.Lo().X();
int lo_y = limits.Lo().Y();
int hi_x = limits.Hi().X();
int hi_y = limits.Hi().Y();
for ( int y = lo_y; y <= hi_y; y++ )
{
unsigned char *pdiff = diff_image->Buffer( lo_x, y );
@ -106,9 +111,11 @@ bool Zone::CheckAlarms( const Image *delta_image )
{
*pdiff = WHITE;
alarm_pixels++;
continue;
}
*pdiff = BLACK;
else
{
*pdiff = BLACK;
}
}
}
if ( record_diag_images )
@ -121,61 +128,65 @@ bool Zone::CheckAlarms( const Image *delta_image )
diff_image->WriteJpeg( diag_path );
}
if ( !alarm_pixels ) return( false );
if ( min_alarm_pixels && alarm_pixels < min_alarm_pixels ) return( false );
if ( max_alarm_pixels && alarm_pixels > max_alarm_pixels ) return( false );
alarm_filter_pixels = 0;
score = (100*alarm_pixels)/(limits.Size().X()*limits.Size().Y());
int bx = filter_box.X();
int by = filter_box.Y();
int bx1 = bx-1;
int by1 = by-1;
if ( bx > 1 || by > 1 )
if ( check_method >= FILTERED_PIXELS )
{
// Now remove any pixels smaller than our filter size
for ( int y = lo_y; y <= hi_y; y++ )
int bx = filter_box.X();
int by = filter_box.Y();
int bx1 = bx-1;
int by1 = by-1;
if ( bx > 1 || by > 1 )
{
unsigned char *pdiff = diff_image->Buffer( lo_x, y );
for ( int x = lo_x; x <= hi_x; x++, pdiff++ )
// Now remove any pixels smaller than our filter size
unsigned char *pdiff;
unsigned char *cpdiff;
int ldx, hdx, ldy, hdy;
bool block;
for ( int y = lo_y; y <= hi_y; y++ )
{
if ( *pdiff == WHITE )
{
// Check participation in an X blob
int ldx = (x>=(lo_x+bx1))?-bx1:lo_x-x;
int hdx = (x<=(hi_x-bx1))?0:((hi_x-x)-bx1);
int ldy = (y>=(lo_y+by1))?-by1:lo_y-y;
int hdy = (y<=(hi_y-by1))?0:((hi_y-y)-by1);
bool blob = false;
for ( int dy = ldy; !blob && dy <= hdy; dy++ )
{
for ( int dx = ldx; !blob && dx <= hdx; dx++ )
{
blob = true;
for ( int dy2 = 0; blob && dy2 < by; dy2++ )
{
for ( int dx2 = 0; blob && dx2 < bx; dx2++ )
{
unsigned char *cpdiff = diff_image->Buffer( x+dx+dx2, y+dy+dy2 );
pdiff = diff_image->Buffer( lo_x, y );
if ( !*cpdiff )
for ( int x = lo_x; x <= hi_x; x++, pdiff++ )
{
if ( *pdiff == WHITE )
{
// Check participation in an X block
ldx = (x>=(lo_x+bx1))?-bx1:lo_x-x;
hdx = (x<=(hi_x-bx1))?0:((hi_x-x)-bx1);
ldy = (y>=(lo_y+by1))?-by1:lo_y-y;
hdy = (y<=(hi_y-by1))?0:((hi_y-y)-by1);
block = false;
for ( int dy = ldy; !block && dy <= hdy; dy++ )
{
for ( int dx = ldx; !block && dx <= hdx; dx++ )
{
block = true;
for ( int dy2 = 0; block && dy2 < by; dy2++ )
{
for ( int dx2 = 0; block && dx2 < bx; dx2++ )
{
blob = false;
cpdiff = diff_image->Buffer( x+dx+dx2, y+dy+dy2 );
if ( !*cpdiff )
{
block = false;
}
}
}
}
}
if ( !block )
{
*pdiff = BLACK;
continue;
}
alarm_filter_pixels++;
}
if ( !blob )
{
*pdiff = BLACK;
continue;
}
alarm_filter_pixels++;
}
}
}
@ -192,225 +203,220 @@ bool Zone::CheckAlarms( const Image *delta_image )
if ( !alarm_filter_pixels ) return( false );
if ( min_filter_pixels && alarm_filter_pixels < min_filter_pixels ) return( false );
if ( max_filter_pixels && alarm_filter_pixels > max_filter_pixels ) return( false );
}
alarm_blobs = 0;
score = (100*alarm_filter_pixels)/(limits.Size().X()*limits.Size().Y());
typedef struct { unsigned char tag; int count; int lo_x; int hi_x; int lo_y; int hi_y; } BlobStats;
BlobStats blob_stats[256];
memset( blob_stats, 0, sizeof(BlobStats)*256 );
for ( int y = lo_y; y <= hi_y; y++ )
{
unsigned char *pdiff = diff_image->Buffer( lo_x, y );
for ( int x = lo_x; x <= hi_x; x++, pdiff++ )
if ( check_method >= BLOBS )
{
if ( *pdiff == WHITE )
typedef struct { unsigned char tag; int count; int lo_x; int hi_x; int lo_y; int hi_y; } BlobStats;
BlobStats blob_stats[256];
memset( blob_stats, 0, sizeof(BlobStats)*256 );
unsigned char *pdiff, *spdiff;
int lx, ly;
BlobStats *bsx, *bsy;
BlobStats *bsm, *bss;
for ( int y = lo_y; y <= hi_y; y++ )
{
//printf( "Got white pixel at %d,%d (%x)\n", x, y, pdiff );
int lx = x>lo_x?*(pdiff-1):0;
int ly = y>lo_y?*(pdiff-diff_image->Width()):0;
if ( lx )
pdiff = diff_image->Buffer( lo_x, y );
for ( int x = lo_x; x <= hi_x; x++, pdiff++ )
{
//printf( "Left neighbour is %d\n", lx );
BlobStats *bsx = &blob_stats[lx];
if ( ly )
if ( *pdiff == WHITE )
{
//printf( "Top neighbour is %d\n", ly );
BlobStats *bsy = &blob_stats[ly];
if ( lx == ly )
//printf( "Got white pixel at %d,%d (%x)\n", x, y, pdiff );
lx = x>lo_x?*(pdiff-1):0;
ly = y>lo_y?*(pdiff-diff_image->Width()):0;
if ( lx )
{
//printf( "Matching neighbours, setting to %d\n", lx );
// Add to the blob from the x side (either side really)
*pdiff = lx;
bsx->count++;
//if ( x < bsx->lo_x ) bsx->lo_x = x;
//if ( y < bsx->lo_y ) bsx->lo_y = y;
if ( x > bsx->hi_x ) bsx->hi_x = x;
if ( y > bsx->hi_y ) bsx->hi_y = y;
//printf( "Left neighbour is %d\n", lx );
bsx = &blob_stats[lx];
if ( ly )
{
//printf( "Top neighbour is %d\n", ly );
bsy = &blob_stats[ly];
if ( lx == ly )
{
//printf( "Matching neighbours, setting to %d\n", lx );
// Add to the blob from the x side (either side really)
*pdiff = lx;
bsx->count++;
if ( x > bsx->hi_x ) bsx->hi_x = x;
if ( y > bsx->hi_y ) bsx->hi_y = y;
}
else
{
// Aggregate blobs
bsm = bsx->count>=bsy->count?bsx:bsy;
bss = bsm==bsx?bsy:bsx;
//printf( "Different neighbours, setting pixels of %d to %d\n", bss->tag, bsm->tag );
// Now change all those pixels to the other setting
for ( int sy = bss->lo_y; sy <= bss->hi_y; sy++ )
{
spdiff = diff_image->Buffer( bss->lo_x, sy );
for ( int sx = bss->lo_x; sx <= bss->hi_x; sx++, spdiff++ )
{
//printf( "Pixel at %d,%d (%x) is %d", sx, sy, spdiff, *spdiff );
if ( *spdiff == bss->tag )
{
//printf( ", setting" );
*spdiff = bsm->tag;
}
//printf( "\n" );
}
}
*pdiff = bsm->tag;
// Merge the slave blob into the master
bsm->count += bss->count+1;
if ( x > bsm->hi_x ) bsm->hi_x = x;
if ( y > bsm->hi_y ) bsm->hi_y = y;
if ( bss->lo_x < bsm->lo_x ) bsm->lo_x = bss->lo_x;
if ( bss->lo_y < bsm->lo_y ) bsm->lo_y = bss->lo_y;
if ( bss->hi_x > bsm->hi_x ) bsm->hi_x = bss->hi_x;
if ( bss->hi_y > bsm->hi_y ) bsm->hi_y = bss->hi_y;
// Clear out the old blob
bss->tag = 0;
bss->count = 0;
bss->lo_x = 0;
bss->lo_y = 0;
bss->hi_x = 0;
bss->hi_y = 0;
alarm_blobs--;
}
}
else
{
//printf( "Setting to left neighbour %d\n", lx );
// Add to the blob from the x side
*pdiff = lx;
bsx->count++;
if ( x > bsx->hi_x ) bsx->hi_x = x;
if ( y > bsx->hi_y ) bsx->hi_y = y;
}
}
else
{
// Aggregate blobs
BlobStats *bsm = bsx->count>=bsy->count?bsx:bsy;
BlobStats *bss = bsm==bsx?bsy:bsx;
//printf( "Different neighbours, setting pixels of %d to %d\n", bss->tag, bsm->tag );
// Now change all those pixels to the other setting
for ( int sy = bss->lo_y; sy <= bss->hi_y; sy++ )
if ( ly )
{
unsigned char *spdiff = diff_image->Buffer( bss->lo_x, sy );
for ( int sx = bss->lo_x; sx <= bss->hi_x; sx++, spdiff++ )
//printf( "Setting to top neighbour %d\n", ly );
// Add to the blob from the y side
BlobStats *bsy = &blob_stats[ly];
*pdiff = ly;
bsy->count++;
if ( x > bsy->hi_x ) bsy->hi_x = x;
if ( y > bsy->hi_y ) bsy->hi_y = y;
}
else
{
// Create a new blob
//for ( int i = 1; i < WHITE; i++ )
for ( int i = WHITE; i > 0; i-- )
{
//printf( "Pixel at %d,%d (%x) is %d", sx, sy, spdiff, *spdiff );
if ( *spdiff == bss->tag )
BlobStats *bs = &blob_stats[i];
if ( !bs->count )
{
//printf( ", setting" );
*spdiff = bsm->tag;
//printf( "Creating new blob %d\n", i );
*pdiff = i;
bs->tag = i;
bs->count++;
bs->lo_x = bs->hi_x = x;
bs->lo_y = bs->hi_y = y;
alarm_blobs++;
break;
}
//printf( "\n" );
}
}
*pdiff = bsm->tag;
// Merge the slave blob into the master
bsm->count += bss->count+1;
if ( x > bsm->hi_x ) bsm->hi_x = x;
if ( y > bsm->hi_y ) bsm->hi_y = y;
if ( bss->lo_x < bsm->lo_x ) bsm->lo_x = bss->lo_x;
if ( bss->lo_y < bsm->lo_y ) bsm->lo_y = bss->lo_y;
if ( bss->hi_x > bsm->hi_x ) bsm->hi_x = bss->hi_x;
if ( bss->hi_y > bsm->hi_y ) bsm->hi_y = bss->hi_y;
// Clear out the old blob
bss->tag = 0;
bss->count = 0;
bss->lo_x = 0;
bss->lo_y = 0;
bss->hi_x = 0;
bss->hi_y = 0;
alarm_blobs--;
}
}
else
}
}
if ( (bool)config.Item( ZM_RECORD_DIAG_IMAGES ) )
{
static char diag_path[PATH_MAX] = "";
if ( !diag_path[0] )
{
sprintf( diag_path, "%s/%s/diag-%d-%d.jpg", (const char *)config.Item( ZM_DIR_EVENTS ), monitor->Name(), id, 3 );
}
diff_image->WriteJpeg( diag_path );
}
if ( !alarm_blobs ) return( false );
alarm_blob_pixels = alarm_filter_pixels;
// Now eliminate blobs under the threshold
for ( int i = 1; i < WHITE; i++ )
{
BlobStats *bs = &blob_stats[i];
if ( bs->count && ((min_blob_pixels && bs->count < min_blob_pixels) || (max_blob_pixels && bs->count > max_blob_pixels)) )
{
//Info(( "Eliminating blob %d, %d pixels (%d,%d - %d,%d)", i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y ));
for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ )
{
//printf( "Setting to left neighbour %d\n", lx );
// Add to the blob from the x side
*pdiff = lx;
bsx->count++;
//if ( x < bsx->lo_x ) bsx->lo_x = x;
//if ( y < bsx->lo_y ) bsx->lo_y = y;
if ( x > bsx->hi_x ) bsx->hi_x = x;
if ( y > bsx->hi_y ) bsx->hi_y = y;
unsigned char *spdiff = diff_image->Buffer( bs->lo_x, sy );
for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ )
{
if ( *spdiff == bs->tag )
{
*spdiff = BLACK;
}
}
}
alarm_blobs--;
alarm_blob_pixels -= bs->count;
bs->tag = 0;
bs->count = 0;
bs->lo_x = 0;
bs->lo_y = 0;
bs->hi_x = 0;
bs->hi_y = 0;
}
else
{
if ( ly )
if ( bs->count )
{
//printf( "Setting to top neighbour %d\n", ly );
// Add to the blob from the y side
BlobStats *bsy = &blob_stats[ly];
*pdiff = ly;
bsy->count++;
//if ( x < bsy->lo_x ) bsy->lo_x = x;
//if ( y < bsy->lo_y ) bsy->lo_y = y;
if ( x > bsy->hi_x ) bsy->hi_x = x;
if ( y > bsy->hi_y ) bsy->hi_y = y;
}
else
{
// Create a new blob
//for ( int i = 1; i < WHITE; i++ )
for ( int i = WHITE; i > 0; i-- )
{
BlobStats *bs = &blob_stats[i];
if ( !bs->count )
{
//printf( "Creating new blob %d\n", i );
*pdiff = i;
bs->tag = i;
bs->count++;
bs->lo_x = bs->hi_x = x;
bs->lo_y = bs->hi_y = y;
alarm_blobs++;
break;
}
}
if ( !min_blob_size || bs->count < min_blob_size ) min_blob_size = bs->count;
if ( !max_blob_size || bs->count > max_blob_size ) max_blob_size = bs->count;
}
}
}
}
}
if ( record_diag_images )
{
static char diag_path[PATH_MAX] = "";
if ( !diag_path[0] )
{
sprintf( diag_path, "%s/%s/diag-%d-%d.jpg", (const char *)config.Item( ZM_DIR_EVENTS ), monitor->Name(), id, 3 );
}
diff_image->WriteJpeg( diag_path );
}
if ( !alarm_blobs ) return( false );
alarm_blob_pixels = alarm_filter_pixels;
min_blob_size = 0;
max_blob_size = 0;
// Now eliminate blobs outside the thresholds
for ( int i = 1; i < WHITE; i++ )
{
BlobStats *bs = &blob_stats[i];
if ( bs->count && ((min_blob_pixels && bs->count < min_blob_pixels) || (max_blob_pixels && bs->count > max_blob_pixels)) )
{
//Info(( "Eliminating blob %d, %d pixels (%d,%d - %d,%d)", i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y ));
for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ )
if ( record_diag_images )
{
unsigned char *spdiff = diff_image->Buffer( bs->lo_x, sy );
for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ )
static char diag_path[PATH_MAX] = "";
if ( !diag_path[0] )
{
if ( *spdiff == bs->tag )
{
*spdiff = BLACK;
}
sprintf( diag_path, "%s/%s/diag-%d-%d.jpg", (const char *)config.Item( ZM_DIR_EVENTS ), monitor->Name(), id, 4 );
}
diff_image->WriteJpeg( diag_path );
}
if ( !alarm_blobs ) return( false );
if ( min_blobs && alarm_blobs < min_blobs ) return( false );
if ( max_blobs && alarm_blobs > max_blobs ) return( false );
alarm_lo_x = hi_x+1;
alarm_hi_x = lo_x-1;
alarm_lo_y = hi_y+1;
alarm_hi_y = lo_y-1;
for ( int i = 1; i < WHITE; i++ )
{
BlobStats *bs = &blob_stats[i];
if ( bs->count )
{
if ( alarm_lo_x > bs->lo_x ) alarm_lo_x = bs->lo_x;
if ( alarm_lo_y > bs->lo_y ) alarm_lo_y = bs->lo_y;
if ( alarm_hi_x < bs->hi_x ) alarm_hi_x = bs->hi_x;
if ( alarm_hi_y < bs->hi_y ) alarm_hi_y = bs->hi_y;
}
}
alarm_blobs--;
alarm_blob_pixels -= bs->count;
bs->tag = 0;
bs->count = 0;
bs->lo_x = 0;
bs->lo_y = 0;
bs->hi_x = 0;
bs->hi_y = 0;
}
else
{
if ( bs->count )
{
if ( !min_blob_size || bs->count < min_blob_size ) min_blob_size = bs->count;
if ( !max_blob_size || bs->count > max_blob_size ) max_blob_size = bs->count;
}
}
}
if ( record_diag_images )
{
static char diag_path[PATH_MAX] = "";
if ( !diag_path[0] )
{
sprintf( diag_path, "%s/%s/diag-%d-%d.jpg", (const char *)config.Item( ZM_DIR_EVENTS ), monitor->Name(), id, 4 );
}
diff_image->WriteJpeg( diag_path );
}
if ( !alarm_blobs ) return( false );
if ( min_blobs && alarm_blobs < min_blobs ) return( false );
if ( max_blobs && alarm_blobs > max_blobs ) return( false );
int alarm_lo_x = hi_x+1;
int alarm_hi_x = lo_x-1;
int alarm_lo_y = hi_y+1;
int alarm_hi_y = lo_y-1;
for ( int i = 1; i < WHITE; i++ )
{
BlobStats *bs = &blob_stats[i];
if ( bs->count )
{
if ( alarm_lo_x > bs->lo_x ) alarm_lo_x = bs->lo_x;
if ( alarm_lo_y > bs->lo_y ) alarm_lo_y = bs->lo_y;
if ( alarm_hi_x < bs->hi_x ) alarm_hi_x = bs->hi_x;
if ( alarm_hi_y < bs->hi_y ) alarm_hi_y = bs->hi_y;
score = ((100*alarm_blob_pixels)/int(sqrt((double)alarm_blobs)))/(limits.Size().X()*limits.Size().Y());
}
}
alarm_box = Box( Coord( alarm_lo_x, alarm_lo_y ), Coord( alarm_hi_x, alarm_hi_y ) );
score = ((100*alarm_blob_pixels)/int(sqrt((double)alarm_blobs)))/(limits.Size().X()*limits.Size().Y());
if ( type == INCLUSIVE )
{
score /= 2;
@ -421,14 +427,15 @@ bool Zone::CheckAlarms( const Image *delta_image )
}
// Now outline the changed region
if ( alarm_blobs )
if ( score )
{
alarm = true;
if ( (type < PRECLUSIVE) && (bool)config.Item( ZM_CREATE_ANALYSIS_IMAGES ) )
alarm_box = Box( Coord( alarm_lo_x, alarm_lo_y ), Coord( alarm_hi_x, alarm_hi_y ) );
if ( (type < PRECLUSIVE) && check_method >= BLOBS && (bool)config.Item( ZM_CREATE_ANALYSIS_IMAGES ) )
{
image = diff_image->HighlightEdges( alarm_rgb, &limits );
// Only need to delete this when 'image' becomes detached and points somewhere else
delete diff_image;
}
@ -441,7 +448,7 @@ bool Zone::CheckAlarms( const Image *delta_image )
int Zone::Load( Monitor *monitor, Zone **&zones )
{
static char sql[BUFSIZ];
sprintf( sql, "select Id,Name,Type+0,Units,LoX,LoY,HiX,HiY,AlarmRGB,MinPixelThreshold,MaxPixelThreshold,MinAlarmPixels,MaxAlarmPixels,FilterX,FilterY,MinFilterPixels,MaxFilterPixels,MinBlobPixels,MaxBlobPixels,MinBlobs,MaxBlobs from Zones where MonitorId = %d order by Type, Id", monitor->Id() );
sprintf( sql, "select Id,Name,Type+0,Units,LoX,LoY,HiX,HiY,AlarmRGB,CheckMethod,MinPixelThreshold,MaxPixelThreshold,MinAlarmPixels,MaxAlarmPixels,FilterX,FilterY,MinFilterPixels,MaxFilterPixels,MinBlobPixels,MaxBlobPixels,MinBlobs,MaxBlobs from Zones where MonitorId = %d order by Type, Id", monitor->Id() );
if ( mysql_query( &dbconn, sql ) )
{
Error(( "Can't run query: %s", mysql_error( &dbconn ) ));
@ -471,6 +478,7 @@ int Zone::Load( Monitor *monitor, Zone **&zones )
int HiX = atoi(dbrow[col++]);
int HiY = atoi(dbrow[col++]);
int AlarmRGB = dbrow[col]?atoi(dbrow[col]):0; col++;
int CheckMethod = atoi(dbrow[col++]);
int MinPixelThreshold = dbrow[col]?atoi(dbrow[col]):0; col++;
int MaxPixelThreshold = dbrow[col]?atoi(dbrow[col]):0; col++;
int MinAlarmPixels = dbrow[col]?atoi(dbrow[col]):0; col++;
@ -504,7 +512,7 @@ int Zone::Load( Monitor *monitor, Zone **&zones )
}
else
{
zones[i] = new Zone( monitor, Id, Name, (Zone::ZoneType)Type, Box( LoX, LoY, HiX, HiY ), AlarmRGB, MinPixelThreshold, MaxPixelThreshold, MinAlarmPixels, MaxAlarmPixels, Coord( FilterX, FilterY ), MinFilterPixels, MaxFilterPixels, MinBlobPixels, MaxBlobPixels, MinBlobs, MaxBlobs );
zones[i] = new Zone( monitor, Id, Name, (Zone::ZoneType)Type, Box( LoX, LoY, HiX, HiY ), AlarmRGB, (Zone::CheckMethod)CheckMethod, MinPixelThreshold, MaxPixelThreshold, MinAlarmPixels, MaxAlarmPixels, Coord( FilterX, FilterY ), MinFilterPixels, MaxFilterPixels, MinBlobPixels, MaxBlobPixels, MinBlobs, MaxBlobs );
}
}
if ( mysql_errno( &dbconn ) )
@ -532,6 +540,11 @@ bool Zone::DumpSettings( char *output, bool /*verbose*/ )
)))));
sprintf( output+strlen(output), " Limits : %d,%d - %d,%d\n", limits.LoX(), limits.LoY(), limits.HiX(), limits.HiY() );
sprintf( output+strlen(output), " Alarm RGB : %06x\n", alarm_rgb );
sprintf( output+strlen(output), " Check Method: %d - %s\n", check_method,
check_method==ALARMED_PIXELS?"Alarmed Pixels":(
check_method==FILTERED_PIXELS?"FilteredPixels":(
check_method==BLOBS?"Blobs":"Unknown"
)));
sprintf( output+strlen(output), " Min Pixel Threshold : %d\n", min_pixel_threshold );
sprintf( output+strlen(output), " Max Pixel Threshold : %d\n", max_pixel_threshold );
sprintf( output+strlen(output), " Min Alarm Pixels : %d\n", min_alarm_pixels );

View File

@ -36,6 +36,7 @@ class Zone
{
public:
typedef enum { ACTIVE=1, INCLUSIVE, EXCLUSIVE, PRECLUSIVE, INACTIVE } ZoneType;
typedef enum { ALARMED_PIXELS=1, FILTERED_PIXELS, BLOBS } CheckMethod;
protected:
static bool initialised;
@ -50,6 +51,7 @@ protected:
ZoneType type;
Box limits;
Rgb alarm_rgb;
CheckMethod check_method;
int min_pixel_threshold;
int max_pixel_threshold;
@ -85,20 +87,20 @@ protected:
record_diag_images = (bool)config.Item( ZM_RECORD_DIAG_IMAGES );
}
void Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Box &p_limits, const Rgb p_alarm_rgb, int p_min_pixel_threshold, int p_max_pixel_threshold, int p_min_alarm_pixels, int p_max_alarm_pixels, const Coord &p_filter_box, int p_min_filter_pixels, int p_max_filter_pixels, int p_min_blob_pixels, int p_max_blob_pixels, int p_min_blobs, int p_max_blobs );
void Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Box &p_limits, const Rgb p_alarm_rgb, CheckMethod p_check_method, int p_min_pixel_threshold, int p_max_pixel_threshold, int p_min_alarm_pixels, int p_max_alarm_pixels, const Coord &p_filter_box, int p_min_filter_pixels, int p_max_filter_pixels, int p_min_blob_pixels, int p_max_blob_pixels, int p_min_blobs, int p_max_blobs );
public:
Zone( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Box &p_limits, const Rgb p_alarm_rgb, int p_min_pixel_threshold=15, int p_max_pixel_threshold=0, int p_min_alarm_pixels=50, int p_max_alarm_pixels=75000, const Coord &p_filter_box=Coord( 3, 3 ), int p_min_filter_pixels=50, int p_max_filter_pixels=50000, int p_min_blob_pixels=10, int p_max_blob_pixels=0, int p_min_blobs=0, int p_max_blobs=0 )
Zone( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Box &p_limits, const Rgb p_alarm_rgb, CheckMethod p_check_method, int p_min_pixel_threshold=15, int p_max_pixel_threshold=0, int p_min_alarm_pixels=50, int p_max_alarm_pixels=75000, const Coord &p_filter_box=Coord( 3, 3 ), int p_min_filter_pixels=50, int p_max_filter_pixels=50000, int p_min_blob_pixels=10, int p_max_blob_pixels=0, int p_min_blobs=0, int p_max_blobs=0 )
{
Setup( p_monitor, p_id, p_label, p_type, p_limits, p_alarm_rgb, p_min_pixel_threshold, p_max_pixel_threshold, p_min_alarm_pixels, p_max_alarm_pixels, p_filter_box, p_min_filter_pixels, p_max_filter_pixels, p_min_blob_pixels, p_max_blob_pixels, p_min_blobs, p_max_blobs );
Setup( p_monitor, p_id, p_label, p_type, p_limits, p_alarm_rgb, p_check_method, p_min_pixel_threshold, p_max_pixel_threshold, p_min_alarm_pixels, p_max_alarm_pixels, p_filter_box, p_min_filter_pixels, p_max_filter_pixels, p_min_blob_pixels, p_max_blob_pixels, p_min_blobs, p_max_blobs );
}
Zone( Monitor *p_monitor, int p_id, const char *p_label, const Box &p_limits, const Rgb p_alarm_rgb, int p_min_pixel_threshold=15, int p_max_pixel_threshold=0, int p_min_alarm_pixels=50, int p_max_alarm_pixels=75000, const Coord &p_filter_box=Coord( 3, 3 ), int p_min_filter_pixels=50, int p_max_filter_pixels=50000, int p_min_blob_pixels=10, int p_max_blob_pixels=0, int p_min_blobs=0, int p_max_blobs=0 )
Zone( Monitor *p_monitor, int p_id, const char *p_label, const Box &p_limits, const Rgb p_alarm_rgb, CheckMethod p_check_method, int p_min_pixel_threshold=15, int p_max_pixel_threshold=0, int p_min_alarm_pixels=50, int p_max_alarm_pixels=75000, const Coord &p_filter_box=Coord( 3, 3 ), int p_min_filter_pixels=50, int p_max_filter_pixels=50000, int p_min_blob_pixels=10, int p_max_blob_pixels=0, int p_min_blobs=0, int p_max_blobs=0 )
{
Setup( p_monitor, p_id, p_label, Zone::ACTIVE, p_limits, p_alarm_rgb, p_min_pixel_threshold, p_max_pixel_threshold, p_min_alarm_pixels, p_max_alarm_pixels, p_filter_box, p_min_filter_pixels, p_max_filter_pixels, p_min_blob_pixels, p_max_blob_pixels, p_min_blobs, p_max_blobs );
Setup( p_monitor, p_id, p_label, Zone::ACTIVE, p_limits, p_alarm_rgb, p_check_method, p_min_pixel_threshold, p_max_pixel_threshold, p_min_alarm_pixels, p_max_alarm_pixels, p_filter_box, p_min_filter_pixels, p_max_filter_pixels, p_min_blob_pixels, p_max_blob_pixels, p_min_blobs, p_max_blobs );
}
Zone( Monitor *p_monitor, int p_id, const char *p_label, const Box &p_limits )
{
Setup( p_monitor, p_id, p_label, Zone::INACTIVE, p_limits, RGB_BLACK, 0, 0, 0, 0, Coord( 0, 0 ), 0, 0, 0, 0, 0, 0 );
Setup( p_monitor, p_id, p_label, Zone::INACTIVE, p_limits, RGB_BLACK, (Zone::CheckMethod)0, 0, 0, 0, 0, Coord( 0, 0 ), 0, 0, 0, 0, 0, 0 );
}
public:

View File

@ -174,6 +174,7 @@ if ( isset($action) )
if ( $new_hi_x != $zone['HiX'] ) $changes[] = "HiX = '$new_hi_x'";
if ( $new_hi_y != $zone['HiY'] ) $changes[] = "HiY = '$new_hi_y'";
if ( $new_alarm_rgb != $zone['AlarmRGB'] ) $changes[] = "AlarmRGB = '$new_alarm_rgb'";
if ( $new_check_method != $zone['CheckMethod'] ) $changes[] = "CheckMethod = '$new_check_method'";
if ( $new_min_pixel_threshold != $zone['MinPixelThreshold'] ) $changes[] = "MinPixelThreshold = '$new_min_pixel_threshold'";
if ( $new_max_pixel_threshold != $zone['MaxPixelThreshold'] ) $changes[] = "MaxPixelThreshold = '$new_max_pixel_threshold'";
if ( $new_min_alarm_pixels != $zone['MinAlarmPixels'] ) $changes[] = "MinAlarmPixels = '$new_min_alarm_pixels'";
@ -260,7 +261,7 @@ if ( isset($action) )
if ( !$result )
die( mysql_error() );
$mid = mysql_insert_id();
$sql = "insert into Zones set MonitorId = $mid, Name = 'All', Type = 'Active', Units = 'Percent', LoX = 0, LoY = 0, HiX = 100, HiY = 100, AlarmRGB = 0xff0000, MinPixelThreshold = 25, MaxPixelThreshold = 0, MinAlarmPixels = 3, MaxAlarmPixels = 75, FilterX = 3, FilterY = 3, MinFilterPixels = 3, MaxFilterPixels = 75, MinBlobPixels = 2, MaxBlobPixels = 0, MinBlobs = 1, MaxBlobs = 0";
$sql = "insert into Zones set MonitorId = $mid, Name = 'All', Type = 'Active', Units = 'Percent', LoX = 0, LoY = 0, HiX = 100, HiY = 100, AlarmRGB = 0xff0000, CheckMethod = 'Blobs', MinPixelThreshold = 25, MaxPixelThreshold = 0, MinAlarmPixels = 3, MaxAlarmPixels = 75, FilterX = 3, FilterY = 3, MinFilterPixels = 3, MaxFilterPixels = 75, MinBlobPixels = 2, MaxBlobPixels = 0, MinBlobs = 1, MaxBlobs = 0";
$result = mysql_query( $sql );
if ( !$result )
die( mysql_error() );

View File

@ -110,6 +110,7 @@ function applyZoneType( Form )
Form.new_alarm_rgb_g.value = "";
Form.new_alarm_rgb_b.disabled = true;
Form.new_alarm_rgb_b.value = "";
Form.new_check_method.disabled = true;
Form.new_min_pixel_threshold.disabled = true;
Form.new_min_pixel_threshold.value = "";
Form.new_max_pixel_threshold.disabled = true;
@ -143,6 +144,7 @@ function applyZoneType( Form )
Form.new_alarm_rgb_g.value = "";
Form.new_alarm_rgb_b.disabled = true;
Form.new_alarm_rgb_b.value = "";
Form.new_check_method.disabled = false;
Form.new_max_pixel_threshold.disabled = false;
Form.new_max_pixel_threshold.value = "<?= $zone['MaxPixelThreshold'] ?>";
Form.new_min_pixel_threshold.disabled = false;
@ -176,6 +178,7 @@ function applyZoneType( Form )
Form.new_alarm_rgb_g.value = "<?= ($zone['AlarmRGB']>>8)&0xff; ?>";
Form.new_alarm_rgb_b.disabled = false;
Form.new_alarm_rgb_b.value = "<?= $zone['AlarmRGB']&0xff; ?>";
Form.new_check_method.disabled = false;
Form.new_max_pixel_threshold.disabled = false;
Form.new_max_pixel_threshold.value = "<?= $zone['MaxPixelThreshold'] ?>";
Form.new_min_pixel_threshold.disabled = false;
@ -207,6 +210,43 @@ function applyZoneType( Form )
}
}
function applyCheckMethod( Form )
{
if ( Form.new_check_method.value == 'AlarmedPixels' )
{
Form.new_filter_x.disabled = true;
Form.new_filter_y.disabled = true;
Form.new_min_filter_pixels.disabled = true;
Form.new_max_filter_pixels.disabled = true;
Form.new_min_blob_pixels.disabled = true;
Form.new_max_blob_pixels.disabled = true;
Form.new_min_blobs.disabled = true;
Form.new_max_blobs.disabled = true;
}
else if ( Form.new_check_method.value == 'FilteredPixels' )
{
Form.new_filter_x.disabled = false;
Form.new_filter_y.disabled = false;
Form.new_min_filter_pixels.disabled = false;
Form.new_max_filter_pixels.disabled = false;
Form.new_min_blob_pixels.disabled = true;
Form.new_max_blob_pixels.disabled = true;
Form.new_min_blobs.disabled = true;
Form.new_max_blobs.disabled = true;
}
else
{
Form.new_filter_x.disabled = false;
Form.new_filter_y.disabled = false;
Form.new_min_filter_pixels.disabled = false;
Form.new_max_filter_pixels.disabled = false;
Form.new_min_blob_pixels.disabled = false;
Form.new_max_blob_pixels.disabled = false;
Form.new_min_blobs.disabled = false;
Form.new_max_blobs.disabled = false;
}
}
function toPixels( Field, maxValue )
{
Field.value = Math.round((Field.value*maxValue)/100);
@ -359,6 +399,16 @@ foreach ( getEnumValues( 'Zones', 'Units' ) as $opt_units )
<tr><td align="left" class="text"><?= $zmSlangZoneMaxX ?></td><td align="left" class="text"><input type="text" name="new_hi_x" value="<?= $zone['HiX'] ?>" size="4" class="form" onchange="checkWidth(this,'Maximum X')"></td></tr>
<tr><td align="left" class="text"><?= $zmSlangZoneMaxY ?></td><td align="left" class="text"><input type="text" name="new_hi_y" value="<?= $zone['HiY'] ?>" size="4" class="form" onchange="checkHeight(this,'Maximum Y')"></td></tr>
<tr><td align="left" class="text"><?= $zmSlangZoneAlarmColour ?></td><td align="left" class="text">R:<input type="text" name="new_alarm_rgb_r" value="<?= ($zone['AlarmRGB']>>16)&0xff ?>" size="3" class="form" onchange="limitRange( this, 0, 255 )">&nbsp;G:<input type="text" name="new_alarm_rgb_g" value="<?= ($zone['AlarmRGB']>>8)&0xff ?>" size="3" class="form" onchange="limitRange( this, 0, 255 )">&nbsp;B:<input type="text" name="new_alarm_rgb_b" value="<?= $zone['AlarmRGB']&0xff ?>" size="3" class="form" onchange="limitRange( this, 0, 255 )"></td></tr>
<tr><td align="left" class="text"><?= $zmSlangCheckMethod ?></td><td align="left" class="text"><select name="new_check_method" class="form" onchange="applyCheckMethod(document.zone_form)">
<?php
foreach ( getEnumValues( 'Zones', 'CheckMethod' ) as $opt_check_method )
{
?>
<option value="<?= $opt_check_method ?>"<?php if ( $opt_check_method == $zone['CheckMethod'] ) { ?> selected<?php } ?>><?= $opt_check_method ?></option>
<?php
}
?>
</select></td></tr>
<tr><td align="left" class="text"><?= $zmSlangZoneMinPixelThres ?></td><td align="left" class="text"><input type="text" name="new_min_pixel_threshold" value="<?= $zone['MinPixelThreshold'] ?>" size="4" class="form" onchange="limitRange( this, 0, 255 )"></td></tr>
<tr><td align="left" class="text"><?= $zmSlangZoneMaxPixelThres ?></td><td align="left" class="text"><input type="text" name="new_max_pixel_threshold" value="<?= $zone['MaxPixelThreshold'] ?>" size="4" class="form" onchange="limitRange( this, 0, 255 )"></td></tr>
<tr><td align="left" class="text"><?= $zmSlangZoneMinAlarmedArea ?></td><td align="left" class="text"><input type="text" name="new_min_alarm_pixels" value="<?= $zone['MinAlarmPixels'] ?>" size="6" class="form" onchange="checkArea(this,'Minimum Alarmed Area')"></td></tr>