Set a reference image for each zone

This commit is contained in:
manupap1 2014-11-11 21:48:56 +01:00
parent 0d430b5f4f
commit 217aafee5a
4 changed files with 231 additions and 100 deletions

View File

@ -311,8 +311,6 @@ Monitor::Monitor(
alarm_ref_blend_perc( p_alarm_ref_blend_perc ), alarm_ref_blend_perc( p_alarm_ref_blend_perc ),
track_motion( p_track_motion ), track_motion( p_track_motion ),
signal_check_colour( p_signal_check_colour ), signal_check_colour( p_signal_check_colour ),
delta_image( width, height, ZM_COLOUR_GRAY8, ZM_SUBPIX_ORDER_NONE ),
ref_image( width, height, p_camera->Colours(), p_camera->SubpixelOrder() ),
purpose( p_purpose ), purpose( p_purpose ),
last_motion_score(0), last_motion_score(0),
camera( p_camera ), camera( p_camera ),
@ -484,7 +482,6 @@ Monitor::Monitor(
Warning( "Waiting for capture daemon" ); Warning( "Waiting for capture daemon" );
sleep( 1 ); sleep( 1 );
} }
ref_image.Assign( width, height, camera->Colours(), camera->SubpixelOrder(), image_buffer[shared_data->last_write_index].image->Buffer(), camera->ImageSize());
n_linked_monitors = 0; n_linked_monitors = 0;
linked_monitors = 0; linked_monitors = 0;
@ -1217,7 +1214,10 @@ bool Monitor::Analyse()
{ {
Info( "Received resume indication at count %d", image_count ); Info( "Received resume indication at count %d", image_count );
shared_data->active = true; shared_data->active = true;
ref_image = *snap_image; for ( int n_zone = 0; n_zone < n_zones; n_zone++ )
{
zones[n_zone]->SetRefImage(*snap_image);
}
ready_count = image_count+(warmup_count/2); ready_count = image_count+(warmup_count/2);
shared_data->alarm_x = shared_data->alarm_y = -1; shared_data->alarm_x = shared_data->alarm_y = -1;
} }
@ -1228,7 +1228,10 @@ bool Monitor::Analyse()
{ {
Info( "Auto resuming at count %d", image_count ); Info( "Auto resuming at count %d", image_count );
shared_data->active = true; shared_data->active = true;
ref_image = *snap_image; for ( int n_zone = 0; n_zone < n_zones; n_zone++ )
{
zones[n_zone]->SetRefImage(*snap_image);
}
ready_count = image_count+(warmup_count/2); ready_count = image_count+(warmup_count/2);
auto_resume_time = 0; auto_resume_time = 0;
} }
@ -1300,32 +1303,36 @@ bool Monitor::Analyse()
noteSetMap[SIGNAL_CAUSE] = noteSet; noteSetMap[SIGNAL_CAUSE] = noteSet;
shared_data->state = state = IDLE; shared_data->state = state = IDLE;
shared_data->active = signal; shared_data->active = signal;
ref_image = *snap_image; for ( int n_zone = 0; n_zone < n_zones; n_zone++ )
{
zones[n_zone]->SetRefImage(*snap_image);
}
} }
else if ( signal && Active() && (function == MODECT || function == MOCORD) ) else if ( signal && Active() && (function == MODECT || function == MOCORD) )
{ {
Event::StringSet zoneSet; Event::StringSet zoneSet;
int motion_score = last_motion_score; unsigned int motion_score = last_motion_score;
bool alarm = false;
if ( !(image_count % (motion_frame_skip+1) ) ) if ( !(image_count % (motion_frame_skip+1) ) )
{ {
// Get new score. // Get new score.
motion_score = last_motion_score = DetectMotion( *snap_image, zoneSet ); alarm = DetectMotion( *snap_image, zoneSet, motion_score );
last_motion_score = motion_score;
} }
//int motion_score = DetectBlack( *snap_image, zoneSet ); //int motion_score = DetectBlack( *snap_image, zoneSet );
if ( motion_score ) if ( alarm )
{ {
if ( !event ) if ( motion_score )
{ {
score += motion_score; score += motion_score;
if ( cause.length() ) if ( !event )
cause += ", "; {
cause += MOTION_CAUSE; if ( cause.length() )
cause += ", ";
cause += MOTION_CAUSE;
}
noteSetMap[MOTION_CAUSE] = zoneSet;
} }
else
{
score += motion_score;
}
noteSetMap[MOTION_CAUSE] = zoneSet;
} }
shared_data->active = signal; shared_data->active = signal;
@ -1617,10 +1624,10 @@ bool Monitor::Analyse()
} }
if ( (!signal_change && signal) && (function == MODECT || function == MOCORD) ) if ( (!signal_change && signal) && (function == MODECT || function == MOCORD) )
{ {
if ( state == ALARM ) { int ref_blend = ( state == ALARM ) ? alarm_ref_blend_perc : ref_blend_perc;
ref_image.Blend( *snap_image, alarm_ref_blend_perc ); for ( int n_zone = 0; n_zone < n_zones; n_zone++ )
} else { {
ref_image.Blend( *snap_image, ref_blend_perc ); zones[n_zone]->BlendRefImage( *snap_image, ref_blend );
} }
} }
last_signal = signal; last_signal = signal;
@ -3166,33 +3173,31 @@ unsigned int Monitor::DetectBlack(const Image &comp_image, Event::StringSet &zon
unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &zoneSet ) unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &zoneSet, unsigned int &score )
{ {
bool alarm = false; bool alarm = false;
unsigned int score = 0; score = 0;
if ( n_zones <= 0 ) return( alarm ); if ( n_zones <= 0 ) return( alarm );
if ( config.record_diag_images ) for ( int n_zone = 0; n_zone < n_zones; n_zone++ )
{ {
static char diag_path[PATH_MAX] = ""; Zone *zone = zones[n_zone];
if ( !diag_path[0] ) if ( config.record_diag_images )
{ {
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-r.jpg", config.dir_events, id ); static char diag_path[PATH_MAX] = "";
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-r.jpg", config.dir_events, id, zone->Id() );
zone->WriteRefImage( diag_path );
} }
ref_image.WriteJpeg( diag_path );
}
ref_image.Delta( comp_image, &delta_image); zone->SetDeltaImage( comp_image );
if ( config.record_diag_images ) if ( config.record_diag_images )
{
static char diag_path[PATH_MAX] = "";
if ( !diag_path[0] )
{ {
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-d.jpg", config.dir_events, id ); static char diag_path[PATH_MAX] = "";
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-d.jpg", config.dir_events, id, zone->Id() );
zone->WriteDeltaImage( diag_path );
} }
delta_image.WriteJpeg( diag_path );
} }
// Blank out all exclusion zones // Blank out all exclusion zones
@ -3207,7 +3212,7 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z
continue; continue;
} }
Debug( 3, "Blanking inactive zone %s", zone->Label() ); Debug( 3, "Blanking inactive zone %s", zone->Label() );
delta_image.Fill( RGB_BLACK, zone->GetPolygon() ); zone->FillDeltaImage( RGB_BLACK );
} }
// Check preclusive zones first // Check preclusive zones first
@ -3221,13 +3226,16 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z
int old_zone_score = zone->Score(); int old_zone_score = zone->Score();
bool old_zone_alarmed = zone->Alarmed(); bool old_zone_alarmed = zone->Alarmed();
Debug( 3, "Checking preclusive zone %s - old score: %d, state: %s", zone->Label(),old_zone_score, zone->Alarmed()?"alarmed":"quiet" ); Debug( 3, "Checking preclusive zone %s - old score: %d, state: %s", zone->Label(),old_zone_score, zone->Alarmed()?"alarmed":"quiet" );
if ( zone->CheckAlarms( &delta_image ) ) if ( zone->CheckAlarms( &comp_image ) )
{ {
alarm = true; alarm = true;
score += zone->Score(); score += zone->Score();
zone->SetAlarm(); if ( !zone->IsPostProcEnabled() )
Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); {
zoneSet.insert( zone->Label() ); zone->SetAlarm();
Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() );
zoneSet.insert( ("[Zone " + std::string(zone->Label()) + "]\n").c_str() );
}
//zone->ResetStats(); //zone->ResetStats();
} else { } else {
// check if end of alarm // check if end of alarm
@ -3265,24 +3273,26 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z
continue; continue;
} }
Debug( 3, "Checking active zone %s", zone->Label() ); Debug( 3, "Checking active zone %s", zone->Label() );
if ( zone->CheckAlarms( &delta_image ) ) if ( zone->CheckAlarms( &comp_image ) )
{ {
alarm = true; alarm = true;
score += zone->Score();
zone->SetAlarm(); zone->SetAlarm();
Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); score += zone->Score();
zoneSet.insert( zone->Label() ); if ( !zone->IsPostProcEnabled() )
if ( config.opt_control && track_motion )
{ {
if ( (int)zone->Score() > top_score ) Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() );
zoneSet.insert( ("[Zone " + std::string(zone->Label()) + "]\n").c_str() );
if ( config.opt_control && track_motion )
{ {
top_score = zone->Score(); if ( (int)zone->Score() > top_score )
alarm_centre = zone->GetAlarmCentre(); {
top_score = zone->Score();
alarm_centre = zone->GetAlarmCentre();
}
} }
} }
} }
} }
if ( alarm ) if ( alarm )
{ {
for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) for ( int n_zone = 0; n_zone < n_zones; n_zone++ )
@ -3293,19 +3303,22 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z
continue; continue;
} }
Debug( 3, "Checking inclusive zone %s", zone->Label() ); Debug( 3, "Checking inclusive zone %s", zone->Label() );
if ( zone->CheckAlarms( &delta_image ) ) if ( zone->CheckAlarms( &comp_image ) )
{ {
alarm = true; alarm = true;
score += zone->Score();
zone->SetAlarm(); zone->SetAlarm();
Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); score += zone->Score();
zoneSet.insert( zone->Label() ); if ( !zone->IsPostProcEnabled() )
if ( config.opt_control && track_motion )
{ {
if ( zone->Score() > (unsigned int)top_score ) Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() );
zoneSet.insert( ("[Zone " + std::string(zone->Label()) + "]\n").c_str() );
if ( config.opt_control && track_motion )
{ {
top_score = zone->Score(); if ( zone->Score() > (unsigned int)top_score )
alarm_centre = zone->GetAlarmCentre(); {
top_score = zone->Score();
alarm_centre = zone->GetAlarmCentre();
}
} }
} }
} }
@ -3322,13 +3335,16 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z
continue; continue;
} }
Debug( 3, "Checking exclusive zone %s", zone->Label() ); Debug( 3, "Checking exclusive zone %s", zone->Label() );
if ( zone->CheckAlarms( &delta_image ) ) if ( zone->CheckAlarms( &comp_image ) )
{ {
alarm = true; alarm = true;
score += zone->Score();
zone->SetAlarm(); zone->SetAlarm();
Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); score += zone->Score();
zoneSet.insert( zone->Label() ); if ( !zone->IsPostProcEnabled() )
{
Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() );
zoneSet.insert( ("[Zone " + std::string(zone->Label()) + "]\n").c_str() );
}
} }
} }
} }
@ -3346,9 +3362,8 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z
shared_data->alarm_x = shared_data->alarm_y = -1; shared_data->alarm_x = shared_data->alarm_y = -1;
} }
// This is a small and innocent hack to prevent scores of 0 being returned in alarm state return alarm;
return( score?score:alarm ); }
}
bool Monitor::DumpSettings( char *output, bool verbose ) bool Monitor::DumpSettings( char *output, bool verbose )
{ {

View File

@ -244,8 +244,6 @@ protected:
Rgb signal_check_colour; // The colour that the camera will emit when no video signal detected Rgb signal_check_colour; // The colour that the camera will emit when no video signal detected
double fps; double fps;
Image delta_image;
Image ref_image;
Purpose purpose; // What this monitor has been created to do Purpose purpose; // What this monitor has been created to do
int event_count; int event_count;
@ -385,6 +383,7 @@ public:
} }
unsigned int DetectMotion( const Image &comp_image, Event::StringSet &zoneSet ); unsigned int DetectMotion( const Image &comp_image, Event::StringSet &zoneSet );
unsigned int DetectMotion( const Image &comp_image, Event::StringSet &zoneSet, unsigned int &score );
// DetectBlack seems to be unused. Check it on zm_monitor.cpp for more info. // DetectBlack seems to be unused. Check it on zm_monitor.cpp for more info.
//unsigned int DetectBlack( const Image &comp_image, Event::StringSet &zoneSet ); //unsigned int DetectBlack( const Image &comp_image, Event::StringSet &zoneSet );
bool CheckSignal( const Image *image ); bool CheckSignal( const Image *image );

