Set a reference image for each zone
This commit is contained in:
parent
0d430b5f4f
commit
217aafee5a
|
@ -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,8 +3362,7 @@ 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 )
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
140
src/zm_zone.cpp
140
src/zm_zone.cpp
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 ); }
|
||||||
|
|
Loading…
Reference in New Issue