Initial implementation of learning, fixed scoring bug and Mark functions.

git-svn-id: http://svn.zoneminder.com/svn/zm/trunk@121 e3e1d417-86f3-4887-817a-d78f3d33393f
This commit is contained in:
stan 2002-11-07 12:25:48 +00:00
parent cdefac9af9
commit db6e5103b9
4 changed files with 158 additions and 93 deletions

View File

@ -21,8 +21,10 @@
MYSQL dbconn; MYSQL dbconn;
void Zone::Setup( int p_id, const char *p_label, ZoneType p_type, const Box &p_limits, const Rgb p_alarm_rgb, int p_alarm_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, int p_alarm_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 )
{ {
monitor = p_monitor;
id = p_id; id = p_id;
label = new char[strlen(p_label)+1]; label = new char[strlen(p_label)+1];
strcpy( label, p_label ); strcpy( label, p_label );
@ -45,6 +47,7 @@ void Zone::Setup( int p_id, const char *p_label, ZoneType p_type, const Box &p_l
alarmed = false; alarmed = false;
alarm_pixels = 0; alarm_pixels = 0;
alarm_filter_pixels = 0; alarm_filter_pixels = 0;
alarm_blob_pixels = 0;
alarm_blobs = 0; alarm_blobs = 0;
image = 0; image = 0;
score = 0; score = 0;
@ -56,10 +59,21 @@ Zone::~Zone()
delete image; delete image;
} }
int Zone::Load( int monitor_id, int width, int height, Zone **&zones ) void Zone::RecordStats( const Event *event )
{ {
static char sql[256]; static char sql[256];
sprintf( sql, "select Id,Name,Type+0,Units,LoX,LoY,HiX,HiY,AlarmRGB,AlarmThreshold,MinAlarmPixels,MaxAlarmPixels,FilterX,FilterY,MinFilterPixels,MaxFilterPixels,MinBlobPixels,MaxBlobPixels,MinBlobs,MaxBlobs from Zones where MonitorId = %d order by Type, Id", monitor_id ); sprintf( sql, "insert into Stats set MonitorId=%d, ZoneId=%d, EventId=%d, FrameId=%d, AlarmPixels=%d, FilterPixels=%d, BlobPixels=%d, Blobs=%d, MinBlobSize=%d, MaxBlobSize=%d, MinX=%d, MinY=%d, MaxX=%d, MaxY=%d, Score=%d", monitor->Id(), id, event->Id(), event->Frames()+1, alarm_pixels, alarm_filter_pixels, alarm_blob_pixels, alarm_blobs, min_blob_size, max_blob_size, alarm_box.LoX(), alarm_box.LoY(), alarm_box.HiX(), alarm_box.HiY(), score );
if ( mysql_query( &dbconn, sql ) )
{
Error(( "Can't insert event: %s\n", mysql_error( &dbconn ) ));
exit( mysql_errno( &dbconn ) );
}
}
int Zone::Load( Monitor *monitor, Zone **&zones )
{
static char sql[256];
sprintf( sql, "select Id,Name,Type+0,Units,LoX,LoY,HiX,HiY,AlarmRGB,AlarmThreshold,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\n", mysql_error( &dbconn ) )); Error(( "Can't run query: %s\n", mysql_error( &dbconn ) ));
@ -73,7 +87,7 @@ int Zone::Load( int monitor_id, int width, int height, Zone **&zones )
exit( mysql_errno( &dbconn ) ); exit( mysql_errno( &dbconn ) );
} }
int n_zones = mysql_num_rows( result ); int n_zones = mysql_num_rows( result );
Info(( "Got %d zones for monitor %d\n", n_zones, monitor_id )); Info(( "Got %d zones for monitor %s\n", n_zones, monitor->Name() ));
delete[] zones; delete[] zones;
zones = new Zone *[n_zones]; zones = new Zone *[n_zones];
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ )
@ -101,25 +115,25 @@ int Zone::Load( int monitor_id, int width, int height, Zone **&zones )
if ( !strcmp( Units, "Percent" ) ) if ( !strcmp( Units, "Percent" ) )
{ {
LoX = (LoX*(width-1))/100; LoX = (LoX*(monitor->Width()-1))/100;
LoY = (LoY*(height-1))/100; LoY = (LoY*(monitor->Height()-1))/100;
HiX = (HiX*(width-1))/100; HiX = (HiX*(monitor->Width()-1))/100;
HiY = (HiY*(height-1))/100; HiY = (HiY*(monitor->Height()-1))/100;
MinAlarmPixels = (MinAlarmPixels*width*height)/100; MinAlarmPixels = (MinAlarmPixels*monitor->Width()*monitor->Height())/100;
MaxAlarmPixels = (MaxAlarmPixels*width*height)/100; MaxAlarmPixels = (MaxAlarmPixels*monitor->Width()*monitor->Height())/100;
MinFilterPixels = (MinFilterPixels*width*height)/100; MinFilterPixels = (MinFilterPixels*monitor->Width()*monitor->Height())/100;
MaxFilterPixels = (MaxFilterPixels*width*height)/100; MaxFilterPixels = (MaxFilterPixels*monitor->Width()*monitor->Height())/100;
MinBlobPixels = (MinBlobPixels*width*height)/100; MinBlobPixels = (MinBlobPixels*monitor->Width()*monitor->Height())/100;
MaxBlobPixels = (MaxBlobPixels*width*height)/100; MaxBlobPixels = (MaxBlobPixels*monitor->Width()*monitor->Height())/100;
} }
if ( atoi(dbrow[2]) == Zone::INACTIVE ) if ( atoi(dbrow[2]) == Zone::INACTIVE )
{ {
zones[i] = new Zone( Id, Name, Box( LoX, LoY, HiX, HiY ) ); zones[i] = new Zone( monitor, Id, Name, Box( LoX, LoY, HiX, HiY ) );
} }
else else
{ {
zones[i] = new Zone( Id, Name, (Zone::ZoneType)Type, Box( LoX, LoY, HiX, HiY ), AlarmRGB, AlarmThreshold, 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, AlarmThreshold, MinAlarmPixels, MaxAlarmPixels, Coord( FilterX, FilterY ), MinFilterPixels, MaxFilterPixels, MinBlobPixels, MaxBlobPixels, MinBlobs, MaxBlobs );
} }
} }
if ( mysql_errno( &dbconn ) ) if ( mysql_errno( &dbconn ) )
@ -514,11 +528,13 @@ Image *Image::Delta( const Image &image, bool absolute ) const
return( result ); return( result );
} }
unsigned int Image::CheckAlarms( Zone *zone, const Image *delta_image ) const bool Image::CheckAlarms( Zone *zone, const Image *delta_image ) const
{ {
bool alarm = false; bool alarm = false;
unsigned int score = 0; unsigned int score = 0;
zone->ResetStats();
delete zone->image; delete zone->image;
Image *diff_image = zone->image = new Image( *delta_image ); Image *diff_image = zone->image = new Image( *delta_image );
@ -564,39 +580,6 @@ unsigned int Image::CheckAlarms( Zone *zone, const Image *delta_image ) const
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 )
{
if ( 0 )
{
int count;
int dx;
// Check participation in an X blob
int ldx = (x>=(lo_x+bx1))?-bx1:lo_x-x;
int hdx = (x<=(hi_x-bx1))?bx1:hi_x-x;
for ( count = 0, dx = ldx; count < bx && dx <= hdx; dx++ )
{
count = (*(pdiff+dx) == WHITE)?count+1:0;
}
if ( count < bx )
{
*pdiff = BLACK;
continue;
}
int dy;
// Check participation in a Y blob
int ldy = (y>=(lo_y+by1))?-by1:lo_y-y;
int hdy = (y<=(hi_y-by1))?by1:hi_y-y;
for ( count = 0, dy = ldy; count < by && dy <= hdy; dy++ )
{
count = (*(pdiff+(diff_image->width*dy)) == WHITE)?count+1:0;
}
if ( count < by )
{
*pdiff = BLACK;
continue;
}
filter_pixels++;
}
else
{ {
// Check participation in an X blob // Check participation in an X blob
int ldx = (x>=(lo_x+bx1))?-bx1:lo_x-x; int ldx = (x>=(lo_x+bx1))?-bx1:lo_x-x;
@ -633,7 +616,6 @@ unsigned int Image::CheckAlarms( Zone *zone, const Image *delta_image ) const
} }
} }
} }
}
//diff_image->WriteJpeg( "diff2.jpg" ); //diff_image->WriteJpeg( "diff2.jpg" );
@ -771,7 +753,6 @@ unsigned int Image::CheckAlarms( Zone *zone, const Image *delta_image ) const
} }
} }
} }
} }
} }
} }
@ -781,6 +762,8 @@ unsigned int Image::CheckAlarms( Zone *zone, const Image *delta_image ) const
if ( !blobs ) return( false ); if ( !blobs ) return( false );
int blob_pixels = filter_pixels; int blob_pixels = filter_pixels;
int min_blob_size = 0;
int max_blob_size = 0;
// Now eliminate blobs under the alarm_threshold // Now eliminate blobs under the alarm_threshold
for ( int i = 1; i < WHITE; i++ ) for ( int i = 1; i < WHITE; i++ )
{ {
@ -809,6 +792,14 @@ unsigned int Image::CheckAlarms( Zone *zone, const Image *delta_image ) const
bs->hi_x = 0; bs->hi_x = 0;
bs->hi_y = 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 ( !blobs ) return( false ); if ( !blobs ) return( false );
@ -831,11 +822,14 @@ unsigned int Image::CheckAlarms( Zone *zone, const Image *delta_image ) const
} }
} }
zone->alarm_blobs = blobs;
zone->alarm_pixels = alarm_pixels; zone->alarm_pixels = alarm_pixels;
zone->alarm_filter_pixels = filter_pixels; zone->alarm_filter_pixels = filter_pixels;
zone->alarm_blob_pixels = blob_pixels;
zone->alarm_blobs = blobs;
zone->min_blob_size = min_blob_size;
zone->max_blob_size = max_blob_size;
zone->alarm_box = Box( Coord( alarm_lo_x, alarm_lo_y ), Coord( alarm_hi_x, alarm_hi_y ) ); zone->alarm_box = Box( Coord( alarm_lo_x, alarm_lo_y ), Coord( alarm_hi_x, alarm_hi_y ) );
score = zone->score = ((100*blob_pixels)/blobs)/(zone->limits.Size().X()*zone->limits.Size().Y()); zone->score = ((100*blob_pixels)/blobs)/(zone->limits.Size().X()*zone->limits.Size().Y());
if ( zone->Type() == Zone::INCLUSIVE ) if ( zone->Type() == Zone::INCLUSIVE )
{ {
zone->score /= 2; zone->score /= 2;
@ -844,7 +838,7 @@ unsigned int Image::CheckAlarms( Zone *zone, const Image *delta_image ) const
{ {
zone->score *= 2; zone->score *= 2;
} }
//Info(( "%d - %d - %d - %.2f\n", zone->alarm_blobs, zone->alarm_pixels, zone->alarm_filter_pixels, zone->result )); score = zone->score;
// Now outline the changed region // Now outline the changed region
if ( zone->alarm_blobs ) if ( zone->alarm_blobs )
@ -879,9 +873,9 @@ unsigned int Image::CheckAlarms( Zone *zone, const Image *delta_image ) const
delete diff_image; delete diff_image;
//high_image->WriteJpeg( "diff4.jpg" ); //high_image->WriteJpeg( "diff4.jpg" );
Info(( "%s: Alarm Pixels: %d, Filter Pixels: %d, Blobs: %d, Score: %d\n", zone->Label(), alarm_pixels, filter_pixels, blobs, score )); Info(( "%s: Alarm Pixels: %d, Filter Pixels: %d, Blob Pixels: %d, Blobs: %d, Score: %d\n", zone->Label(), alarm_pixels, filter_pixels, blob_pixels, blobs, score ));
} }
return( score ); return( true );
} }
unsigned int Image::Compare( const Image &image, int n_zones, Zone *zones[] ) const unsigned int Image::Compare( const Image &image, int n_zones, Zone *zones[] ) const
@ -919,8 +913,6 @@ unsigned int Image::Compare( const Image &image, int n_zones, Zone *zones[] ) co
} }
} }
unsigned int zone_score = 0;
// Find all alarm pixels in active zones // Find all alarm pixels in active zones
for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) for ( int n_zone = 0; n_zone < n_zones; n_zone++ )
{ {
@ -930,12 +922,12 @@ unsigned int Image::Compare( const Image &image, int n_zones, Zone *zones[] ) co
continue; continue;
} }
Debug( 3, ( "Checking active zone %s", zone->Label() )); Debug( 3, ( "Checking active zone %s", zone->Label() ));
if ( zone_score = CheckAlarms( zone, delta_image ) ) if ( CheckAlarms( zone, delta_image ) )
{ {
alarm = true; alarm = true;
score += zone_score; score += zone->score;
zone->alarmed = true; zone->alarmed = true;
Debug( 3, ( "Zone is alarmed, zone score = %d", zone_score )); Debug( 3, ( "Zone is alarmed, zone score = %d", zone->score ));
} }
} }
@ -949,12 +941,12 @@ unsigned int Image::Compare( const Image &image, int n_zones, Zone *zones[] ) co
continue; continue;
} }
Debug( 3, ( "Checking inclusive zone %s", zone->Label() )); Debug( 3, ( "Checking inclusive zone %s", zone->Label() ));
if ( zone_score = CheckAlarms( zone, delta_image ) ) if ( CheckAlarms( zone, delta_image ) )
{ {
alarm = true; alarm = true;
score += zone_score; score += zone->score;
zone->alarmed = true; zone->alarmed = true;
Debug( 3, ( "Zone is alarmed, zone score = %d", zone_score )); Debug( 3, ( "Zone is alarmed, zone score = %d", zone->score ));
} }
} }
} }
@ -969,18 +961,19 @@ unsigned int Image::Compare( const Image &image, int n_zones, Zone *zones[] ) co
continue; continue;
} }
Debug( 3, ( "Checking exclusive zone %s", zone->Label() )); Debug( 3, ( "Checking exclusive zone %s", zone->Label() ));
if ( zone_score = CheckAlarms( zone, delta_image ) ) if ( CheckAlarms( zone, delta_image ) )
{ {
alarm = true; alarm = true;
score += zone_score; score += zone->score;
zone->alarmed = true; zone->alarmed = true;
Debug( 3, ( "Zone is alarmed, zone score = %d", zone_score )); Debug( 3, ( "Zone is alarmed, zone score = %d", zone->score ));
} }
} }
} }
delete delta_image; delete delta_image;
return( score ); // This is a small and innocent hack to prevent scores of 0 being returned in alarm state
return( score?score:alarm );
} }
void Image::Annotate( const char *text, const Coord &coord, const Rgb colour ) void Image::Annotate( const char *text, const Coord &coord, const Rgb colour )
@ -1486,7 +1479,7 @@ Monitor::Monitor( int p_id, char *p_name, int p_function, int p_device, int p_ch
{ {
n_zones = 1; n_zones = 1;
zones = new Zone *[1]; zones = new Zone *[1];
zones[0] = new Zone( 0, "All", Zone::ACTIVE, Box( width, height ), RGB_RED ); zones[0] = new Zone( this, 0, "All", Zone::ACTIVE, Box( width, height ), RGB_RED );
} }
start_time = last_fps_time = time( 0 ); start_time = last_fps_time = time( 0 );
@ -1530,10 +1523,7 @@ Monitor::Monitor( int p_id, char *p_name, int p_function, int p_device, int p_ch
} }
} }
//if ( capture ) record_zone_stats = true;
//{
//Camera::Capture( ref_image );
//}
} }
Monitor::~Monitor() Monitor::~Monitor()
@ -1557,6 +1547,12 @@ Monitor::~Monitor()
} }
} }
void Monitor::AddZones( int p_n_zones, Zone *p_zones[] )
{
n_zones = p_n_zones;
zones = p_zones;
}
Monitor::State Monitor::GetState() const Monitor::State Monitor::GetState() const
{ {
return( shared_images->state ); return( shared_images->state );
@ -1649,14 +1645,20 @@ void Monitor::CheckFunction()
void Monitor::DumpZoneImage() void Monitor::DumpZoneImage()
{ {
Mark();
int index = shared_images->last_write_index; int index = shared_images->last_write_index;
Mark();
Snapshot *snap = &image_buffer[index]; Snapshot *snap = &image_buffer[index];
Mark();
Image *image = snap->image; Image *image = snap->image;
Mark();
Image zone_image( *image ); Image zone_image( *image );
Mark();
zone_image.Colourise(); zone_image.Colourise();
for( int i = 0; i < n_zones; i++ ) for( int i = 0; i < n_zones; i++ )
{ {
Mark();
unsigned char *psrc = zone_image.buffer; unsigned char *psrc = zone_image.buffer;
int lo_x = zones[i]->Limits().Lo().X(); int lo_x = zones[i]->Limits().Lo().X();
int lo_y = zones[i]->Limits().Lo().Y(); int lo_y = zones[i]->Limits().Lo().Y();
@ -1699,8 +1701,11 @@ void Monitor::DumpZoneImage()
} }
} }
char filename[64]; char filename[64];
Mark();
sprintf( filename, "%s-Zones.jpg", name ); sprintf( filename, "%s-Zones.jpg", name );
Mark();
zone_image.WriteJpeg( filename ); zone_image.WriteJpeg( filename );
Mark();
} }
void Monitor::DumpImage( Image *image ) const void Monitor::DumpImage( Image *image ) const
@ -1785,6 +1790,10 @@ bool Monitor::Analyse()
if ( zones[i]->Alarmed() ) if ( zones[i]->Alarmed() )
{ {
alarm_image.Overlay( zones[i]->AlarmImage() ); alarm_image.Overlay( zones[i]->AlarmImage() );
if ( record_zone_stats )
{
zones[i]->RecordStats( event );
}
} }
} }
event->AddFrame( now, image, &alarm_image, score ); event->AddFrame( now, image, &alarm_image, score );
@ -1812,7 +1821,7 @@ void Monitor::ReloadZones()
delete zones[i]; delete zones[i];
} }
//delete[] zones; //delete[] zones;
n_zones = Zone::Load( id, width, height, zones ); n_zones = Zone::Load( this, zones );
DumpZoneImage(); DumpZoneImage();
} }
@ -1845,9 +1854,10 @@ int Monitor::Load( int device, Monitor **&monitors, bool capture )
monitors = new Monitor *[n_monitors]; monitors = new Monitor *[n_monitors];
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ )
{ {
monitors[i] = new Monitor( atoi(dbrow[0]), dbrow[1], atoi(dbrow[2]), atoi(dbrow[3]), atoi(dbrow[4]), atoi(dbrow[5]), atoi(dbrow[6]), atoi(dbrow[7]), atoi(dbrow[8]), capture, dbrow[9], Coord( atoi(dbrow[10]), atoi(dbrow[11]) ), atoi(dbrow[12]), atoi(dbrow[13]), atoi(dbrow[14]), atoi(dbrow[15]), atoi(dbrow[16]), atoi(dbrow[17]), atoi(dbrow[18]) );
Zone **zones = 0; Zone **zones = 0;
int n_zones = Zone::Load( atoi(dbrow[0]), atoi(dbrow[6]), atoi(dbrow[7]), zones ); int n_zones = Zone::Load( monitors[i], zones );
monitors[i] = new Monitor( atoi(dbrow[0]), dbrow[1], atoi(dbrow[2]), atoi(dbrow[3]), atoi(dbrow[4]), atoi(dbrow[5]), atoi(dbrow[6]), atoi(dbrow[7]), atoi(dbrow[8]), capture, dbrow[9], Coord( atoi(dbrow[10]), atoi(dbrow[11]) ), atoi(dbrow[12]), atoi(dbrow[13]), atoi(dbrow[14]), atoi(dbrow[15]), atoi(dbrow[16]), atoi(dbrow[17]), atoi(dbrow[18]), n_zones, zones ); monitors[i]->AddZones( n_zones, zones );
Info(( "Loaded monitor %d(%s), %d zones\n", atoi(dbrow[0]), dbrow[1], n_zones )); Info(( "Loaded monitor %d(%s), %d zones\n", atoi(dbrow[0]), dbrow[1], n_zones ));
} }
if ( mysql_errno( &dbconn ) ) if ( mysql_errno( &dbconn ) )
@ -1882,13 +1892,14 @@ Monitor *Monitor::Load( int id, bool load_zones )
Monitor *monitor = 0; Monitor *monitor = 0;
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ )
{ {
Zone **zones = 0; monitor = new Monitor( atoi(dbrow[0]), dbrow[1], atoi(dbrow[2]), atoi(dbrow[3]), atoi(dbrow[4]), atoi(dbrow[5]), atoi(dbrow[6]), atoi(dbrow[7]), atoi(dbrow[8]), false, dbrow[9], Coord( atoi(dbrow[10]), atoi(dbrow[11]) ), atoi(dbrow[12]), atoi(dbrow[13]), atoi(dbrow[14]), atoi(dbrow[15]), atoi(dbrow[16]), atoi(dbrow[17]), atoi(dbrow[18]) );
int n_zones = 0; int n_zones = 0;
if ( load_zones ) if ( load_zones )
{ {
int n_zones = Zone::Load( atoi(dbrow[0]), atoi(dbrow[6]), atoi(dbrow[7]), zones ); Zone **zones = 0;
n_zones = Zone::Load( monitor, zones );
monitor->AddZones( n_zones, zones );
} }
monitor = new Monitor( atoi(dbrow[0]), dbrow[1], atoi(dbrow[2]), atoi(dbrow[3]), atoi(dbrow[4]), atoi(dbrow[5]), atoi(dbrow[6]), atoi(dbrow[7]), atoi(dbrow[8]), false, dbrow[9], Coord( atoi(dbrow[10]), atoi(dbrow[11]) ), atoi(dbrow[12]), atoi(dbrow[13]), atoi(dbrow[14]), atoi(dbrow[15]), atoi(dbrow[16]), atoi(dbrow[17]), atoi(dbrow[18]), n_zones, zones );
Info(( "Loaded monitor %d(%s), %d zones\n", atoi(dbrow[0]), dbrow[1], n_zones )); Info(( "Loaded monitor %d(%s), %d zones\n", atoi(dbrow[0]), dbrow[1], n_zones ));
} }
if ( mysql_errno( &dbconn ) ) if ( mysql_errno( &dbconn ) )