View File

@ -60,10 +60,20 @@ void Zone::Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_
max_blob_size = 0; max_blob_size = 0;
image = 0; image = 0;
score = 0; score = 0;
text = "";
post_proc_enabled = false;
post_proc_in_progress = false;
include_nat_det = true;
reinit_nat_det = false;
overload_count = 0; overload_count = 0;
extend_alarm_count = 0; extend_alarm_count = 0;
delta_image = Image( monitor->Width(), monitor->Height(), ZM_COLOUR_GRAY8, ZM_SUBPIX_ORDER_NONE );
ref_image = Image( monitor->Width(), monitor->Height(), monitor->Colours(), monitor->SubpixelOrder());
bl_image = Image( monitor->Width(), monitor->Height(), monitor->Colours(), monitor->SubpixelOrder());
bl_image.Fill( RGB_BLACK );
pg_image = new Image( monitor->Width(), monitor->Height(), 1, ZM_SUBPIX_ORDER_NONE); pg_image = new Image( monitor->Width(), monitor->Height(), 1, ZM_SUBPIX_ORDER_NONE);
pg_image->Clear(); pg_image->Clear();
pg_image->Fill( 0xff, polygon ); pg_image->Fill( 0xff, polygon );
@ -91,14 +101,10 @@ void Zone::Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_
} }
} }
} }
if ( config.record_diag_images && (id > 0))
if ( config.record_diag_images )
{ {
static char diag_path[PATH_MAX] = ""; static char diag_path[PATH_MAX] = "";
if ( !diag_path[0] ) snprintf( diag_path, sizeof(diag_path), "%s/%s/diag-%d-poly.jpg", config.dir_events, monitor->Name(), id);
{
snprintf( diag_path, sizeof(diag_path), "%s/%s/diag-%d-poly.jpg", config.dir_events, monitor->Name(), id);
}
pg_image->WriteJpeg( diag_path ); pg_image->WriteJpeg( diag_path );
} }
} }
@ -142,6 +148,37 @@ void Zone::SetScore(unsigned int nScore)
score = nScore; score = nScore;
} }
void Zone::SetText(std::string sText)
{
text = "[Zone ";
text += label;
text += "]\n" + sText;
}
void Zone::AssignRefImage( unsigned int p_width, unsigned int p_height, unsigned int p_colours, unsigned int p_subpixelorder, const uint8_t* new_buffer, const size_t buffer_size )
{
ref_image.Assign( p_width, p_height, p_colours, p_subpixelorder, new_buffer, buffer_size);
}
void Zone::SetRefImage(const Image &srcImage)
{
ref_image = srcImage;
}
void Zone::BlendRefImage( const Image &srcImage, int transparency )
{
ref_image.Blend( srcImage, transparency );
}
void Zone::SetDeltaImage( const Image &srcImage )
{
ref_image.Delta( srcImage, &delta_image );
}
void Zone::FillDeltaImage( Rgb colour )
{
delta_image.Fill( colour, polygon);
}
void Zone::SetAlarmImage(const Image* srcImage) void Zone::SetAlarmImage(const Image* srcImage)
{ {
@ -149,6 +186,16 @@ void Zone::SetAlarmImage(const Image* srcImage)
image = new Image(*srcImage); image = new Image(*srcImage);
} }
bool Zone::WriteRefImage( const char *filename, int quality_override ) const
{
return ref_image.WriteJpeg( filename, quality_override );
}
bool Zone::WriteDeltaImage( const char *filename, int quality_override ) const
{
return delta_image.WriteJpeg( filename, quality_override );
}
int Zone::GetOverloadCount() int Zone::GetOverloadCount()
{ {
return overload_count; return overload_count;
@ -194,9 +241,33 @@ bool Zone::CheckExtendAlarmCount()
//=========================================================================== //===========================================================================
void Zone::SetConfig( zConf zone_conf )
{
post_proc_enabled = zone_conf.RequireNatDet;
include_nat_det = zone_conf.IncludeNatDet;
reinit_nat_det = zone_conf.ReInitNatDet;
if ( post_proc_enabled ) {
std::string sMessage;
if ( include_nat_det ) {
sMessage = "(native detection included";
}
if ( reinit_nat_det ) {
if (sMessage.empty()) {
sMessage = "(native detection will be reinitialized";
} else {
sMessage += ", reinitialization is required";
}
}
if (!sMessage.empty()) {
sMessage += ")";
}
Info("Post processing enabled for zone '%s' %s", label, sMessage.c_str());
}
}
bool Zone::CheckAlarms( const Image *delta_image ) bool Zone::CheckAlarms( const Image *comp_image )
{ {
ResetStats(); ResetStats();
@ -205,12 +276,13 @@ bool Zone::CheckAlarms( const Image *delta_image )
Info( "In overload mode, %d frames of %d remaining", overload_count, overload_frames ); 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 ); Debug( 4, "In overload mode, %d frames of %d remaining", overload_count, overload_frames );
overload_count--; overload_count--;
post_proc_in_progress = false;
return( false ); return( false );
} }
delete image; delete image;
// Get the difference image // Get the difference image
Image *diff_image = image = new Image( *delta_image ); Image *diff_image = image = new Image( delta_image );
int diff_width = diff_image->Width(); int diff_width = diff_image->Width();
uint8_t* diff_buff = (uint8_t*)diff_image->Buffer(); uint8_t* diff_buff = (uint8_t*)diff_image->Buffer();
uint8_t* pdiff; uint8_t* pdiff;
@ -245,10 +317,7 @@ bool Zone::CheckAlarms( const Image *delta_image )
if ( config.record_diag_images ) if ( config.record_diag_images )
{ {
static char diag_path[PATH_MAX] = ""; static char diag_path[PATH_MAX] = "";
if ( !diag_path[0] ) snprintf( diag_path, sizeof(diag_path), "%s/%s/diag-%d-%d.jpg", config.dir_events, monitor->Name(), id, 1 );
{
snprintf( diag_path, sizeof(diag_path), "%s/%s/diag-%d-%d.jpg", config.dir_events, monitor->Name(), id, 1 );
}
diff_image->WriteJpeg( diag_path ); diff_image->WriteJpeg( diag_path );
} }
@ -259,14 +328,17 @@ bool Zone::CheckAlarms( const Image *delta_image )
if( alarm_pixels ) { if( alarm_pixels ) {
if( min_alarm_pixels && (alarm_pixels < (unsigned int)min_alarm_pixels) ) { if( min_alarm_pixels && (alarm_pixels < (unsigned int)min_alarm_pixels) ) {
/* Not enough pixels alarmed */ /* Not enough pixels alarmed */
post_proc_in_progress = false;
return (false); return (false);
} else if( max_alarm_pixels && (alarm_pixels > (unsigned int)max_alarm_pixels) ) { } else if( max_alarm_pixels && (alarm_pixels > (unsigned int)max_alarm_pixels) ) {
/* Too many pixels alarmed */ /* Too many pixels alarmed */
overload_count = overload_frames; overload_count = overload_frames;
post_proc_in_progress = false;
return (false); return (false);
} }
} else { } else {
/* No alarmed pixels */ /* No alarmed pixels */
post_proc_in_progress = false;
return (false); return (false);
} }
@ -342,10 +414,7 @@ bool Zone::CheckAlarms( const Image *delta_image )
if ( config.record_diag_images ) if ( config.record_diag_images )
{ {
static char diag_path[PATH_MAX] = ""; static char diag_path[PATH_MAX] = "";
if ( !diag_path[0] ) snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 2 );
{
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 2 );
}
diff_image->WriteJpeg( diag_path ); diff_image->WriteJpeg( diag_path );
} }
@ -354,14 +423,17 @@ bool Zone::CheckAlarms( const Image *delta_image )
if( alarm_filter_pixels ) { if( alarm_filter_pixels ) {
if( min_filter_pixels && (alarm_filter_pixels < min_filter_pixels) ) { if( min_filter_pixels && (alarm_filter_pixels < min_filter_pixels) ) {
/* Not enough pixels alarmed */ /* Not enough pixels alarmed */
post_proc_in_progress = false;
return (false); return (false);
} else if( max_filter_pixels && (alarm_filter_pixels > max_filter_pixels) ) { } else if( max_filter_pixels && (alarm_filter_pixels > max_filter_pixels) ) {
/* Too many pixels alarmed */ /* Too many pixels alarmed */
overload_count = overload_frames; overload_count = overload_frames;
post_proc_in_progress = false;
return (false); return (false);
} }
} else { } else {
/* No filtered pixels */ /* No filtered pixels */
post_proc_in_progress = false;
return (false); return (false);
} }
@ -583,15 +655,13 @@ bool Zone::CheckAlarms( const Image *delta_image )
if ( config.record_diag_images ) if ( config.record_diag_images )
{ {
static char diag_path[PATH_MAX] = ""; static char diag_path[PATH_MAX] = "";
if ( !diag_path[0] ) snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 3 );
{
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 3 );
}
diff_image->WriteJpeg( diag_path ); diff_image->WriteJpeg( diag_path );
} }
if ( !alarm_blobs ) if ( !alarm_blobs )
{ {
post_proc_in_progress = false;
return( false ); return( false );
} }
@ -642,10 +712,7 @@ bool Zone::CheckAlarms( const Image *delta_image )
if ( config.record_diag_images ) if ( config.record_diag_images )
{ {
static char diag_path[PATH_MAX] = ""; static char diag_path[PATH_MAX] = "";
if ( !diag_path[0] ) snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 4 );
{
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 4 );
}
diff_image->WriteJpeg( diag_path ); diff_image->WriteJpeg( diag_path );
} }
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 ); 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 );
@ -653,14 +720,17 @@ bool Zone::CheckAlarms( const Image *delta_image )
if( alarm_blobs ) { if( alarm_blobs ) {
if( min_blobs && (alarm_blobs < min_blobs) ) { if( min_blobs && (alarm_blobs < min_blobs) ) {
/* Not enough pixels alarmed */ /* Not enough pixels alarmed */
post_proc_in_progress = false;
return (false); return (false);
} else if(max_blobs && (alarm_blobs > max_blobs) ) { } else if(max_blobs && (alarm_blobs > max_blobs) ) {
/* Too many pixels alarmed */ /* Too many pixels alarmed */
overload_count = overload_frames; overload_count = overload_frames;
post_proc_in_progress = false;
return (false); return (false);
} }
} else { } else {
/* No blobs */ /* No blobs */
post_proc_in_progress = false;
return (false); return (false);
} }
@ -797,13 +867,23 @@ bool Zone::CheckAlarms( const Image *delta_image )
} }
} }
} }
if ( post_proc_enabled ) {
if( monitor->Colours() == ZM_COLOUR_GRAY8 ) { post_proc_in_progress = true;
image = diff_image->HighlightEdges( alarm_rgb, ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB, &polygon.Extent() ); }
} else { if ( include_nat_det ) {
image = diff_image->HighlightEdges( alarm_rgb, monitor->Colours(), monitor->SubpixelOrder(), &polygon.Extent() ); if( monitor->Colours() == ZM_COLOUR_GRAY8 ) {
image = diff_image->HighlightEdges( alarm_rgb, ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB, &polygon.Extent() );
} else {
image = diff_image->HighlightEdges( alarm_rgb, monitor->Colours(), monitor->SubpixelOrder(), &polygon.Extent() );
}
} else {
score = 0;
image = new Image( bl_image );
}
// Update reference image if required
if ( reinit_nat_det ) {
ref_image = *comp_image;
} }
// 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;
} }

