Bug 410 - Added in detection suspension if motion overloaded.

git-svn-id: http://svn.zoneminder.com/svn/zm/trunk@2132 e3e1d417-86f3-4887-817a-d78f3d33393f
This commit is contained in:
stan 2007-06-05 14:12:14 +00:00
parent 5124065e77
commit 2c09dbeeb9
7 changed files with 97 additions and 31 deletions

View File

@ -453,6 +453,7 @@ CREATE TABLE `ZonePresets` (
`MaxBlobPixels` int(10) unsigned default NULL,
`MinBlobs` smallint(5) unsigned default NULL,
`MaxBlobs` smallint(5) unsigned default NULL,
`OverloadFrames` smallint(5) unsigned NOT NULL default '0',
PRIMARY KEY (`Id`),
UNIQUE KEY `UC_Id` (`Id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
@ -485,6 +486,7 @@ CREATE TABLE `Zones` (
`MaxBlobPixels` int(10) unsigned default NULL,
`MinBlobs` smallint(5) unsigned default NULL,
`MaxBlobs` smallint(5) unsigned default NULL,
`OverloadFrames` smallint(5) unsigned NOT NULL default '0',
PRIMARY KEY (`Id`),
UNIQUE KEY `UC_Id` (`Id`),
KEY `MonitorId` (`MonitorId`)
@ -571,12 +573,12 @@ INSERT INTO MonitorPresets VALUES ('','Gadspot IP, mpjpeg','Remote',NULL,NULL,NU
--
-- Add some zone preset values
--
INSERT INTO ZonePresets VALUES (1,'Fast, low sensitivity','Active','Percent','AlarmedPixels',60,NULL,20,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
INSERT INTO ZonePresets VALUES (2,'Fast, medium sensitivity','Active','Percent','AlarmedPixels',40,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
INSERT INTO ZonePresets VALUES (3,'Fast, high sensitivity','Active','Percent','AlarmedPixels',20,NULL,5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
INSERT INTO ZonePresets VALUES (4,'Best, low sensitivity','Active','Percent','Blobs',60,NULL,36,NULL,7,7,24,NULL,20,NULL,1,NULL);
INSERT INTO ZonePresets VALUES (5,'Best, medium sensitivity','Active','Percent','Blobs',40,NULL,16,NULL,5,5,12,NULL,10,NULL,1,NULL);
INSERT INTO ZonePresets VALUES (6,'Best, high sensitivity','Active','Percent','Blobs',20,NULL,8,NULL,3,3,6,NULL,5,NULL,1,NULL);
INSERT INTO ZonePresets VALUES (1,'Fast, low sensitivity','Active','Percent','AlarmedPixels',60,NULL,20,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);
INSERT INTO ZonePresets VALUES (2,'Fast, medium sensitivity','Active','Percent','AlarmedPixels',40,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);
INSERT INTO ZonePresets VALUES (3,'Fast, high sensitivity','Active','Percent','AlarmedPixels',20,NULL,5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);
INSERT INTO ZonePresets VALUES (4,'Best, low sensitivity','Active','Percent','Blobs',60,NULL,36,NULL,7,7,24,NULL,20,NULL,1,NULL,0);
INSERT INTO ZonePresets VALUES (5,'Best, medium sensitivity','Active','Percent','Blobs',40,NULL,16,NULL,5,5,12,NULL,10,NULL,1,NULL,0);
INSERT INTO ZonePresets VALUES (6,'Best, high sensitivity','Active','Percent','Blobs',20,NULL,8,NULL,3,3,6,NULL,5,NULL,1,NULL,0);
--
-- Apply the initial configuration

View File

@ -7,6 +7,12 @@
--
alter table States modify column Definition text;
--
-- Add overload shutout to zones and presets
--
alter table Zones add column OverloadFrames smallint(5) unsigned NOT NULL default '0' after MaxBlobs;
alter table ZonePresets add column OverloadFrames smallint(5) unsigned NOT NULL default '0' after MaxBlobs;
--
-- These are optional, but we might as well do it now
--

View File

@ -1097,11 +1097,11 @@ bool Monitor::Analyse()
{
if ( state == IDLE || state == TAPE )
{
Info(( "Ended event" ));
Info(( "%s: %03d - Ending event %d", name, image_count, event->Id() ));
}
else
{
Info(( "Force closed event" ));
Info(( "%s: %03d - Force closing event %d", name, image_count, event->Id() ));
}
closeEvent();
last_section_mod = 0;
@ -1162,6 +1162,8 @@ bool Monitor::Analyse()
}
shared_data->last_event = event->Id();
Info(( "%s: %03d - Creating new event %d", name, image_count, event->Id() ));
for ( int i = 0; i < pre_event_count; i++ )
{
timestamps[i] = image_buffer[pre_index].timestamp;
@ -1309,7 +1311,7 @@ bool Monitor::Analyse()
int section_mod = timestamp->tv_sec%section_length;
if ( section_mod < last_section_mod )
{
Info(( "Ended event" ));
Info(( "%s: %03d - Ending event %d", name, image_count, event->Id() ));
closeEvent();
last_section_mod = 0;
}
@ -1325,7 +1327,7 @@ bool Monitor::Analyse()
{
if ( event )
{
Info(( "Closed event" ));
Info(( "%s: %03d - Closing event %d", name, image_count, event->Id() ));
closeEvent();
}
shared_data->state = state = IDLE;

View File

@ -23,7 +23,7 @@
#include "zm_image.h"
#include "zm_monitor.h"
void Zone::Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Polygon &p_polygon, 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 )
void Zone::Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Polygon &p_polygon, 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, int p_overload_frames )
{
monitor = p_monitor;
@ -45,8 +45,9 @@ void Zone::Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_
max_blob_pixels = p_max_blob_pixels;
min_blobs = p_min_blobs;
max_blobs = p_max_blobs;
overload_frames = p_overload_frames;
Debug( 1, ( "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, polygon.Width(), polygon.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 ));
Debug( 1, ( "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, OF: %d", id, label, type, polygon.Width(), polygon.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, overload_frames ));
alarmed = false;
pixel_diff = 0;
@ -59,6 +60,8 @@ void Zone::Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_
image = 0;
score = 0;
overload_count = 0;
pg_image = new Image( monitor->Width(), monitor->Height(), 1 );
pg_image->Fill( 0xff, polygon );
pg_image->Outline( 0xff, polygon );
@ -116,6 +119,14 @@ bool Zone::CheckAlarms( const Image *delta_image )
ResetStats();
if ( overload_count )
{
Info(( "In overload mode, %d frames of %d remaining", overload_count, overload_frames ));
Debug( 4, ( "In overload mode, %d frames of %d remaining", overload_count, overload_frames ));
overload_count--;
return( false );
}
delete image;
// Get the difference image
Image *diff_image = image = new Image( *delta_image );
@ -139,6 +150,7 @@ bool Zone::CheckAlarms( const Image *delta_image )
int hi_x;
Debug( 4, ( "Checking alarms for zone %d/%s in lines %d -> %d", id, label, lo_y, hi_y ));
Debug( 5, ( "Checking for alarmed pixels" ));
unsigned char *pdiff, *ppoly;
// Create an upper margin
@ -212,10 +224,19 @@ 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 );
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) )
{
overload_count = overload_frames;
return( false );
}
score = (100*alarm_pixels)/polygon.Area();
Debug( 5, ( "Current score is %d", score ));
@ -294,9 +315,19 @@ bool Zone::CheckAlarms( const Image *delta_image )
}
Debug( 5, ( "Got %d filtered pixels, need %d -> %d", alarm_filter_pixels, min_filter_pixels, max_filter_pixels ));
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 );
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) )
{
overload_count = overload_frames;
return( false );
}
score = (100*alarm_filter_pixels)/(polygon.Area());
Debug( 5, ( "Current score is %d", score ));
@ -505,7 +536,10 @@ bool Zone::CheckAlarms( const Image *delta_image )
diff_image->WriteJpeg( diag_path );
}
if ( !alarm_blobs ) return( false );
if ( !alarm_blobs )
{
return( false );
}
alarm_blob_pixels = alarm_filter_pixels;
Debug( 5, ( "Got %d raw blob pixels, %d raw blobs, need %d -> %d, %d -> %d", alarm_blob_pixels, alarm_blobs, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs ));
@ -562,9 +596,19 @@ bool Zone::CheckAlarms( const Image *delta_image )
}
Debug( 5, ( "Got %d blob pixels, %d blobs, need %d -> %d, %d -> %d", alarm_blob_pixels, alarm_blobs, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs ));
if ( !alarm_blobs ) return( false );
if ( min_blobs && alarm_blobs < min_blobs ) return( false );
if ( max_blobs && alarm_blobs > max_blobs ) return( false );
if ( !alarm_blobs )
{
return( false );
}
if ( min_blobs && (alarm_blobs < min_blobs) )
{
return( false );
}
if ( max_blobs && (alarm_blobs > max_blobs) )
{
overload_count = overload_frames;
return( false );
}
alarm_lo_x = polygon.HiX()+1;
alarm_hi_x = polygon.LoX()-1;
@ -832,7 +876,7 @@ bool Zone::ParseZoneString( const char *zone_string, int &zone_id, int &colour,
int Zone::Load( Monitor *monitor, Zone **&zones )
{
static char sql[BUFSIZ];
snprintf( sql, sizeof(sql), "select Id,Name,Type+0,Units,NumCoords,Coords,AlarmRGB,CheckMethod+0,MinPixelThreshold,MaxPixelThreshold,MinAlarmPixels,MaxAlarmPixels,FilterX,FilterY,MinFilterPixels,MaxFilterPixels,MinBlobPixels,MaxBlobPixels,MinBlobs,MaxBlobs from Zones where MonitorId = %d order by Type, Id", monitor->Id() );
snprintf( sql, sizeof(sql), "select Id,Name,Type+0,Units,NumCoords,Coords,AlarmRGB,CheckMethod+0,MinPixelThreshold,MaxPixelThreshold,MinAlarmPixels,MaxAlarmPixels,FilterX,FilterY,MinFilterPixels,MaxFilterPixels,MinBlobPixels,MaxBlobPixels,MinBlobs,MaxBlobs,OverloadFrames 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 ) ));
@ -873,6 +917,7 @@ int Zone::Load( Monitor *monitor, Zone **&zones )
int MaxBlobPixels = dbrow[col]?atoi(dbrow[col]):0; col++;
int MinBlobs = dbrow[col]?atoi(dbrow[col]):0; col++;
int MaxBlobs = dbrow[col]?atoi(dbrow[col]):0; col++;
int OverloadFrames = dbrow[col]?atoi(dbrow[col]):0; col++;
Debug( 5, ( "Parsing polygon %s", Coords ));
Polygon polygon;
@ -898,7 +943,7 @@ int Zone::Load( Monitor *monitor, Zone **&zones )
}
else
{
zones[i] = new Zone( monitor, Id, Name, (Zone::ZoneType)Type, polygon, AlarmRGB, (Zone::CheckMethod)CheckMethod, MinPixelThreshold, MaxPixelThreshold, MinAlarmPixels, MaxAlarmPixels, Coord( FilterX, FilterY ), MinFilterPixels, MaxFilterPixels, MinBlobPixels, MaxBlobPixels, MinBlobs, MaxBlobs );
zones[i] = new Zone( monitor, Id, Name, (Zone::ZoneType)Type, polygon, AlarmRGB, (Zone::CheckMethod)CheckMethod, MinPixelThreshold, MaxPixelThreshold, MinAlarmPixels, MaxAlarmPixels, Coord( FilterX, FilterY ), MinFilterPixels, MaxFilterPixels, MinBlobPixels, MaxBlobPixels, MinBlobs, MaxBlobs, OverloadFrames );
}
}
if ( mysql_errno( &dbconn ) )

View File

@ -72,6 +72,8 @@ protected:
int min_blobs;
int max_blobs;
int overload_frames;
// Outputs/Statistics
bool alarmed;
int pixel_diff;
@ -88,21 +90,23 @@ protected:
Range *ranges;
Image *image;
int overload_count;
protected:
void Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Polygon &p_polygon, 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 );
void Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Polygon &p_polygon, 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, int p_overload_frames );
public:
Zone( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Polygon &p_polygon, 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 )
Zone( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Polygon &p_polygon, 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, int p_overload_frames=0 )
{
Setup( p_monitor, p_id, p_label, p_type, p_polygon, 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 );
Setup( p_monitor, p_id, p_label, p_type, p_polygon, 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, p_overload_frames );
}
Zone( Monitor *p_monitor, int p_id, const char *p_label, const Polygon &p_polygon, 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 )
Zone( Monitor *p_monitor, int p_id, const char *p_label, const Polygon &p_polygon, 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, int p_overload_frames=0 )
{
Setup( p_monitor, p_id, p_label, Zone::ACTIVE, p_polygon, 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 );
Setup( p_monitor, p_id, p_label, Zone::ACTIVE, p_polygon, 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, p_overload_frames );
}
Zone( Monitor *p_monitor, int p_id, const char *p_label, const Polygon &p_polygon )
{
Setup( p_monitor, p_id, p_label, Zone::INACTIVE, p_polygon, RGB_BLACK, (Zone::CheckMethod)0, 0, 0, 0, 0, Coord( 0, 0 ), 0, 0, 0, 0, 0, 0 );
Setup( p_monitor, p_id, p_label, Zone::INACTIVE, p_polygon, RGB_BLACK, (Zone::CheckMethod)0, 0, 0, 0, 0, Coord( 0, 0 ), 0, 0, 0, 0, 0, 0, 0 );
}
public:

View File

@ -277,6 +277,7 @@ function applyZoneType()
form.elements['new_zone[MaxBlobPixels]'].disabled = true;
form.elements['new_zone[MinBlobs]'].disabled = true;
form.elements['new_zone[MaxBlobs]'].disabled = true;
form.elements['new_zone[OverloadFrames]'].disabled = true;
}
else if ( form.elements['new_zone[Type]'].value == 'Preclusive' )
{
@ -289,6 +290,7 @@ function applyZoneType()
form.elements['new_zone[MaxPixelThreshold]'].disabled = false;
form.elements['new_zone[MinAlarmPixels]'].disabled = false;
form.elements['new_zone[MaxAlarmPixels]'].disabled = false;
form.elements['new_zone[OverloadFrames]'].disabled = false;
applyCheckMethod();
}
else
@ -302,6 +304,7 @@ function applyZoneType()
form.elements['new_zone[MaxPixelThreshold]'].disabled = false;
form.elements['new_zone[MinAlarmPixels]'].disabled = false;
form.elements['new_zone[MaxAlarmPixels]'].disabled = false;
form.elements['new_zone[OverloadFrames]'].disabled = false;
applyCheckMethod();
}
}
@ -371,6 +374,7 @@ foreach ( $presets as $preset )
form.elements['new_zone[MaxBlobPixels]'].value = '<?= $preset['MaxBlobPixels'] ?>';
form.elements['new_zone[MinBlobs]'].value = '<?= $preset['MinBlobs'] ?>';
form.elements['new_zone[MaxBlobs]'].value = '<?= $preset['MaxBlobs'] ?>';
form.elements['new_zone[OverloadFrames]'].value = '<?= $preset['OverloadFrames'] ?>';
break;
}
<?php
@ -683,6 +687,8 @@ foreach ( getEnumValues( 'Zones', 'CheckMethod' ) as $opt_check_method )
<tr><td align="left" class="text"><?= $zmSlangZoneMinMaxBlobArea ?></td><td align="left" class="text"><input type="text" name="new_zone[MinBlobPixels]" value="<?= $new_zone['MinBlobPixels'] ?>" size="6" class="form"></td><td align="left" class="text"><input type="text" name="new_zone[MaxBlobPixels]" value="<?= $new_zone['MaxBlobPixels'] ?>" size="6" class="form"></td></tr>
<tr><td colspan="3"><img src="graphics/spacer.gif" width="1" height="5"></td></tr>
<tr><td align="left" class="text"><?= $zmSlangZoneMinMaxBlobs ?></td><td align="left" class="text"><input type="text" name="new_zone[MinBlobs]" value="<?= $new_zone['MinBlobs'] ?>" size="4" class="form"></td><td align="left" class="text"><input type="text" name="new_zone[MaxBlobs]" value="<?= $new_zone['MaxBlobs'] ?>" size="4" class="form"></td></tr>
<tr><td colspan="3"><img src="graphics/spacer.gif" width="1" height="5"></td></tr>
<tr><td align="left" class="text"><?= $zmSlangZoneOverloadFrames ?></td><td colspan="2" align="left" class="text"><input type="text" name="new_zone[OverloadFrames]" value="<?= $new_zone['OverloadFrames'] ?>" size="4" class="form"></td></tr>
<tr><td colspan="3" align="left" class="text">&nbsp;</td></tr>
</table>
</td>

View File

@ -642,6 +642,7 @@ $zmSlangZoneMinMaxBlobArea = 'Min/Max Blob Area';
$zmSlangZoneMinMaxBlobs = 'Min/Max Blobs';
$zmSlangZoneMinMaxFiltArea = 'Min/Max Filtered Area';
$zmSlangZoneMinMaxPixelThres = 'Min/Max Pixel Threshold (0-255)';
$zmSlangZoneOverloadFrames = 'Overload Frame Ignore Count';
$zmSlangZones = 'Zones';
$zmSlangZone = 'Zone';
$zmSlangZoomIn = 'Zoom In';