View File

@ -183,7 +183,11 @@ public:
{ {
} }
inline const Coord &Lo() const { return( lo ); } inline const Coord &Lo() const { return( lo ); }
inline int LoX() const { return( lo.X() ); }
inline int LoY() const { return( lo.Y() ); }
inline const Coord &Hi() const { return( hi ); } inline const Coord &Hi() const { return( hi ); }
inline int HiX() const { return( hi.X() ); }
inline int HiY() const { return( hi.Y() ); }
inline const Coord &Size() const { return( size ); } inline const Coord &Size() const { return( size ); }
inline int Width() const inline int Width() const
{ {
@ -200,6 +204,9 @@ public:
} }
}; };
class Monitor;
class Event;
class Zone class Zone
{ {
friend class Image; friend class Image;
@ -209,6 +216,8 @@ public:
protected: protected:
// Inputs // Inputs
Monitor *monitor;
int id; int id;
char *label; char *label;
ZoneType type; ZoneType type;
@ -228,30 +237,33 @@ protected:
int min_blobs; int min_blobs;
int max_blobs; int max_blobs;
// Outputs // Outputs/Statistics
bool alarmed; bool alarmed;
int alarm_pixels; int alarm_pixels;
int alarm_filter_pixels; int alarm_filter_pixels;
int alarm_blob_pixels;
int alarm_blobs; int alarm_blobs;
int min_blob_size;
int max_blob_size;
Box alarm_box; Box alarm_box;
unsigned int score; unsigned int score;
Image *image; Image *image;
protected: protected:
void Setup( int p_id, const char *p_label, ZoneType p_type, const Box &p_limits, const Rgb p_alarm_rgb, int p_alarm_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, int p_alarm_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( int p_id, const char *p_label, ZoneType p_type, const Box &p_limits, const Rgb p_alarm_rgb, int p_alarm_threshold=15, 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, int p_alarm_threshold=15, 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_id, p_label, p_type, p_limits, p_alarm_rgb, p_alarm_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_alarm_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( int p_id, const char *p_label, const Box &p_limits, const Rgb p_alarm_rgb, int p_alarm_threshold=15, 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, int p_alarm_threshold=15, 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_id, p_label, Zone::ACTIVE, p_limits, p_alarm_rgb, p_alarm_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_alarm_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( 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_id, p_label, Zone::INACTIVE, p_limits, RGB_BLACK, 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, 0, 0, 0, Coord( 0, 0 ), 0, 0, 0, 0, 0, 0 );
} }
public: public:
@ -273,7 +285,19 @@ public:
{ {
return( alarmed ); return( alarmed );
} }
static int Load( int monitor_id, int width, int height, Zone **&zones ); inline void ResetStats()
{
alarmed = false;
alarm_pixels = 0;
alarm_filter_pixels = 0;
alarm_blob_pixels = 0;
alarm_blobs = 0;
min_blob_size = 0;
max_blob_size = 0;
score = 0;
}
void RecordStats( const Event *event );
static int Load( Monitor *monitor, Zone **&zones );
}; };
class Camera; class Camera;
@ -383,7 +407,7 @@ public:
static Image *Merge( int n_images, Image *images[], double weight ); static Image *Merge( int n_images, Image *images[], double weight );
static Image *Highlight( int n_images, Image *images[], const Rgb threshold=RGB_BLACK, const Rgb ref_colour=RGB_RED ); static Image *Highlight( int n_images, Image *images[], const Rgb threshold=RGB_BLACK, const Rgb ref_colour=RGB_RED );
Image *Delta( const Image &image, bool absolute=true ) const; Image *Delta( const Image &image, bool absolute=true ) const;
unsigned int CheckAlarms( Zone *zone, const Image *delta_image ) const; bool CheckAlarms( Zone *zone, const Image *delta_image ) const;
unsigned int Compare( const Image &image, int n_zones, Zone *zones[] ) const; unsigned int Compare( const Image &image, int n_zones, Zone *zones[] ) const;
void Annotate( const char *text, const Coord &coord, const Rgb colour ); void Annotate( const char *text, const Coord &coord, const Rgb colour );
void Annotate( const char *text, const Coord &coord ); void Annotate( const char *text, const Coord &coord );
@ -402,8 +426,8 @@ protected:
int device; int device;
int channel; int channel;
int format; int format;
int width; unsigned int width;
int height; unsigned int height;
int colours; int colours;
bool capture; bool capture;
@ -427,6 +451,9 @@ public:
{ {
return( name ); return( name );
} }
unsigned int Width() const { return( width ); }
unsigned int Height() const { return( height ); }
static void Initialise( int device, int channel, int format, int width, int height, int colours ); static void Initialise( int device, int channel, int format, int width, int height, int colours );
void Terminate(); void Terminate();
@ -516,6 +543,11 @@ protected:
public: public:
Event( Monitor *p_monitor, time_t p_start_time ); Event( Monitor *p_monitor, time_t p_start_time );
~Event(); ~Event();
int Id() const { return( id ); }
int Frames() const { return( frames ); }
int AlarmFrames() const { return( alarm_frames ); }
void AddFrame( time_t timestamp, const Image *image, const Image *alarm_frame=NULL, unsigned int score=0 ); void AddFrame( time_t timestamp, const Image *image, const Image *alarm_frame=NULL, unsigned int score=0 );
static void StreamEvent( const char *path, int event_id, unsigned long refresh=100, FILE *fd=stdout ); static void StreamEvent( const char *path, int event_id, unsigned long refresh=100, FILE *fd=stdout );
@ -578,10 +610,14 @@ protected:
SharedImages *shared_images; SharedImages *shared_images;
bool record_zone_stats;
public: public:
Monitor( int p_id, char *p_name, int p_function, int p_device, int p_channel, int p_format, int p_width, int p_height, int p_colours, bool p_capture, char *p_label_format, const Coord &p_label_coord, int p_warmup_count, int p_pre_event_count, int p_post_event_count, int p_alarm_frame_count, int p_image_buffer_count, int p_fps_report_interval, int p_ref_blend_perc, int p_n_zones=0, Zone *p_zones[]=0 ); Monitor( int p_id, char *p_name, int p_function, int p_device, int p_channel, int p_format, int p_width, int p_height, int p_colours, bool p_capture, char *p_label_format, const Coord &p_label_coord, int p_warmup_count, int p_pre_event_count, int p_post_event_count, int p_alarm_frame_count, int p_image_buffer_count, int p_fps_report_interval, int p_ref_blend_perc, int p_n_zones=0, Zone *p_zones[]=0 );
~Monitor(); ~Monitor();
void AddZones( int p_n_zones, Zone *p_zones[] );
State GetState() const; State GetState() const;
int GetImage( int index=-1 ) const; int GetImage( int index=-1 ) const;
time_t GetTimestamp( int index=-1 ) const; time_t GetTimestamp( int index=-1 ) const;

View File

@ -21,6 +21,12 @@
bool reload = false; bool reload = false;
void die_handler( int signal )
{
Info(( "Got signal %d, crashing", signal ));
exit( signal );
}
void hup_handler( int signal ) void hup_handler( int signal )
{ {
Info(( "Got HUP signal, reloading" )); Info(( "Got HUP signal, reloading" ));
@ -63,17 +69,27 @@ int main( int argc, const char *argv[] )
int n_monitors = Monitor::Load( device, monitors, false ); int n_monitors = Monitor::Load( device, monitors, false );
Info(( "Warming up" )); Info(( "Warming up" ));
sigset_t block_set; sigset_t block_set;
sigemptyset( &block_set ); sigemptyset( &block_set );
struct sigaction action, old_action; struct sigaction action, old_action;
action.sa_handler = hup_handler; action.sa_handler = hup_handler;
action.sa_mask = block_set; action.sa_mask = block_set;
action.sa_flags = 0; action.sa_flags = 0;
sigaction( SIGHUP, &action, &old_action ); sigaction( SIGHUP, &action, &old_action );
action.sa_handler = term_handler; action.sa_handler = term_handler;
action.sa_mask = block_set; action.sa_mask = block_set;
action.sa_flags = 0; action.sa_flags = 0;
sigaction( SIGTERM, &action, &old_action ); sigaction( SIGTERM, &action, &old_action );
action.sa_handler = die_handler;
action.sa_mask = block_set;
action.sa_flags = 0;
sigaction( SIGBUS, &action, &old_action );
sigaction( SIGSEGV, &action, &old_action );
sigaddset( &block_set, SIGHUP ); sigaddset( &block_set, SIGHUP );
//sigaddset( &block_set, SIGTERM ); //sigaddset( &block_set, SIGTERM );
while( 1 ) while( 1 )
@ -97,7 +113,9 @@ int main( int argc, const char *argv[] )
{ {
for ( int i = 0; i < n_monitors; i++ ) for ( int i = 0; i < n_monitors; i++ )
{ {
Mark();
monitors[i]->ReloadZones(); monitors[i]->ReloadZones();
Mark();
monitors[i]->CheckFunction(); monitors[i]->CheckFunction();
} }
reload = false; reload = false;

View File

@ -58,7 +58,7 @@
#define Fatal(params) DbgPrintf(DBG_FAT,params) #define Fatal(params) DbgPrintf(DBG_FAT,params)
#define Entrypoint(params) DbgPrintf(9,params); #define Entrypoint(params) DbgPrintf(9,params);
#define Exitpoint(params) DbgPrintf(9,params); #define Exitpoint(params) DbgPrintf(9,params);
#define Mark() Info(("Mark")) #define Mark() Info(("Mark/%s/%d", __FILE__, __LINE__ ))
#define Log() Info(("Log")) #define Log() Info(("Log"))
#ifdef __GNUC__ #ifdef __GNUC__
#define Enter(level) DbgPrintf(level,("Entering %s",__PRETTY_FUNCTION__)) #define Enter(level) DbgPrintf(level,("Entering %s",__PRETTY_FUNCTION__))