View File

@ -28,6 +28,19 @@
class Monitor; class Monitor;
//! A structure to store the post processing configuration for the zone
struct zConf
{
bool RequireNatDet;
bool IncludeNatDet;
bool ReInitNatDet;
zConf():
RequireNatDet(false),
IncludeNatDet(false),
ReInitNatDet(false)
{}
};
// //
// This describes a 'zone', or an area of an image that has certain // This describes a 'zone', or an area of an image that has certain
// detection characteristics. // detection characteristics.
@ -87,12 +100,20 @@ protected:
Box alarm_box; Box alarm_box;
Coord alarm_centre; Coord alarm_centre;
unsigned int score; unsigned int score;
std::string text;
Image *pg_image; Image *pg_image;
Range *ranges; Range *ranges;
Image *image; Image *image;
Image delta_image;
Image ref_image;
Image bl_image;
int overload_count; int overload_count;
int extend_alarm_count; int extend_alarm_count;
bool post_proc_enabled;
bool include_nat_det;
bool reinit_nat_det;
bool post_proc_in_progress;
protected: 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, int p_overload_frames, int p_extend_alarm_frames ); 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, int p_extend_alarm_frames );
@ -130,7 +151,14 @@ public:
inline void ClearAlarm() { alarmed = false; } inline void ClearAlarm() { alarmed = false; }
inline Coord GetAlarmCentre() const { return( alarm_centre ); } inline Coord GetAlarmCentre() const { return( alarm_centre ); }
inline unsigned int Score() const { return( score ); } inline unsigned int Score() const { return( score ); }
inline std::string Text() const { return( text ); }
void SetConfig( zConf zone_conf );
inline bool IsPostProcEnabled() const { return post_proc_enabled; }
inline bool IsNatDetIncluded() const { return include_nat_det; }
inline bool IsNatDetReInitialized() const { return reinit_nat_det; }
inline void StartPostProcessing() { post_proc_in_progress = true; }
inline void StopPostProcessing() { post_proc_in_progress = false; }
inline bool IsPostProcInProgress() { return post_proc_in_progress; }
inline void ResetStats() inline void ResetStats()
{ {
alarmed = false; alarmed = false;
@ -142,9 +170,10 @@ public:
min_blob_size = 0; min_blob_size = 0;
max_blob_size = 0; max_blob_size = 0;
score = 0; score = 0;
text = "";
} }
void RecordStats( const Event *event ); void RecordStats( const Event *event );
bool CheckAlarms( const Image *delta_image ); bool CheckAlarms( const Image *comp_image );
bool DumpSettings( char *output, bool verbose ); bool DumpSettings( char *output, bool verbose );
static bool ParsePolygonString( const char *polygon_string, Polygon &polygon ); static bool ParsePolygonString( const char *polygon_string, Polygon &polygon );
@ -161,7 +190,15 @@ public:
void SetExtendAlarmCount(int nOverCount); void SetExtendAlarmCount(int nOverCount);
int GetExtendAlarmFrames(); int GetExtendAlarmFrames();
void SetScore(unsigned int nScore); void SetScore(unsigned int nScore);
void SetText(std::string sText);
void SetAlarmImage(const Image* srcImage); void SetAlarmImage(const Image* srcImage);
void AssignRefImage( unsigned int p_width, unsigned int p_height, unsigned int p_colours, unsigned int p_subpixelorder, const uint8_t* new_buffer, const size_t buffer_size );
void SetRefImage( const Image &srcImage);
void BlendRefImage( const Image &srcImage, int transparency=12 );
void SetDeltaImage( const Image &srcImage );
void FillDeltaImage( Rgb colour );
bool WriteRefImage( const char *filename, int quality_override=0 ) const;
bool WriteDeltaImage( const char *filename, int quality_override=0 ) const;
inline const Image *getPgImage() const { return( pg_image ); } inline const Image *getPgImage() const { return( pg_image ); }
inline const Range *getRanges() const { return( ranges ); } inline const Range *getRanges() const { return( ranges ); }