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 -- 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 column MonitorId;
alter table Filters drop index FilterIDX; alter table Filters drop index FilterIDX;
-- --

View File

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

View File

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

View File

@ -133,7 +133,7 @@ public:
inline int Width() { return( width ); } inline int Width() { return( width ); }
inline int Height() { return( height ); } 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 ) 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; n_zones = 1;
zones = new Zone *[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 ); start_time = last_fps_time = time( 0 );

View File

@ -26,7 +26,7 @@
bool Zone::initialised = false; bool Zone::initialised = false;
bool Zone::record_diag_images; 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 ) if ( !initialised )
Initialise(); Initialise();
@ -39,6 +39,7 @@ void Zone::Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_
type = p_type; type = p_type;
limits = p_limits; limits = p_limits;
alarm_rgb = p_alarm_rgb; alarm_rgb = p_alarm_rgb;
check_method = p_check_method;
min_pixel_threshold = p_min_pixel_threshold; min_pixel_threshold = p_min_pixel_threshold;
max_pixel_threshold = p_max_pixel_threshold; max_pixel_threshold = p_max_pixel_threshold;
min_alarm_pixels = p_min_alarm_pixels; 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; min_blobs = p_min_blobs;
max_blobs = p_max_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; alarmed = false;
alarm_pixels = 0; alarm_pixels = 0;
@ -88,15 +89,19 @@ bool Zone::CheckAlarms( const Image *delta_image )
ResetStats(); ResetStats();
delete image; delete image;
// Get the difference image
Image *diff_image = image = new Image( *delta_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_x = limits.Lo().X();
int lo_y = limits.Lo().Y(); int lo_y = limits.Lo().Y();
int hi_x = limits.Hi().X(); int hi_x = limits.Hi().X();
int hi_y = limits.Hi().Y(); int hi_y = limits.Hi().Y();
for ( int y = lo_y; y <= hi_y; y++ ) for ( int y = lo_y; y <= hi_y; y++ )
{ {
unsigned char *pdiff = diff_image->Buffer( lo_x, y ); unsigned char *pdiff = diff_image->Buffer( lo_x, y );
@ -106,11 +111,13 @@ bool Zone::CheckAlarms( const Image *delta_image )
{ {
*pdiff = WHITE; *pdiff = WHITE;
alarm_pixels++; alarm_pixels++;
continue;
} }
else
{
*pdiff = BLACK; *pdiff = BLACK;
} }
} }
}
if ( record_diag_images ) if ( record_diag_images )
{ {
static char diag_path[PATH_MAX] = ""; static char diag_path[PATH_MAX] = "";
@ -121,13 +128,14 @@ bool Zone::CheckAlarms( const Image *delta_image )
diff_image->WriteJpeg( diag_path ); diff_image->WriteJpeg( diag_path );
} }
if ( !alarm_pixels ) return( false ); if ( !alarm_pixels ) return( false );
if ( min_alarm_pixels && alarm_pixels < min_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 ); 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());
if ( check_method >= FILTERED_PIXELS )
{
int bx = filter_box.X(); int bx = filter_box.X();
int by = filter_box.Y(); int by = filter_box.Y();
int bx1 = bx-1; int bx1 = bx-1;
@ -136,41 +144,43 @@ bool Zone::CheckAlarms( const Image *delta_image )
if ( bx > 1 || by > 1 ) if ( bx > 1 || by > 1 )
{ {
// Now remove any pixels smaller than our filter size // 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++ ) for ( int y = lo_y; y <= hi_y; y++ )
{ {
unsigned char *pdiff = diff_image->Buffer( lo_x, y ); pdiff = diff_image->Buffer( lo_x, y );
for ( int x = lo_x; x <= hi_x; x++, pdiff++ ) for ( int x = lo_x; x <= hi_x; x++, pdiff++ )
{ {
if ( *pdiff == WHITE ) if ( *pdiff == WHITE )
{ {
// Check participation in an X blob // Check participation in an X block
int ldx = (x>=(lo_x+bx1))?-bx1:lo_x-x; ldx = (x>=(lo_x+bx1))?-bx1:lo_x-x;
int hdx = (x<=(hi_x-bx1))?0:((hi_x-x)-bx1); hdx = (x<=(hi_x-bx1))?0:((hi_x-x)-bx1);
int ldy = (y>=(lo_y+by1))?-by1:lo_y-y; ldy = (y>=(lo_y+by1))?-by1:lo_y-y;
int hdy = (y<=(hi_y-by1))?0:((hi_y-y)-by1); hdy = (y<=(hi_y-by1))?0:((hi_y-y)-by1);
bool blob = false; block = false;
for ( int dy = ldy; !blob && dy <= hdy; dy++ ) for ( int dy = ldy; !block && dy <= hdy; dy++ )
{ {
for ( int dx = ldx; !blob && dx <= hdx; dx++ ) for ( int dx = ldx; !block && dx <= hdx; dx++ )
{ {
blob = true; block = true;
for ( int dy2 = 0; blob && dy2 < by; dy2++ ) for ( int dy2 = 0; block && dy2 < by; dy2++ )
{ {
for ( int dx2 = 0; blob && dx2 < bx; dx2++ ) for ( int dx2 = 0; block && dx2 < bx; dx2++ )
{ {
unsigned char *cpdiff = diff_image->Buffer( x+dx+dx2, y+dy+dy2 ); cpdiff = diff_image->Buffer( x+dx+dx2, y+dy+dy2 );
if ( !*cpdiff ) if ( !*cpdiff )
{ {
blob = false; block = false;
}
} }
} }
} }
} }
if ( !blob ) }
if ( !block )
{ {
*pdiff = BLACK; *pdiff = BLACK;
continue; continue;
@ -179,6 +189,7 @@ bool Zone::CheckAlarms( const Image *delta_image )
} }
} }
} }
}
if ( record_diag_images ) if ( record_diag_images )
{ {
static char diag_path[PATH_MAX] = ""; static char diag_path[PATH_MAX] = "";
@ -192,56 +203,56 @@ bool Zone::CheckAlarms( const Image *delta_image )
if ( !alarm_filter_pixels ) return( false ); if ( !alarm_filter_pixels ) return( false );
if ( min_filter_pixels && alarm_filter_pixels < min_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 ); 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());
if ( check_method >= BLOBS )
{
typedef struct { unsigned char tag; int count; int lo_x; int hi_x; int lo_y; int hi_y; } BlobStats; typedef struct { unsigned char tag; int count; int lo_x; int hi_x; int lo_y; int hi_y; } BlobStats;
BlobStats blob_stats[256]; BlobStats blob_stats[256];
memset( blob_stats, 0, sizeof(BlobStats)*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++ ) for ( int y = lo_y; y <= hi_y; y++ )
{ {
unsigned char *pdiff = diff_image->Buffer( lo_x, y ); pdiff = diff_image->Buffer( lo_x, y );
for ( int x = lo_x; x <= hi_x; x++, pdiff++ ) for ( int x = lo_x; x <= hi_x; x++, pdiff++ )
{ {
if ( *pdiff == WHITE ) if ( *pdiff == WHITE )
{ {
//printf( "Got white pixel at %d,%d (%x)\n", x, y, pdiff ); //printf( "Got white pixel at %d,%d (%x)\n", x, y, pdiff );
int lx = x>lo_x?*(pdiff-1):0; lx = x>lo_x?*(pdiff-1):0;
int ly = y>lo_y?*(pdiff-diff_image->Width()):0; ly = y>lo_y?*(pdiff-diff_image->Width()):0;
if ( lx ) if ( lx )
{ {
//printf( "Left neighbour is %d\n", lx ); //printf( "Left neighbour is %d\n", lx );
BlobStats *bsx = &blob_stats[lx]; bsx = &blob_stats[lx];
if ( ly ) if ( ly )
{ {
//printf( "Top neighbour is %d\n", ly ); //printf( "Top neighbour is %d\n", ly );
BlobStats *bsy = &blob_stats[ly]; bsy = &blob_stats[ly];
if ( lx == ly ) if ( lx == ly )
{ {
//printf( "Matching neighbours, setting to %d\n", lx ); //printf( "Matching neighbours, setting to %d\n", lx );
// Add to the blob from the x side (either side really) // Add to the blob from the x side (either side really)
*pdiff = lx; *pdiff = lx;
bsx->count++; 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 ( x > bsx->hi_x ) bsx->hi_x = x;
if ( y > bsx->hi_y ) bsx->hi_y = y; if ( y > bsx->hi_y ) bsx->hi_y = y;
} }
else else
{ {
// Aggregate blobs // Aggregate blobs
BlobStats *bsm = bsx->count>=bsy->count?bsx:bsy; bsm = bsx->count>=bsy->count?bsx:bsy;
BlobStats *bss = bsm==bsx?bsy:bsx; bss = bsm==bsx?bsy:bsx;
//printf( "Different neighbours, setting pixels of %d to %d\n", bss->tag, bsm->tag ); //printf( "Different neighbours, setting pixels of %d to %d\n", bss->tag, bsm->tag );
// Now change all those pixels to the other setting // Now change all those pixels to the other setting
for ( int sy = bss->lo_y; sy <= bss->hi_y; sy++ ) for ( int sy = bss->lo_y; sy <= bss->hi_y; sy++ )
{ {
unsigned char *spdiff = diff_image->Buffer( bss->lo_x, sy ); spdiff = diff_image->Buffer( bss->lo_x, sy );
for ( int sx = bss->lo_x; sx <= bss->hi_x; sx++, spdiff++ ) for ( int sx = bss->lo_x; sx <= bss->hi_x; sx++, spdiff++ )
{ {
//printf( "Pixel at %d,%d (%x) is %d", sx, sy, spdiff, *spdiff ); //printf( "Pixel at %d,%d (%x) is %d", sx, sy, spdiff, *spdiff );
@ -281,8 +292,6 @@ bool Zone::CheckAlarms( const Image *delta_image )
// Add to the blob from the x side // Add to the blob from the x side
*pdiff = lx; *pdiff = lx;
bsx->count++; 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 ( x > bsx->hi_x ) bsx->hi_x = x;
if ( y > bsx->hi_y ) bsx->hi_y = y; if ( y > bsx->hi_y ) bsx->hi_y = y;
} }
@ -298,8 +307,6 @@ bool Zone::CheckAlarms( const Image *delta_image )
*pdiff = ly; *pdiff = ly;
bsy->count++; 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 ( x > bsy->hi_x ) bsy->hi_x = x;
if ( y > bsy->hi_y ) bsy->hi_y = y; if ( y > bsy->hi_y ) bsy->hi_y = y;
} }
@ -327,7 +334,7 @@ bool Zone::CheckAlarms( const Image *delta_image )
} }
} }
} }
if ( record_diag_images ) if ( (bool)config.Item( ZM_RECORD_DIAG_IMAGES ) )
{ {
static char diag_path[PATH_MAX] = ""; static char diag_path[PATH_MAX] = "";
if ( !diag_path[0] ) if ( !diag_path[0] )
@ -340,9 +347,7 @@ bool Zone::CheckAlarms( const Image *delta_image )
if ( !alarm_blobs ) return( false ); if ( !alarm_blobs ) return( false );
alarm_blob_pixels = alarm_filter_pixels; alarm_blob_pixels = alarm_filter_pixels;
min_blob_size = 0; // Now eliminate blobs under the threshold
max_blob_size = 0;
// Now eliminate blobs outside the thresholds
for ( int i = 1; i < WHITE; i++ ) for ( int i = 1; i < WHITE; i++ )
{ {
BlobStats *bs = &blob_stats[i]; BlobStats *bs = &blob_stats[i];
@ -393,10 +398,10 @@ bool Zone::CheckAlarms( const Image *delta_image )
if ( min_blobs && alarm_blobs < min_blobs ) return( false ); if ( min_blobs && alarm_blobs < min_blobs ) return( false );
if ( max_blobs && alarm_blobs > max_blobs ) return( false ); if ( max_blobs && alarm_blobs > max_blobs ) return( false );
int alarm_lo_x = hi_x+1; alarm_lo_x = hi_x+1;
int alarm_hi_x = lo_x-1; alarm_hi_x = lo_x-1;
int alarm_lo_y = hi_y+1; alarm_lo_y = hi_y+1;
int alarm_hi_y = lo_y-1; alarm_hi_y = lo_y-1;
for ( int i = 1; i < WHITE; i++ ) for ( int i = 1; i < WHITE; i++ )
{ {
BlobStats *bs = &blob_stats[i]; BlobStats *bs = &blob_stats[i];
@ -408,9 +413,10 @@ bool Zone::CheckAlarms( const Image *delta_image )
if ( alarm_hi_y < bs->hi_y ) alarm_hi_y = bs->hi_y; if ( alarm_hi_y < bs->hi_y ) alarm_hi_y = bs->hi_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()); score = ((100*alarm_blob_pixels)/int(sqrt((double)alarm_blobs)))/(limits.Size().X()*limits.Size().Y());
}
}
if ( type == INCLUSIVE ) if ( type == INCLUSIVE )
{ {
score /= 2; score /= 2;
@ -421,14 +427,15 @@ bool Zone::CheckAlarms( const Image *delta_image )
} }
// Now outline the changed region // Now outline the changed region
if ( alarm_blobs ) if ( score )
{ {
alarm = true; 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 ); image = diff_image->HighlightEdges( alarm_rgb, &limits );
// Only need to delete this when 'image' becomes detached and points somewhere else // Only need to delete this when 'image' becomes detached and points somewhere else
delete diff_image; delete diff_image;
} }
@ -441,7 +448,7 @@ bool Zone::CheckAlarms( const Image *delta_image )
int Zone::Load( Monitor *monitor, Zone **&zones ) int Zone::Load( Monitor *monitor, Zone **&zones )
{ {
static char sql[BUFSIZ]; 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 ) ) if ( mysql_query( &dbconn, sql ) )
{ {
Error(( "Can't run query: %s", mysql_error( &dbconn ) )); 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 HiX = atoi(dbrow[col++]);
int HiY = atoi(dbrow[col++]); int HiY = atoi(dbrow[col++]);
int AlarmRGB = dbrow[col]?atoi(dbrow[col]):0; 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 MinPixelThreshold = dbrow[col]?atoi(dbrow[col]):0; col++;
int MaxPixelThreshold = 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++; int MinAlarmPixels = dbrow[col]?atoi(dbrow[col]):0; col++;
@ -504,7 +512,7 @@ int Zone::Load( Monitor *monitor, Zone **&zones )
} }
else 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 ) ) 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), " 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), " 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), " Min Pixel Threshold : %d\n", min_pixel_threshold );
sprintf( output+strlen(output), " Max Pixel Threshold : %d\n", max_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 ); sprintf( output+strlen(output), " Min Alarm Pixels : %d\n", min_alarm_pixels );

View File

@ -36,6 +36,7 @@ class Zone
{ {
public: public:
typedef enum { ACTIVE=1, INCLUSIVE, EXCLUSIVE, PRECLUSIVE, INACTIVE } ZoneType; typedef enum { ACTIVE=1, INCLUSIVE, EXCLUSIVE, PRECLUSIVE, INACTIVE } ZoneType;
typedef enum { ALARMED_PIXELS=1, FILTERED_PIXELS, BLOBS } CheckMethod;
protected: protected:
static bool initialised; static bool initialised;
@ -50,6 +51,7 @@ protected:
ZoneType type; ZoneType type;
Box limits; Box limits;
Rgb alarm_rgb; Rgb alarm_rgb;
CheckMethod check_method;
int min_pixel_threshold; int min_pixel_threshold;
int max_pixel_threshold; int max_pixel_threshold;
@ -85,20 +87,20 @@ protected:
record_diag_images = (bool)config.Item( ZM_RECORD_DIAG_IMAGES ); 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: 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 ) 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: public:

View File

@ -174,6 +174,7 @@ if ( isset($action) )
if ( $new_hi_x != $zone['HiX'] ) $changes[] = "HiX = '$new_hi_x'"; if ( $new_hi_x != $zone['HiX'] ) $changes[] = "HiX = '$new_hi_x'";
if ( $new_hi_y != $zone['HiY'] ) $changes[] = "HiY = '$new_hi_y'"; if ( $new_hi_y != $zone['HiY'] ) $changes[] = "HiY = '$new_hi_y'";
if ( $new_alarm_rgb != $zone['AlarmRGB'] ) $changes[] = "AlarmRGB = '$new_alarm_rgb'"; 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_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_max_pixel_threshold != $zone['MaxPixelThreshold'] ) $changes[] = "MaxPixelThreshold = '$new_max_pixel_threshold'";
if ( $new_min_alarm_pixels != $zone['MinAlarmPixels'] ) $changes[] = "MinAlarmPixels = '$new_min_alarm_pixels'"; if ( $new_min_alarm_pixels != $zone['MinAlarmPixels'] ) $changes[] = "MinAlarmPixels = '$new_min_alarm_pixels'";
@ -260,7 +261,7 @@ if ( isset($action) )
if ( !$result ) if ( !$result )
die( mysql_error() ); die( mysql_error() );
$mid = mysql_insert_id(); $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 ); $result = mysql_query( $sql );
if ( !$result ) if ( !$result )
die( mysql_error() ); die( mysql_error() );

View File

@ -110,6 +110,7 @@ function applyZoneType( Form )
Form.new_alarm_rgb_g.value = ""; Form.new_alarm_rgb_g.value = "";
Form.new_alarm_rgb_b.disabled = true; Form.new_alarm_rgb_b.disabled = true;
Form.new_alarm_rgb_b.value = ""; Form.new_alarm_rgb_b.value = "";
Form.new_check_method.disabled = true;
Form.new_min_pixel_threshold.disabled = true; Form.new_min_pixel_threshold.disabled = true;
Form.new_min_pixel_threshold.value = ""; Form.new_min_pixel_threshold.value = "";
Form.new_max_pixel_threshold.disabled = true; Form.new_max_pixel_threshold.disabled = true;
@ -143,6 +144,7 @@ function applyZoneType( Form )
Form.new_alarm_rgb_g.value = ""; Form.new_alarm_rgb_g.value = "";
Form.new_alarm_rgb_b.disabled = true; Form.new_alarm_rgb_b.disabled = true;
Form.new_alarm_rgb_b.value = ""; Form.new_alarm_rgb_b.value = "";
Form.new_check_method.disabled = false;
Form.new_max_pixel_threshold.disabled = false; Form.new_max_pixel_threshold.disabled = false;
Form.new_max_pixel_threshold.value = "<?= $zone['MaxPixelThreshold'] ?>"; Form.new_max_pixel_threshold.value = "<?= $zone['MaxPixelThreshold'] ?>";
Form.new_min_pixel_threshold.disabled = false; 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_g.value = "<?= ($zone['AlarmRGB']>>8)&0xff; ?>";
Form.new_alarm_rgb_b.disabled = false; Form.new_alarm_rgb_b.disabled = false;
Form.new_alarm_rgb_b.value = "<?= $zone['AlarmRGB']&0xff; ?>"; 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.disabled = false;
Form.new_max_pixel_threshold.value = "<?= $zone['MaxPixelThreshold'] ?>"; Form.new_max_pixel_threshold.value = "<?= $zone['MaxPixelThreshold'] ?>";
Form.new_min_pixel_threshold.disabled = false; 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 ) function toPixels( Field, maxValue )
{ {
Field.value = Math.round((Field.value*maxValue)/100); 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"><?= $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"><?= $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"><?= $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"><?= $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"><?= $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> <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>