cleanup. Google Code Style. Move diag_path from a static to a class member so that multiple zones will create different diag files.
parent
3ab0755e03
commit
18b015903a
349
src/zm_zone.cpp
349
src/zm_zone.cpp
|
@ -108,14 +108,12 @@ void Zone::Setup(
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME: Is this not a problem? If you had two zones for a monitor.. then these would conflict. You would only get 1 dump file
|
||||
if ( config.record_diag_images ) {
|
||||
static char diag_path[PATH_MAX] = "";
|
||||
if ( ! diag_path[0] ) {
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/diag-%d-poly.jpg", monitor->getStorage()->Path(), id);
|
||||
}
|
||||
pg_image->WriteJpeg( diag_path );
|
||||
}
|
||||
snprintf(diag_path, sizeof(diag_path), "%s/diag-%d-poly.jpg", monitor->getStorage()->Path(), id);
|
||||
pg_image->WriteJpeg(diag_path);
|
||||
} else {
|
||||
diag_path[0] = 0;
|
||||
}
|
||||
} // end Zone::Setup
|
||||
|
||||
Zone::~Zone() {
|
||||
|
@ -127,21 +125,22 @@ Zone::~Zone() {
|
|||
|
||||
void Zone::RecordStats( const Event *event ) {
|
||||
static char sql[ZM_SQL_MED_BUFSIZ];
|
||||
snprintf( sql, sizeof(sql), "insert into Stats set MonitorId=%d, ZoneId=%d, EventId=%d, FrameId=%d, PixelDiff=%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, pixel_diff, 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 );
|
||||
db_mutex.lock();
|
||||
if ( mysql_query( &dbconn, sql ) ) {
|
||||
Error( "Can't insert event stats: %s", mysql_error( &dbconn ) );
|
||||
snprintf(sql, sizeof(sql),
|
||||
"INSERT INTO Stats SET MonitorId=%d, ZoneId=%d, EventId=%" PRIu64 ", FrameId=%d, PixelDiff=%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, pixel_diff, 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 stats: %s", mysql_error(&dbconn));
|
||||
}
|
||||
db_mutex.unlock();
|
||||
} // end void Zone::RecordStats( const Event *event )
|
||||
|
||||
bool Zone::CheckOverloadCount() {
|
||||
Info("Overloaded count: %d, Overloaded frames: %d", overload_count, overload_frames);
|
||||
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 );
|
||||
Debug(4, "In overload mode, %d frames of %d remaining", overload_count, overload_frames);
|
||||
overload_count--;
|
||||
return( false );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} // end bool Zone::CheckOverloadCount()
|
||||
|
@ -180,28 +179,27 @@ int Zone::GetExtendAlarmFrames() {
|
|||
} // end int Zone::GetExtendAlarmFrames()
|
||||
|
||||
bool Zone::CheckExtendAlarmCount() {
|
||||
Info( "ExtendAlarm count: %d, ExtendAlarm frames: %d", extend_alarm_count, extend_alarm_frames );
|
||||
Info("ExtendAlarm count: %d, ExtendAlarm frames: %d", extend_alarm_count, extend_alarm_frames);
|
||||
if ( extend_alarm_count ) {
|
||||
Debug( 3, "In extend mode, %d frames of %d remaining", extend_alarm_count, extend_alarm_frames );
|
||||
Debug(3, "In extend mode, %d frames of %d remaining", extend_alarm_count, extend_alarm_frames);
|
||||
extend_alarm_count--;
|
||||
return( true );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} // end bool Zone::CheckExtendAlarmCount
|
||||
|
||||
bool Zone::CheckAlarms( const Image *delta_image ) {
|
||||
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 );
|
||||
Info("In overload mode, %d frames of %d remaining", overload_count, overload_frames);
|
||||
overload_count--;
|
||||
return( false );
|
||||
return false;
|
||||
}
|
||||
|
||||
delete 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();
|
||||
uint8_t* diff_buff = (uint8_t*)diff_image->Buffer();
|
||||
uint8_t* pdiff;
|
||||
|
@ -221,7 +219,7 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
|||
unsigned int hi_x = polygon.HiX();
|
||||
unsigned int hi_y = polygon.HiY();
|
||||
|
||||
Debug( 4, "Checking alarms for zone %d/%s in lines %d -> %d", id, label, lo_y, hi_y );
|
||||
Debug(4, "Checking alarms for zone %d/%s in lines %d -> %d", id, label, lo_y, hi_y);
|
||||
|
||||
/* if(config.cpu_extensions && sseversion >= 20) {
|
||||
sse2_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count);
|
||||
|
@ -230,36 +228,31 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
|||
} */
|
||||
std_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count);
|
||||
|
||||
if ( config.record_diag_images ) {
|
||||
static char diag_path[PATH_MAX] = "";
|
||||
if ( ! diag_path[0] ) {
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/diag-%d-%d.jpg", monitor->getStorage()->Path(), id, 1 );
|
||||
}
|
||||
diff_image->WriteJpeg( diag_path );
|
||||
}
|
||||
if ( config.record_diag_images )
|
||||
diff_image->WriteJpeg(diag_path);
|
||||
|
||||
if ( pixel_diff_count && alarm_pixels )
|
||||
pixel_diff = pixel_diff_count/alarm_pixels;
|
||||
Debug( 5, "Got %d alarmed pixels, need %d -> %d, avg pixel diff %d", alarm_pixels, min_alarm_pixels, max_alarm_pixels, pixel_diff );
|
||||
Debug(5, "Got %d alarmed pixels, need %d -> %d, avg pixel diff %d", alarm_pixels, min_alarm_pixels, max_alarm_pixels, pixel_diff);
|
||||
|
||||
if( alarm_pixels ) {
|
||||
if( min_alarm_pixels && (alarm_pixels < (unsigned int)min_alarm_pixels) ) {
|
||||
if ( alarm_pixels ) {
|
||||
if ( min_alarm_pixels && (alarm_pixels < (unsigned int)min_alarm_pixels) ) {
|
||||
/* Not enough pixels alarmed */
|
||||
return (false);
|
||||
} else if( max_alarm_pixels && (alarm_pixels > (unsigned int)max_alarm_pixels) ) {
|
||||
return false;
|
||||
} else if ( max_alarm_pixels && (alarm_pixels > (unsigned int)max_alarm_pixels) ) {
|
||||
/* Too many pixels alarmed */
|
||||
overload_count = overload_frames;
|
||||
return (false);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
/* No alarmed pixels */
|
||||
return (false);
|
||||
return false;
|
||||
}
|
||||
|
||||
score = (100*alarm_pixels)/polygon.Area();
|
||||
if ( score < 1 )
|
||||
score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */
|
||||
Debug( 5, "Current score is %d", score );
|
||||
Debug(5, "Current score is %d", score);
|
||||
|
||||
if ( check_method >= FILTERED_PIXELS ) {
|
||||
int bx = filter_box.X();
|
||||
|
@ -268,7 +261,7 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
|||
int by1 = by-1;
|
||||
|
||||
|
||||
Debug( 5, "Checking for filtered pixels" );
|
||||
Debug(5, "Checking for filtered pixels");
|
||||
if ( bx > 1 || by > 1 ) {
|
||||
// Now remove any pixels smaller than our filter size
|
||||
unsigned char *cpdiff;
|
||||
|
@ -306,47 +299,42 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
|||
continue;
|
||||
}
|
||||
alarm_filter_pixels++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end if white
|
||||
} // end for x
|
||||
} // end foreach y line
|
||||
} else {
|
||||
alarm_filter_pixels = alarm_pixels;
|
||||
}
|
||||
|
||||
if ( config.record_diag_images ) {
|
||||
static char diag_path[PATH_MAX] = "";
|
||||
if ( !diag_path[0] ) {
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/diag-%d-%d.jpg", monitor->getStorage()->Path(), id, 2 );
|
||||
}
|
||||
diff_image->WriteJpeg( diag_path );
|
||||
}
|
||||
if ( config.record_diag_images )
|
||||
diff_image->WriteJpeg(diag_path);
|
||||
|
||||
Debug( 5, "Got %d filtered pixels, need %d -> %d", alarm_filter_pixels, min_filter_pixels, max_filter_pixels );
|
||||
Debug(5, "Got %d filtered pixels, need %d -> %d", alarm_filter_pixels, min_filter_pixels, max_filter_pixels);
|
||||
|
||||
if( alarm_filter_pixels ) {
|
||||
if( min_filter_pixels && (alarm_filter_pixels < min_filter_pixels) ) {
|
||||
if ( alarm_filter_pixels ) {
|
||||
if ( min_filter_pixels && (alarm_filter_pixels < min_filter_pixels) ) {
|
||||
/* Not enough pixels alarmed */
|
||||
return (false);
|
||||
} else if( max_filter_pixels && (alarm_filter_pixels > max_filter_pixels) ) {
|
||||
return false;
|
||||
} else if ( max_filter_pixels && (alarm_filter_pixels > max_filter_pixels) ) {
|
||||
/* Too many pixels alarmed */
|
||||
overload_count = overload_frames;
|
||||
return (false);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
/* No filtered pixels */
|
||||
return (false);
|
||||
return false;
|
||||
}
|
||||
|
||||
score = (100*alarm_filter_pixels)/(polygon.Area());
|
||||
if ( score < 1 )
|
||||
score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */
|
||||
Debug( 5, "Current score is %d", score );
|
||||
Debug(5, "Current score is %d", score);
|
||||
|
||||
if ( check_method >= BLOBS ) {
|
||||
Debug( 5, "Checking for blob pixels" );
|
||||
Debug(5, "Checking for blob pixels");
|
||||
typedef struct { unsigned char tag; int count; int lo_x; int hi_x; int lo_y; int hi_y; } BlobStats;
|
||||
BlobStats blob_stats[256];
|
||||
memset( blob_stats, 0, sizeof(BlobStats)*256 );
|
||||
memset(blob_stats, 0, sizeof(BlobStats)*256);
|
||||
uint8_t *spdiff;
|
||||
uint8_t last_x, last_y;
|
||||
BlobStats *bsx, *bsy;
|
||||
|
@ -358,32 +346,32 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
|||
pdiff = (uint8_t*)diff_image->Buffer( lo_x, y );
|
||||
for ( int x = lo_x; x <= hi_x; x++, pdiff++ ) {
|
||||
if ( *pdiff == WHITE ) {
|
||||
Debug( 9, "Got white pixel at %d,%d (%p)", x, y, pdiff );
|
||||
Debug(9, "Got white pixel at %d,%d (%p)", x, y, pdiff);
|
||||
//last_x = (x>lo_x)?*(pdiff-1):0;
|
||||
//last_y = (y>lo_y&&x>=last_lo_x&&x<=last_hi_x)?*(pdiff-diff_width):0;
|
||||
|
||||
last_x = 0;
|
||||
if(x > 0) {
|
||||
if((x-1) >= lo_x) {
|
||||
if ( x > 0 ) {
|
||||
if ( (x-1) >= lo_x ) {
|
||||
last_x = *(pdiff-1);
|
||||
}
|
||||
}
|
||||
|
||||
last_y = 0;
|
||||
if(y > 0) {
|
||||
if((y-1) >= lo_y && ranges[(y-1)].lo_x <= x && ranges[(y-1)].hi_x >= x) {
|
||||
if (y > 0 ) {
|
||||
if ( (y-1) >= lo_y && ranges[(y-1)].lo_x <= x && ranges[(y-1)].hi_x >= x ) {
|
||||
last_y = *(pdiff-diff_width);
|
||||
}
|
||||
}
|
||||
|
||||
if ( last_x ) {
|
||||
Debug( 9, "Left neighbour is %d", last_x );
|
||||
Debug(9, "Left neighbour is %d", last_x);
|
||||
bsx = &blob_stats[last_x];
|
||||
if ( last_y ) {
|
||||
Debug( 9, "Top neighbour is %d", last_y );
|
||||
Debug(9, "Top neighbour is %d", last_y);
|
||||
bsy = &blob_stats[last_y];
|
||||
if ( last_x == last_y ) {
|
||||
Debug( 9, "Matching neighbours, setting to %d", last_x );
|
||||
Debug(9, "Matching neighbours, setting to %d", last_x);
|
||||
// Add to the blob from the x side (either side really)
|
||||
*pdiff = last_x;
|
||||
alarm_blob_pixels++;
|
||||
|
@ -395,22 +383,29 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
|||
bsm = bsx->count>=bsy->count?bsx:bsy;
|
||||
bss = bsm==bsx?bsy:bsx;
|
||||
|
||||
Debug( 9, "Different neighbours, setting pixels of %d to %d", bss->tag, bsm->tag );
|
||||
Debug( 9, "Master blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bsm->tag, bsm->count, bsm->lo_x, bsm->hi_x, bsm->lo_y, bsm->hi_y );
|
||||
Debug( 9, "Slave blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bss->tag, bss->count, bss->lo_x, bss->hi_x, bss->lo_y, bss->hi_y );
|
||||
Debug(9,
|
||||
"Different neighbours, setting pixels of %d to %d\n"
|
||||
"Master blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d\n"
|
||||
"Slave blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d\n",
|
||||
bss->tag, bsm->tag,
|
||||
bsm->tag, bsm->count, bsm->lo_x, bsm->hi_x, bsm->lo_y, bsm->hi_y,
|
||||
bss->tag, bss->count, bss->lo_x, bss->hi_x, bss->lo_y, bss->hi_y
|
||||
);
|
||||
// Now change all those pixels to the other setting
|
||||
int changed = 0;
|
||||
for ( int sy = bss->lo_y; sy <= bss->hi_y; sy++) {
|
||||
for ( int sy = bss->lo_y; sy <= bss->hi_y; sy++ ) {
|
||||
int lo_sx = bss->lo_x>=ranges[sy].lo_x?bss->lo_x:ranges[sy].lo_x;
|
||||
int hi_sx = bss->hi_x<=ranges[sy].hi_x?bss->hi_x:ranges[sy].hi_x;
|
||||
|
||||
Debug( 9, "Changing %d, %d->%d", sy, lo_sx, hi_sx );
|
||||
Debug( 9, "Range %d, %d->%d", sy, ranges[sy].lo_x, ranges[sy].hi_x );
|
||||
Debug(9,
|
||||
"Changing %d, %d->%d Range %d->%d",
|
||||
sy, lo_sx, hi_sx, ranges[sy].lo_x, ranges[sy].hi_x
|
||||
);
|
||||
spdiff = diff_buff + ((diff_width * sy) + lo_sx);
|
||||
for ( int sx = lo_sx; sx <= hi_sx; sx++, spdiff++ ) {
|
||||
Debug( 9, "Pixel at %d,%d (%p) is %d", sx, sy, spdiff, *spdiff );
|
||||
Debug(9, "Pixel at %d,%d (%p) is %d", sx, sy, spdiff, *spdiff);
|
||||
if ( *spdiff == bss->tag ) {
|
||||
Debug( 9, "Setting pixel" );
|
||||
Debug(9, "Setting pixel");
|
||||
*spdiff = bsm->tag;
|
||||
changed++;
|
||||
}
|
||||
|
@ -419,10 +414,14 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
|||
*pdiff = bsm->tag;
|
||||
alarm_blob_pixels++;
|
||||
if ( !changed ) {
|
||||
Info( "Master blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bsm->tag, bsm->count, bsm->lo_x, bsm->hi_x, bsm->lo_y, bsm->hi_y );
|
||||
Info( "Slave blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bss->tag, bss->count, bss->lo_x, bss->hi_x, bss->lo_y, bss->hi_y );
|
||||
Error( "No pixels changed, exiting" );
|
||||
exit( -1 );
|
||||
Info(
|
||||
"Master blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d\n"
|
||||
"Slave blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d",
|
||||
bsm->tag, bsm->count, bsm->lo_x, bsm->hi_x, bsm->lo_y, bsm->hi_y,
|
||||
bss->tag, bss->count, bss->lo_x, bss->hi_x, bss->lo_y, bss->hi_y
|
||||
);
|
||||
Error("No pixels changed, exiting");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Merge the slave blob into the master
|
||||
|
@ -436,7 +435,7 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
|||
|
||||
alarm_blobs--;
|
||||
|
||||
Debug( 6, "Merging blob %d with %d at %d,%d, %d current blobs", bss->tag, bsm->tag, x, y, alarm_blobs );
|
||||
Debug(6, "Merging blob %d with %d at %d,%d, %d current blobs", bss->tag, bsm->tag, x, y, alarm_blobs);
|
||||
|
||||
// Clear out the old blob
|
||||
bss->tag = 0;
|
||||
|
@ -447,7 +446,7 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
|||
bss->hi_y = 0;
|
||||
}
|
||||
} else {
|
||||
Debug( 9, "Setting to left neighbour %d", last_x );
|
||||
Debug(9, "Setting to left neighbour %d", last_x);
|
||||
// Add to the blob from the x side
|
||||
*pdiff = last_x;
|
||||
alarm_blob_pixels++;
|
||||
|
@ -457,8 +456,7 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
|||
}
|
||||
} else {
|
||||
if ( last_y ) {
|
||||
Debug( 9, "Top neighbour is %d", last_y );
|
||||
Debug( 9, "Setting to top neighbour %d", last_y );
|
||||
Debug(9, "Top neighbour is %d", last_y);
|
||||
|
||||
// Add to the blob from the y side
|
||||
BlobStats *bsy = &blob_stats[last_y];
|
||||
|
@ -489,7 +487,8 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
|||
alarm_blobs--;
|
||||
alarm_blob_pixels -= bs->count;
|
||||
|
||||
Debug( 6, "Eliminated blob %d, %d pixels (%d,%d - %d,%d), %d current blobs", i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y, alarm_blobs );
|
||||
Debug(6, "Eliminated blob %d, %d pixels (%d,%d - %d,%d), %d current blobs",
|
||||
i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y, alarm_blobs);
|
||||
|
||||
bs->tag = 0;
|
||||
bs->count = 0;
|
||||
|
@ -500,7 +499,7 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
|||
}
|
||||
}
|
||||
if ( !bs->count ) {
|
||||
Debug( 9, "Creating new blob %d", i );
|
||||
Debug(9, "Creating new blob %d", i);
|
||||
*pdiff = i;
|
||||
alarm_blob_pixels++;
|
||||
bs->tag = i;
|
||||
|
@ -509,12 +508,12 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
|||
bs->lo_y = bs->hi_y = y;
|
||||
alarm_blobs++;
|
||||
|
||||
Debug( 6, "Created blob %d at %d,%d, %d current blobs", bs->tag, x, y, alarm_blobs );
|
||||
Debug(6, "Created blob %d at %d,%d, %d current blobs", bs->tag, x, y, alarm_blobs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( i == 0 ) {
|
||||
Warning( "Max blob count reached. Unable to allocate new blobs so terminating. Zone settings may be too sensitive." );
|
||||
Warning("Max blob count reached. Unable to allocate new blobs so terminating. Zone settings may be too sensitive.");
|
||||
x = hi_x+1;
|
||||
y = hi_y+1;
|
||||
}
|
||||
|
@ -523,19 +522,15 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if ( config.record_diag_images ) {
|
||||
static char diag_path[PATH_MAX] = "";
|
||||
if ( !diag_path[0] ) {
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/diag-%d-%d.jpg", monitor->getStorage()->Path(), id, 3 );
|
||||
}
|
||||
diff_image->WriteJpeg( diag_path );
|
||||
}
|
||||
if ( config.record_diag_images )
|
||||
diff_image->WriteJpeg(diag_path);
|
||||
|
||||
if ( !alarm_blobs ) {
|
||||
return( false );
|
||||
return false;
|
||||
}
|
||||
|
||||
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 );
|
||||
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);
|
||||
|
||||
// Now eliminate blobs under the threshold
|
||||
for ( int i = 1; i < WHITE; i++ ) {
|
||||
|
@ -555,7 +550,8 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
|||
alarm_blobs--;
|
||||
alarm_blob_pixels -= bs->count;
|
||||
|
||||
Debug( 6, "Eliminated blob %d, %d pixels (%d,%d - %d,%d), %d current blobs", i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y, alarm_blobs );
|
||||
Debug(6, "Eliminated blob %d, %d pixels (%d,%d - %d,%d), %d current blobs",
|
||||
i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y, alarm_blobs );
|
||||
|
||||
bs->tag = 0;
|
||||
bs->count = 0;
|
||||
|
@ -564,39 +560,37 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
|||
bs->hi_x = 0;
|
||||
bs->hi_y = 0;
|
||||
} else {
|
||||
Debug( 6, "Preserved blob %d, %d pixels (%d,%d - %d,%d), %d current blobs", i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y, alarm_blobs );
|
||||
Debug(6, "Preserved blob %d, %d pixels (%d,%d - %d,%d), %d current blobs",
|
||||
i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y, alarm_blobs );
|
||||
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 ( config.record_diag_images ) {
|
||||
static char diag_path[PATH_MAX] = "";
|
||||
if ( !diag_path[0] ) {
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/diag-%d-%d.jpg", monitor->getStorage()->Path(), id, 4 );
|
||||
}
|
||||
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 );
|
||||
} // end if bs_count
|
||||
} // end for i < WHITE
|
||||
if ( config.record_diag_images )
|
||||
diff_image->WriteJpeg(diag_path);
|
||||
|
||||
if( alarm_blobs ) {
|
||||
if( min_blobs && (alarm_blobs < min_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);
|
||||
|
||||
if ( alarm_blobs ) {
|
||||
if ( min_blobs && (alarm_blobs < min_blobs) ) {
|
||||
/* Not enough pixels alarmed */
|
||||
return (false);
|
||||
} else if(max_blobs && (alarm_blobs > max_blobs) ) {
|
||||
return false;
|
||||
} else if ( max_blobs && (alarm_blobs > max_blobs) ) {
|
||||
/* Too many pixels alarmed */
|
||||
overload_count = overload_frames;
|
||||
return (false);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
/* No blobs */
|
||||
return (false);
|
||||
return false;
|
||||
}
|
||||
|
||||
score = (100*alarm_blob_pixels)/(polygon.Area());
|
||||
if ( score < 1 )
|
||||
score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */
|
||||
Debug( 5, "Current score is %d", score );
|
||||
Debug(5, "Current score is %d", score);
|
||||
|
||||
alarm_lo_x = polygon.HiX()+1;
|
||||
alarm_hi_x = polygon.LoX()-1;
|
||||
|
@ -648,15 +642,15 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
|||
score *= 2;
|
||||
}
|
||||
|
||||
Debug( 5, "Adjusted score is %d", score );
|
||||
Debug(5, "Adjusted score is %d", score);
|
||||
|
||||
// Now outline the changed region
|
||||
if ( score ) {
|
||||
alarm_box = Box( Coord( alarm_lo_x, alarm_lo_y ), Coord( alarm_hi_x, alarm_hi_y ) );
|
||||
alarm_box = Box(Coord(alarm_lo_x, alarm_lo_y), Coord(alarm_hi_x, alarm_hi_y));
|
||||
|
||||
//if ( monitor->followMotion() )
|
||||
if ( true ) {
|
||||
alarm_centre = Coord( alarm_mid_x, alarm_mid_y );
|
||||
alarm_centre = Coord(alarm_mid_x, alarm_mid_y);
|
||||
} else {
|
||||
alarm_centre = alarm_box.Centre();
|
||||
}
|
||||
|
@ -698,9 +692,9 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
|||
}
|
||||
|
||||
if ( monitor->Colours() == ZM_COLOUR_GRAY8 ) {
|
||||
image = diff_image->HighlightEdges( alarm_rgb, ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB, &polygon.Extent() );
|
||||
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() );
|
||||
image = diff_image->HighlightEdges(alarm_rgb, monitor->Colours(), monitor->SubpixelOrder(), &polygon.Extent());
|
||||
}
|
||||
|
||||
// Only need to delete this when 'image' becomes detached and points somewhere else
|
||||
|
@ -710,18 +704,18 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
|||
image = 0;
|
||||
}
|
||||
|
||||
Debug( 1, "%s: Pixel Diff: %d, Alarm Pixels: %d, Filter Pixels: %d, Blob Pixels: %d, Blobs: %d, Score: %d",
|
||||
Label(), pixel_diff, alarm_pixels, alarm_filter_pixels, alarm_blob_pixels, alarm_blobs, score );
|
||||
Debug(1, "%s: Pixel Diff: %d, Alarm Pixels: %d, Filter Pixels: %d, Blob Pixels: %d, Blobs: %d, Score: %d",
|
||||
Label(), pixel_diff, alarm_pixels, alarm_filter_pixels, alarm_blob_pixels, alarm_blobs, score);
|
||||
}
|
||||
return( true );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Zone::ParsePolygonString( const char *poly_string, Polygon &polygon ) {
|
||||
Debug( 3, "Parsing polygon string '%s'", poly_string );
|
||||
bool Zone::ParsePolygonString(const char *poly_string, Polygon &polygon) {
|
||||
Debug(3, "Parsing polygon string '%s'", poly_string);
|
||||
|
||||
char *str_ptr = new char[strlen(poly_string)+1];
|
||||
char *str = str_ptr;
|
||||
strcpy( str, poly_string );
|
||||
strcpy(str, poly_string);
|
||||
|
||||
char *ws;
|
||||
int n_coords = 0;
|
||||
|
@ -731,16 +725,16 @@ bool Zone::ParsePolygonString( const char *poly_string, Polygon &polygon ) {
|
|||
if ( *str == '\0' ) {
|
||||
break;
|
||||
}
|
||||
ws = strchr( str, ' ' );
|
||||
ws = strchr(str, ' ');
|
||||
if ( ws ) {
|
||||
*ws = '\0';
|
||||
}
|
||||
char *cp = strchr( str, ',' );
|
||||
char *cp = strchr(str, ',');
|
||||
if ( !cp ) {
|
||||
Error( "Bogus coordinate %s found in polygon string", str );
|
||||
Error("Bogus coordinate %s found in polygon string", str);
|
||||
delete[] coords;
|
||||
delete[] str_ptr;
|
||||
return( false );
|
||||
return false;
|
||||
} else {
|
||||
*cp = '\0';
|
||||
char *xp = str;
|
||||
|
@ -749,7 +743,7 @@ bool Zone::ParsePolygonString( const char *poly_string, Polygon &polygon ) {
|
|||
int x = atoi(xp);
|
||||
int y = atoi(yp);
|
||||
|
||||
Debug( 3, "Got coordinate %d,%d from polygon string", x, y );
|
||||
Debug(3, "Got coordinate %d,%d from polygon string", x, y);
|
||||
#if 0
|
||||
if ( x < 0 )
|
||||
x = 0;
|
||||
|
@ -767,80 +761,80 @@ bool Zone::ParsePolygonString( const char *poly_string, Polygon &polygon ) {
|
|||
else
|
||||
break;
|
||||
}
|
||||
polygon = Polygon( n_coords, coords );
|
||||
polygon = Polygon(n_coords, coords);
|
||||
|
||||
Debug( 3, "Successfully parsed polygon string" );
|
||||
Debug(3, "Successfully parsed polygon string");
|
||||
//printf( "Area: %d\n", pg.Area() );
|
||||
//printf( "Centre: %d,%d\n", pg.Centre().X(), pg.Centre().Y() );
|
||||
|
||||
delete[] coords;
|
||||
delete[] str_ptr;
|
||||
|
||||
return( true );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Zone::ParseZoneString( const char *zone_string, int &zone_id, int &colour, Polygon &polygon ) {
|
||||
Debug( 3, "Parsing zone string '%s'", zone_string );
|
||||
bool Zone::ParseZoneString(const char *zone_string, int &zone_id, int &colour, Polygon &polygon) {
|
||||
Debug(3, "Parsing zone string '%s'", zone_string);
|
||||
|
||||
char *str_ptr = new char[strlen(zone_string)+1];
|
||||
char *str = str_ptr;
|
||||
strcpy( str, zone_string );
|
||||
strcpy(str, zone_string);
|
||||
|
||||
char *ws = strchr( str, ' ' );
|
||||
char *ws = strchr(str, ' ');
|
||||
if ( !ws ) {
|
||||
Debug( 3, "No initial whitespace found in zone string '%s', finishing", str );
|
||||
Debug(3, "No initial whitespace found in zone string '%s', finishing", str);
|
||||
}
|
||||
zone_id = strtol( str, 0, 10 );
|
||||
Debug( 3, "Got zone %d from zone string", zone_id );
|
||||
zone_id = strtol(str, 0, 10);
|
||||
Debug(3, "Got zone %d from zone string", zone_id);
|
||||
if ( !ws ) {
|
||||
delete[] str_ptr;
|
||||
return( true );
|
||||
return true;
|
||||
}
|
||||
|
||||
*ws = '\0';
|
||||
str = ws+1;
|
||||
|
||||
ws = strchr( str, ' ' );
|
||||
ws = strchr(str, ' ');
|
||||
if ( !ws ) {
|
||||
Debug( 3, "No secondary whitespace found in zone string '%s', finishing", zone_string );
|
||||
Debug(3, "No secondary whitespace found in zone string '%s', finishing", zone_string);
|
||||
}
|
||||
colour = strtol( str, 0, 16 );
|
||||
Debug( 3, "Got colour %06x from zone string", colour );
|
||||
colour = strtol(str, 0, 16);
|
||||
Debug(3, "Got colour %06x from zone string", colour);
|
||||
if ( !ws ) {
|
||||
delete[] str_ptr;
|
||||
return( true );
|
||||
return true;
|
||||
}
|
||||
*ws = '\0';
|
||||
str = ws+1;
|
||||
|
||||
bool result = ParsePolygonString( str, polygon );
|
||||
bool result = ParsePolygonString(str, polygon);
|
||||
|
||||
//printf( "Area: %d\n", pg.Area() );
|
||||
//printf( "Centre: %d,%d\n", pg.Centre().X(), pg.Centre().Y() );
|
||||
|
||||
delete[] str_ptr;
|
||||
|
||||
return( result );
|
||||
return result;
|
||||
}
|
||||
|
||||
int Zone::Load( Monitor *monitor, Zone **&zones ) {
|
||||
int Zone::Load(Monitor *monitor, Zone **&zones) {
|
||||
static char sql[ZM_SQL_MED_BUFSIZ];
|
||||
snprintf( sql, sizeof(sql), "select Id,Name,Type+0,Units,Coords,AlarmRGB,CheckMethod+0,MinPixelThreshold,MaxPixelThreshold,MinAlarmPixels,MaxAlarmPixels,FilterX,FilterY,MinFilterPixels,MaxFilterPixels,MinBlobPixels,MaxBlobPixels,MinBlobs,MaxBlobs,OverloadFrames,ExtendAlarmFrames 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 ) );
|
||||
exit( mysql_errno( &dbconn ) );
|
||||
snprintf(sql, sizeof(sql), "select Id,Name,Type+0,Units,Coords,AlarmRGB,CheckMethod+0,MinPixelThreshold,MaxPixelThreshold,MinAlarmPixels,MaxAlarmPixels,FilterX,FilterY,MinFilterPixels,MaxFilterPixels,MinBlobPixels,MaxBlobPixels,MinBlobs,MaxBlobs,OverloadFrames,ExtendAlarmFrames 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));
|
||||
return 0;
|
||||
}
|
||||
|
||||
MYSQL_RES *result = mysql_store_result( &dbconn );
|
||||
if ( !result ) {
|
||||
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
|
||||
exit( mysql_errno( &dbconn ) );
|
||||
Error("Can't use query result: %s", mysql_error(&dbconn));
|
||||
return 0;
|
||||
}
|
||||
int n_zones = mysql_num_rows( result );
|
||||
Debug( 1, "Got %d zones for monitor %s", n_zones, monitor->Name() );
|
||||
int n_zones = mysql_num_rows(result);
|
||||
Debug(1, "Got %d zones for monitor %s", n_zones, monitor->Name());
|
||||
delete[] 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++ ) {
|
||||
int col = 0;
|
||||
|
||||
int Id = atoi(dbrow[col++]);
|
||||
|
@ -868,17 +862,18 @@ int Zone::Load( Monitor *monitor, Zone **&zones ) {
|
|||
/* HTML colour code is actually BGR in memory, we want RGB */
|
||||
AlarmRGB = rgb_convert(AlarmRGB, ZM_SUBPIX_ORDER_BGR);
|
||||
|
||||
Debug( 5, "Parsing polygon %s", Coords );
|
||||
Debug(5, "Parsing polygon %s", Coords);
|
||||
Polygon polygon;
|
||||
if ( !ParsePolygonString( Coords, polygon ) ) {
|
||||
Error( "Unable to parse polygon string '%s' for zone %d/%s for monitor %s, ignoring", Coords, Id, Name, monitor->Name() );
|
||||
if ( !ParsePolygonString(Coords, polygon) ) {
|
||||
Error("Unable to parse polygon string '%s' for zone %d/%s for monitor %s, ignoring", Coords, Id, Name, monitor->Name());
|
||||
n_zones -= 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( polygon.LoX() < 0 || polygon.HiX() >= (int)monitor->Width()
|
||||
|| polygon.LoY() < 0 || polygon.HiY() >= (int)monitor->Height() ) {
|
||||
Error( "Zone %d/%s for monitor %s extends outside of image dimensions, (%d,%d), (%d,%d), ignoring", Id, Name, monitor->Name(), polygon.LoX(), polygon.LoY(), polygon.HiX(), polygon.HiY() );
|
||||
Error("Zone %d/%s for monitor %s extends outside of image dimensions, (%d,%d), (%d,%d), ignoring",
|
||||
Id, Name, monitor->Name(), polygon.LoX(), polygon.LoY(), polygon.HiX(), polygon.HiY());
|
||||
n_zones -= 1;
|
||||
continue;
|
||||
}
|
||||
|
@ -893,21 +888,17 @@ int Zone::Load( Monitor *monitor, Zone **&zones ) {
|
|||
}
|
||||
|
||||
if ( atoi(dbrow[2]) == Zone::INACTIVE ) {
|
||||
zones[i] = new Zone( monitor, Id, Name, polygon );
|
||||
zones[i] = new Zone(monitor, Id, Name, polygon);
|
||||
} else if ( atoi(dbrow[2]) == Zone::PRIVACY ) {
|
||||
zones[i] = new Zone( monitor, Id, Name, (Zone::ZoneType)Type, polygon );
|
||||
zones[i] = new Zone(monitor, Id, Name, (Zone::ZoneType)Type, polygon);
|
||||
}
|
||||
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, ExtendAlarmFrames );
|
||||
}
|
||||
if ( mysql_errno( &dbconn ) ) {
|
||||
Error( "Can't fetch row: %s", mysql_error( &dbconn ) );
|
||||
exit( mysql_errno( &dbconn ) );
|
||||
}
|
||||
mysql_free_result( result );
|
||||
return( n_zones );
|
||||
}
|
||||
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, ExtendAlarmFrames);
|
||||
} // end foreach row
|
||||
mysql_free_result(result);
|
||||
return n_zones;
|
||||
} // end int Zone::Load(Monitor *monitor, Zone **&zones)
|
||||
|
||||
bool Zone::DumpSettings( char *output, bool /*verbose*/ ) {
|
||||
bool Zone::DumpSettings(char *output, bool /*verbose*/) {
|
||||
output[0] = 0;
|
||||
|
||||
sprintf( output+strlen(output), " Id : %d\n", id );
|
||||
|
@ -951,7 +942,7 @@ void Zone::std_alarmedpixels(Image* pdiff_image, const Image* ppoly_image, unsig
|
|||
unsigned int lo_y;
|
||||
unsigned int hi_y;
|
||||
|
||||
if(max_pixel_threshold)
|
||||
if ( max_pixel_threshold )
|
||||
calc_max_pixel_threshold = max_pixel_threshold;
|
||||
|
||||
lo_y = polygon.LoY();
|
||||
|
@ -960,9 +951,9 @@ void Zone::std_alarmedpixels(Image* pdiff_image, const Image* ppoly_image, unsig
|
|||
unsigned int lo_x = ranges[y].lo_x;
|
||||
unsigned int hi_x = ranges[y].hi_x;
|
||||
|
||||
Debug( 7, "Checking line %d from %d -> %d", y, lo_x, hi_x );
|
||||
uint8_t *pdiff = (uint8_t*)pdiff_image->Buffer( lo_x, y );
|
||||
const uint8_t *ppoly = ppoly_image->Buffer( lo_x, y );
|
||||
Debug(7, "Checking line %d from %d -> %d", y, lo_x, hi_x);
|
||||
uint8_t *pdiff = (uint8_t*)pdiff_image->Buffer(lo_x, y);
|
||||
const uint8_t *ppoly = ppoly_image->Buffer(lo_x, y);
|
||||
|
||||
for ( unsigned int x = lo_x; x <= hi_x; x++, pdiff++, ppoly++ ) {
|
||||
if ( *ppoly && (*pdiff > min_pixel_threshold) && (*pdiff <= calc_max_pixel_threshold) ) {
|
||||
|
|
Loading…
Reference in New Issue