New files created as a result of breaking out the classes to support
the use of remote cameras. git-svn-id: http://svn.zoneminder.com/svn/zm/trunk@414 e3e1d417-86f3-4887-817a-d78f3d33393fpull/27/merge
parent
e0f7d80844
commit
a6f405b4ac
|
@ -0,0 +1,44 @@
|
|||
//
|
||||
// ZoneMinder MySQL Implementation, $Date$, $Revision$
|
||||
// Copyright (C) 2003 Philip Coombes
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "zm_db.h"
|
||||
|
||||
MYSQL dbconn;
|
||||
|
||||
void zmDbConnect( const char *user, const char*pass )
|
||||
{
|
||||
if ( !mysql_init( &dbconn ) )
|
||||
{
|
||||
fprintf( stderr, "Can't initialise structure: %s\n", mysql_error( &dbconn ) );
|
||||
exit( mysql_errno( &dbconn ) );
|
||||
}
|
||||
if ( !mysql_connect( &dbconn, ZM_DB_SERVER, user, pass ) )
|
||||
{
|
||||
fprintf( stderr, "Can't connect to server: %s\n", mysql_error( &dbconn ) );
|
||||
exit( mysql_errno( &dbconn ) );
|
||||
}
|
||||
if ( mysql_select_db( &dbconn, ZM_DB_NAME ) )
|
||||
{
|
||||
fprintf( stderr, "Can't select database: %s\n", mysql_error( &dbconn ) );
|
||||
exit( mysql_errno( &dbconn ) );
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
//
|
||||
// ZoneMinder Core Interfaces, $Date$, $Revision$
|
||||
// Copyright (C) 2003 Philip Coombes
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
//
|
||||
|
||||
#ifndef ZM_DB_H
|
||||
#define ZM_DB_H
|
||||
|
||||
#include <mysql/mysql.h>
|
||||
|
||||
#include "zm.h"
|
||||
|
||||
extern MYSQL dbconn;
|
||||
|
||||
void zmDbConnect( const char *user, const char*pass );
|
||||
|
||||
#endif // ZM_DB_H
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,328 @@
|
|||
/*
|
||||
* ZoneMinder JPEG memory encoding/decoding, $Date$, $Revision$
|
||||
* Copyright (C) 2003 Philip Coombes
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jerror.h"
|
||||
|
||||
/* Expanded data destination object for memory */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_destination_mgr pub; /* public fields */
|
||||
|
||||
JOCTET *outbuffer; /* target buffer */
|
||||
int *outbuffer_size;
|
||||
JOCTET *buffer; /* start of buffer */
|
||||
} mem_destination_mgr;
|
||||
|
||||
typedef mem_destination_mgr * mem_dest_ptr;
|
||||
|
||||
#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */
|
||||
|
||||
|
||||
/*
|
||||
* Initialize destination --- called by jpeg_start_compress
|
||||
* before any data is actually written.
|
||||
*/
|
||||
|
||||
static void init_destination (j_compress_ptr cinfo)
|
||||
{
|
||||
mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
|
||||
|
||||
/* Allocate the output buffer --- it will be released when done with image */
|
||||
dest->buffer = (JOCTET *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
OUTPUT_BUF_SIZE * SIZEOF(JOCTET));
|
||||
|
||||
dest->pub.next_output_byte = dest->buffer;
|
||||
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
|
||||
|
||||
*(dest->outbuffer_size) = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Empty the output buffer --- called whenever buffer fills up.
|
||||
*
|
||||
* In typical applications, this should write the entire output buffer
|
||||
* (ignoring the current state of next_output_byte & free_in_buffer),
|
||||
* reset the pointer & count to the start of the buffer, and return TRUE
|
||||
* indicating that the buffer has been dumped.
|
||||
*
|
||||
* In applications that need to be able to suspend compression due to output
|
||||
* overrun, a FALSE return indicates that the buffer cannot be emptied now.
|
||||
* In this situation, the compressor will return to its caller (possibly with
|
||||
* an indication that it has not accepted all the supplied scanlines). The
|
||||
* application should resume compression after it has made more room in the
|
||||
* output buffer. Note that there are substantial restrictions on the use of
|
||||
* suspension --- see the documentation.
|
||||
*
|
||||
* When suspending, the compressor will back up to a convenient restart point
|
||||
* (typically the start of the current MCU). next_output_byte & free_in_buffer
|
||||
* indicate where the restart point will be if the current call returns FALSE.
|
||||
* Data beyond this point will be regenerated after resumption, so do not
|
||||
* write it out when emptying the buffer externally.
|
||||
*/
|
||||
|
||||
static boolean empty_output_buffer (j_compress_ptr cinfo)
|
||||
{
|
||||
mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
|
||||
|
||||
memcpy( dest->outbuffer+*(dest->outbuffer_size), dest->buffer, OUTPUT_BUF_SIZE );
|
||||
*(dest->outbuffer_size) += OUTPUT_BUF_SIZE;
|
||||
|
||||
dest->pub.next_output_byte = dest->buffer;
|
||||
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Terminate destination --- called by jpeg_finish_compress
|
||||
* after all data has been written. Usually needs to flush buffer.
|
||||
*
|
||||
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
|
||||
* application must deal with any cleanup that should happen even
|
||||
* for error exit.
|
||||
*/
|
||||
|
||||
static void term_destination (j_compress_ptr cinfo)
|
||||
{
|
||||
mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
|
||||
size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
|
||||
|
||||
if (datacount > 0) {
|
||||
memcpy( dest->outbuffer+*(dest->outbuffer_size), dest->buffer, datacount );
|
||||
*(dest->outbuffer_size) += datacount;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Prepare for output to a stdio stream.
|
||||
* The caller must have already opened the stream, and is responsible
|
||||
* for closing it after finishing compression.
|
||||
*/
|
||||
|
||||
void jpeg_mem_dest (j_compress_ptr cinfo, JOCTET *outbuffer, int *outbuffer_size )
|
||||
{
|
||||
mem_dest_ptr dest;
|
||||
|
||||
/* The destination object is made permanent so that multiple JPEG images
|
||||
* can be written to the same file without re-executing jpeg_stdio_dest.
|
||||
* This makes it dangerous to use this manager and a different destination
|
||||
* manager serially with the same JPEG object, because their private object
|
||||
* sizes may be different. Caveat programmer.
|
||||
*/
|
||||
if (cinfo->dest == NULL) { /* first time for this JPEG object? */
|
||||
cinfo->dest = (struct jpeg_destination_mgr *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
SIZEOF(mem_destination_mgr));
|
||||
}
|
||||
|
||||
dest = (mem_dest_ptr) cinfo->dest;
|
||||
dest->pub.init_destination = init_destination;
|
||||
dest->pub.empty_output_buffer = empty_output_buffer;
|
||||
dest->pub.term_destination = term_destination;
|
||||
dest->outbuffer = outbuffer;
|
||||
dest->outbuffer_size = outbuffer_size;
|
||||
}
|
||||
|
||||
/* Expanded data source object for memory input */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_source_mgr pub; /* public fields */
|
||||
|
||||
JOCTET * inbuffer; /* source stream */
|
||||
int inbuffer_size;
|
||||
|
||||
JOCTET * buffer; /* start of buffer */
|
||||
boolean start_of_data; /* have we gotten any data yet? */
|
||||
} mem_source_mgr;
|
||||
|
||||
typedef mem_source_mgr * mem_src_ptr;
|
||||
|
||||
#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */
|
||||
|
||||
|
||||
/*
|
||||
* Initialize source --- called by jpeg_read_header
|
||||
* before any data is actually read.
|
||||
*/
|
||||
|
||||
static void init_source (j_decompress_ptr cinfo)
|
||||
{
|
||||
mem_src_ptr src = (mem_src_ptr) cinfo->src;
|
||||
|
||||
/* We reset the empty-input-file flag for each image,
|
||||
* but we don't clear the input buffer.
|
||||
* This is correct behavior for reading a series of images from one source.
|
||||
*/
|
||||
src->start_of_data = TRUE;
|
||||
src->pub.bytes_in_buffer = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fill the input buffer --- called whenever buffer is emptied.
|
||||
*
|
||||
* In typical applications, this should read fresh data into the buffer
|
||||
* (ignoring the current state of next_input_byte & bytes_in_buffer),
|
||||
* reset the pointer & count to the start of the buffer, and return TRUE
|
||||
* indicating that the buffer has been reloaded. It is not necessary to
|
||||
* fill the buffer entirely, only to obtain at least one more byte.
|
||||
*
|
||||
* There is no such thing as an EOF return. If the end of the file has been
|
||||
* reached, the routine has a choice of ERREXIT() or inserting fake data into
|
||||
* the buffer. In most cases, generating a warning message and inserting a
|
||||
* fake EOI marker is the best course of action --- this will allow the
|
||||
* decompressor to output however much of the image is there. However,
|
||||
* the resulting error message is misleading if the real problem is an empty
|
||||
* input file, so we handle that case specially.
|
||||
*
|
||||
* In applications that need to be able to suspend compression due to input
|
||||
* not being available yet, a FALSE return indicates that no more data can be
|
||||
* obtained right now, but more may be forthcoming later. In this situation,
|
||||
* the decompressor will return to its caller (with an indication of the
|
||||
* number of scanlines it has read, if any). The application should resume
|
||||
* decompression after it has loaded more data into the input buffer. Note
|
||||
* that there are substantial restrictions on the use of suspension --- see
|
||||
* the documentation.
|
||||
*
|
||||
* When suspending, the decompressor will back up to a convenient restart point
|
||||
* (typically the start of the current MCU). next_input_byte & bytes_in_buffer
|
||||
* indicate where the restart point will be if the current call returns FALSE.
|
||||
* Data beyond this point must be rescanned after resumption, so move it to
|
||||
* the front of the buffer rather than discarding it.
|
||||
*/
|
||||
|
||||
static boolean fill_input_buffer (j_decompress_ptr cinfo)
|
||||
{
|
||||
mem_src_ptr src = (mem_src_ptr) cinfo->src;
|
||||
size_t nbytes;
|
||||
|
||||
memcpy( src->buffer, src->inbuffer, src->inbuffer_size );
|
||||
nbytes = src->inbuffer_size;
|
||||
|
||||
if (nbytes <= 0) {
|
||||
if (src->start_of_data) /* Treat empty input file as fatal error */
|
||||
ERREXIT(cinfo, JERR_INPUT_EMPTY);
|
||||
WARNMS(cinfo, JWRN_JPEG_EOF);
|
||||
/* Insert a fake EOI marker */
|
||||
src->buffer[0] = (JOCTET) 0xFF;
|
||||
src->buffer[1] = (JOCTET) JPEG_EOI;
|
||||
nbytes = 2;
|
||||
}
|
||||
|
||||
src->pub.next_input_byte = src->buffer;
|
||||
src->pub.bytes_in_buffer = nbytes;
|
||||
src->start_of_data = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Skip data --- used to skip over a potentially large amount of
|
||||
* uninteresting data (such as an APPn marker).
|
||||
*
|
||||
* Writers of suspendable-input applications must note that skip_input_data
|
||||
* is not granted the right to give a suspension return. If the skip extends
|
||||
* beyond the data currently in the buffer, the buffer can be marked empty so
|
||||
* that the next read will cause a fill_input_buffer call that can suspend.
|
||||
* Arranging for additional bytes to be discarded before reloading the input
|
||||
* buffer is the application writer's problem.
|
||||
*/
|
||||
|
||||
static void skip_input_data (j_decompress_ptr cinfo, long num_bytes)
|
||||
{
|
||||
mem_src_ptr src = (mem_src_ptr) cinfo->src;
|
||||
|
||||
/* Just a dumb implementation for now. Could use fseek() except
|
||||
* it doesn't work on pipes. Not clear that being smart is worth
|
||||
* any trouble anyway --- large skips are infrequent.
|
||||
*/
|
||||
if (num_bytes > 0) {
|
||||
while (num_bytes > (long) src->pub.bytes_in_buffer) {
|
||||
num_bytes -= (long) src->pub.bytes_in_buffer;
|
||||
(void) fill_input_buffer(cinfo);
|
||||
/* note we assume that fill_input_buffer will never return FALSE,
|
||||
* so suspension need not be handled.
|
||||
*/
|
||||
}
|
||||
src->pub.next_input_byte += (size_t) num_bytes;
|
||||
src->pub.bytes_in_buffer -= (size_t) num_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Terminate source --- called by jpeg_finish_decompress
|
||||
* after all data has been read. Often a no-op.
|
||||
*
|
||||
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
|
||||
* application must deal with any cleanup that should happen even
|
||||
* for error exit.
|
||||
*/
|
||||
|
||||
static void term_source (j_decompress_ptr cinfo)
|
||||
{
|
||||
/* no work necessary here */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Prepare for input from a memory stream.
|
||||
* The caller must have already opened the stream, and is responsible
|
||||
* for closing it after finishing decompression.
|
||||
*/
|
||||
|
||||
void jpeg_mem_src (j_decompress_ptr cinfo, JOCTET *inbuffer, int inbuffer_size )
|
||||
{
|
||||
mem_src_ptr src;
|
||||
|
||||
/* The source object and input buffer are made permanent so that a series
|
||||
* of JPEG images can be read from the same file by calling jpeg_mem_src
|
||||
* only before the first one. (If we discarded the buffer at the end of
|
||||
* one image, we'd likely lose the start of the next one.)
|
||||
* This makes it unsafe to use this manager and a different source
|
||||
* manager serially with the same JPEG object. Caveat programmer.
|
||||
*/
|
||||
if (cinfo->src == NULL) { /* first time for this JPEG object? */
|
||||
cinfo->src = (struct jpeg_source_mgr *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
SIZEOF(mem_source_mgr));
|
||||
src = (mem_src_ptr) cinfo->src;
|
||||
src->buffer = (JOCTET *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
inbuffer_size * SIZEOF(JOCTET));
|
||||
}
|
||||
|
||||
src = (mem_src_ptr) cinfo->src;
|
||||
src->pub.init_source = init_source;
|
||||
src->pub.fill_input_buffer = fill_input_buffer;
|
||||
src->pub.skip_input_data = skip_input_data;
|
||||
src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
|
||||
src->pub.term_source = term_source;
|
||||
src->inbuffer = inbuffer;
|
||||
src->inbuffer_size = inbuffer_size;
|
||||
src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
|
||||
src->pub.next_input_byte = NULL; /* until buffer loaded */
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
//
|
||||
// ZoneMinder RGB Interface, $Date$, $Revision$
|
||||
// Copyright (C) 2003 Philip Coombes
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
//
|
||||
|
||||
#ifndef ZM_RGB_H
|
||||
#define ZM_RGB_H
|
||||
|
||||
typedef unsigned int Rgb; // RGB colour type
|
||||
|
||||
#define RED(byte) (*(byte))
|
||||
#define GREEN(byte) (*(byte+1))
|
||||
#define BLUE(byte) (*(byte+2))
|
||||
|
||||
#define WHITE 0xff
|
||||
#define WHITE_R 0xff
|
||||
#define WHITE_G 0xff
|
||||
#define WHITE_B 0xff
|
||||
|
||||
#define BLACK 0x00
|
||||
#define BLACK_R 0x00
|
||||
#define BLACK_G 0x00
|
||||
#define BLACK_B 0x00
|
||||
|
||||
#define RGB_WHITE (0x00ffffff)
|
||||
#define RGB_BLACK (0x00000000)
|
||||
#define RGB_RED (0x00ff0000)
|
||||
#define RGB_GREEN (0x0000ff00)
|
||||
#define RGB_BLUE (0x000000ff)
|
||||
|
||||
#define RGB_VAL(v,c) (((v)>>(16-((c)*8)))&0xff)
|
||||
#define RGB_RED_VAL(v) (((v)>>16)&0xff)
|
||||
#define RGB_GREEN_VAL(v) (((v)>>8)&0xff)
|
||||
#define RGB_BLUE_VAL(v) ((v)&0xff)
|
||||
|
||||
#endif // ZM_RGB_H
|
|
@ -0,0 +1,502 @@
|
|||
//
|
||||
// ZoneMinder Zone Class Implementation, $Date$, $Revision$
|
||||
// Copyright (C) 2003 Philip Coombes
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
//
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_db.h"
|
||||
#include "zm_zone.h"
|
||||
#include "zm_image.h"
|
||||
#include "zm_monitor.h"
|
||||
|
||||
void Zone::Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Box &p_limits, const Rgb p_alarm_rgb, int p_alarm_threshold, int p_min_alarm_pixels, int p_max_alarm_pixels, const Coord &p_filter_box, int p_min_filter_pixels, int p_max_filter_pixels, int p_min_blob_pixels, int p_max_blob_pixels, int p_min_blobs, int p_max_blobs )
|
||||
{
|
||||
monitor = p_monitor;
|
||||
|
||||
id = p_id;
|
||||
label = new char[strlen(p_label)+1];
|
||||
strcpy( label, p_label );
|
||||
type = p_type;
|
||||
limits = p_limits;
|
||||
alarm_rgb = p_alarm_rgb;
|
||||
alarm_threshold = p_alarm_threshold;
|
||||
min_alarm_pixels = p_min_alarm_pixels;
|
||||
max_alarm_pixels = p_max_alarm_pixels;
|
||||
filter_box = p_filter_box;
|
||||
min_filter_pixels = p_min_filter_pixels;
|
||||
max_filter_pixels = p_max_filter_pixels;
|
||||
min_blob_pixels = p_min_blob_pixels;
|
||||
max_blob_pixels = p_max_blob_pixels;
|
||||
min_blobs = p_min_blobs;
|
||||
max_blobs = p_max_blobs;
|
||||
|
||||
Info(( "Initialised zone %d/%s - %d - %dx%d - Rgb:%06x, AT:%d, MnAP:%d, MxAP:%d, FB:%dx%d, MnFP:%d, MxFP:%d, MnBS:%d, MxBS:%d, MnB:%d, MxB:%d", id, label, type, limits.Width(), limits.Height(), alarm_rgb, alarm_threshold, min_alarm_pixels, max_alarm_pixels, filter_box.X(), filter_box.Y(), min_filter_pixels, max_filter_pixels, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs ));
|
||||
|
||||
alarmed = false;
|
||||
alarm_pixels = 0;
|
||||
alarm_filter_pixels = 0;
|
||||
alarm_blob_pixels = 0;
|
||||
alarm_blobs = 0;
|
||||
image = 0;
|
||||
score = 0;
|
||||
}
|
||||
|
||||
Zone::~Zone()
|
||||
{
|
||||
delete[] label;
|
||||
delete image;
|
||||
}
|
||||
|
||||
void Zone::RecordStats( const Event *event )
|
||||
{
|
||||
static char sql[256];
|
||||
sprintf( sql, "insert into Stats set MonitorId=%d, ZoneId=%d, EventId=%d, FrameId=%d, AlarmPixels=%d, FilterPixels=%d, BlobPixels=%d, Blobs=%d, MinBlobSize=%d, MaxBlobSize=%d, MinX=%d, MinY=%d, MaxX=%d, MaxY=%d, Score=%d", monitor->Id(), id, event->Id(), event->Frames()+1, alarm_pixels, alarm_filter_pixels, alarm_blob_pixels, alarm_blobs, min_blob_size, max_blob_size, alarm_box.LoX(), alarm_box.LoY(), alarm_box.HiX(), alarm_box.HiY(), score );
|
||||
if ( mysql_query( &dbconn, sql ) )
|
||||
{
|
||||
Error(( "Can't insert event: %s", mysql_error( &dbconn ) ));
|
||||
exit( mysql_errno( &dbconn ) );
|
||||
}
|
||||
}
|
||||
|
||||
bool Zone::CheckAlarms( const Image *delta_image )
|
||||
{
|
||||
bool alarm = false;
|
||||
unsigned int score = 0;
|
||||
|
||||
ResetStats();
|
||||
|
||||
delete image;
|
||||
Image *diff_image = image = new Image( *delta_image );
|
||||
|
||||
int alarm_pixels = 0;
|
||||
|
||||
int lo_x = limits.Lo().X();
|
||||
int lo_y = limits.Lo().Y();
|
||||
int hi_x = limits.Hi().X();
|
||||
int hi_y = limits.Hi().Y();
|
||||
for ( int y = lo_y; y <= hi_y; y++ )
|
||||
{
|
||||
unsigned char *pdiff = diff_image->Buffer( lo_x, y );
|
||||
for ( int x = lo_x; x <= hi_x; x++, pdiff++ )
|
||||
{
|
||||
if ( *pdiff > alarm_threshold )
|
||||
{
|
||||
*pdiff = WHITE;
|
||||
alarm_pixels++;
|
||||
continue;
|
||||
}
|
||||
*pdiff = BLACK;
|
||||
}
|
||||
}
|
||||
|
||||
//diff_image->WriteJpeg( "diff1.jpg" );
|
||||
|
||||
if ( !alarm_pixels ) return( false );
|
||||
if ( min_alarm_pixels && alarm_pixels < min_alarm_pixels ) return( false );
|
||||
if ( max_alarm_pixels && alarm_pixels > max_alarm_pixels ) return( false );
|
||||
|
||||
int filter_pixels = 0;
|
||||
|
||||
int bx = filter_box.X();
|
||||
int by = filter_box.Y();
|
||||
int bx1 = bx-1;
|
||||
int by1 = by-1;
|
||||
|
||||
// Now eliminate all pixels that don't participate in a blob
|
||||
for ( int y = lo_y; y <= hi_y; y++ )
|
||||
{
|
||||
unsigned char *pdiff = diff_image->Buffer( lo_x, y );
|
||||
|
||||
for ( int x = lo_x; x <= hi_x; x++, pdiff++ )
|
||||
{
|
||||
if ( *pdiff == WHITE )
|
||||
{
|
||||
// Check participation in an X blob
|
||||
int ldx = (x>=(lo_x+bx1))?-bx1:lo_x-x;
|
||||
int hdx = (x<=(hi_x-bx1))?0:((hi_x-x)-bx1);
|
||||
int ldy = (y>=(lo_y+by1))?-by1:lo_y-y;
|
||||
int hdy = (y<=(hi_y-by1))?0:((hi_y-y)-by1);
|
||||
bool blob = false;
|
||||
for ( int dy = ldy; !blob && dy <= hdy; dy++ )
|
||||
{
|
||||
for ( int dx = ldx; !blob && dx <= hdx; dx++ )
|
||||
{
|
||||
blob = true;
|
||||
for ( int dy2 = 0; blob && dy2 < by; dy2++ )
|
||||
{
|
||||
for ( int dx2 = 0; blob && dx2 < bx; dx2++ )
|
||||
{
|
||||
unsigned char *cpdiff = diff_image->Buffer( x+dx+dx2, y+dy+dy2 );
|
||||
|
||||
if ( !*cpdiff )
|
||||
{
|
||||
blob = false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( !blob )
|
||||
{
|
||||
*pdiff = BLACK;
|
||||
continue;
|
||||
}
|
||||
filter_pixels++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//diff_image->WriteJpeg( "diff2.jpg" );
|
||||
|
||||
if ( !filter_pixels ) return( false );
|
||||
if ( min_filter_pixels && filter_pixels < min_filter_pixels ) return( false );
|
||||
if ( max_filter_pixels && filter_pixels > max_filter_pixels ) return( false );
|
||||
|
||||
int blobs = 0;
|
||||
|
||||
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 );
|
||||
for ( int y = lo_y; y <= hi_y; y++ )
|
||||
{
|
||||
unsigned char *pdiff = diff_image->Buffer( lo_x, y );
|
||||
for ( int x = lo_x; x <= hi_x; x++, pdiff++ )
|
||||
{
|
||||
if ( *pdiff == WHITE )
|
||||
{
|
||||
//printf( "Got white pixel at %d,%d (%x)\n", x, y, pdiff );
|
||||
int lx = x>lo_x?*(pdiff-1):0;
|
||||
int ly = y>lo_y?*(pdiff-diff_image->Width()):0;
|
||||
|
||||
if ( lx )
|
||||
{
|
||||
//printf( "Left neighbour is %d\n", lx );
|
||||
BlobStats *bsx = &blob_stats[lx];
|
||||
|
||||
if ( ly )
|
||||
{
|
||||
//printf( "Top neighbour is %d\n", ly );
|
||||
BlobStats *bsy = &blob_stats[ly];
|
||||
|
||||
if ( lx == ly )
|
||||
{
|
||||
//printf( "Matching neighbours, setting to %d\n", lx );
|
||||
// Add to the blob from the x side (either side really)
|
||||
*pdiff = lx;
|
||||
bsx->count++;
|
||||
//if ( x < bsx->lo_x ) bsx->lo_x = x;
|
||||
//if ( y < bsx->lo_y ) bsx->lo_y = y;
|
||||
if ( x > bsx->hi_x ) bsx->hi_x = x;
|
||||
if ( y > bsx->hi_y ) bsx->hi_y = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Amortise blobs
|
||||
BlobStats *bsm = bsx->count>=bsy->count?bsx:bsy;
|
||||
BlobStats *bss = bsm==bsx?bsy:bsx;
|
||||
|
||||
//printf( "Different neighbours, setting pixels of %d to %d\n", bss->tag, bsm->tag );
|
||||
// Now change all those pixels to the other setting
|
||||
for ( int sy = bss->lo_y; sy <= bss->hi_y; sy++ )
|
||||
{
|
||||
unsigned char *spdiff = diff_image->Buffer( bss->lo_x, sy );
|
||||
for ( int sx = bss->lo_x; sx <= bss->hi_x; sx++, spdiff++ )
|
||||
{
|
||||
//printf( "Pixel at %d,%d (%x) is %d", sx, sy, spdiff, *spdiff );
|
||||
if ( *spdiff == bss->tag )
|
||||
{
|
||||
//printf( ", setting" );
|
||||
*spdiff = bsm->tag;
|
||||
}
|
||||
//printf( "\n" );
|
||||
}
|
||||
}
|
||||
*pdiff = bsm->tag;
|
||||
|
||||
// Merge the slave blob into the master
|
||||
bsm->count += bss->count+1;
|
||||
if ( x > bsm->hi_x ) bsm->hi_x = x;
|
||||
if ( y > bsm->hi_y ) bsm->hi_y = y;
|
||||
if ( bss->lo_x < bsm->lo_x ) bsm->lo_x = bss->lo_x;
|
||||
if ( bss->lo_y < bsm->lo_y ) bsm->lo_y = bss->lo_y;
|
||||
if ( bss->hi_x > bsm->hi_x ) bsm->hi_x = bss->hi_x;
|
||||
if ( bss->hi_y > bsm->hi_y ) bsm->hi_y = bss->hi_y;
|
||||
|
||||
// Clear out the old blob
|
||||
bss->tag = 0;
|
||||
bss->count = 0;
|
||||
bss->lo_x = 0;
|
||||
bss->lo_y = 0;
|
||||
bss->hi_x = 0;
|
||||
bss->hi_y = 0;
|
||||
|
||||
blobs--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf( "Setting to left neighbour %d\n", lx );
|
||||
// Add to the blob from the x side
|
||||
*pdiff = lx;
|
||||
bsx->count++;
|
||||
//if ( x < bsx->lo_x ) bsx->lo_x = x;
|
||||
//if ( y < bsx->lo_y ) bsx->lo_y = y;
|
||||
if ( x > bsx->hi_x ) bsx->hi_x = x;
|
||||
if ( y > bsx->hi_y ) bsx->hi_y = y;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ly )
|
||||
{
|
||||
//printf( "Setting to top neighbour %d\n", ly );
|
||||
|
||||
// Add to the blob from the y side
|
||||
BlobStats *bsy = &blob_stats[ly];
|
||||
|
||||
*pdiff = ly;
|
||||
bsy->count++;
|
||||
//if ( x < bsy->lo_x ) bsy->lo_x = x;
|
||||
//if ( y < bsy->lo_y ) bsy->lo_y = y;
|
||||
if ( x > bsy->hi_x ) bsy->hi_x = x;
|
||||
if ( y > bsy->hi_y ) bsy->hi_y = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a new blob
|
||||
for ( int i = 1; i < WHITE; i++ )
|
||||
{
|
||||
BlobStats *bs = &blob_stats[i];
|
||||
if ( !bs->count )
|
||||
{
|
||||
//printf( "Creating new blob %d\n", i );
|
||||
*pdiff = i;
|
||||
bs->tag = i;
|
||||
bs->count++;
|
||||
bs->lo_x = bs->hi_x = x;
|
||||
bs->lo_y = bs->hi_y = y;
|
||||
blobs++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//diff_image->WriteJpeg( "diff3.jpg" );
|
||||
|
||||
if ( !blobs ) return( false );
|
||||
int blob_pixels = filter_pixels;
|
||||
|
||||
int min_blob_size = 0;
|
||||
int max_blob_size = 0;
|
||||
// Now eliminate blobs under the alarm_threshold
|
||||
for ( int i = 1; i < WHITE; i++ )
|
||||
{
|
||||
BlobStats *bs = &blob_stats[i];
|
||||
if ( bs->count && ((min_blob_pixels && bs->count < min_blob_pixels) || (max_blob_pixels && bs->count > max_blob_pixels)) )
|
||||
{
|
||||
//Info(( "Eliminating blob %d, %d pixels (%d,%d - %d,%d)\n", i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y ));
|
||||
for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ )
|
||||
{
|
||||
unsigned char *spdiff = diff_image->Buffer( bs->lo_x, sy );
|
||||
for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ )
|
||||
{
|
||||
if ( *spdiff == bs->tag )
|
||||
{
|
||||
*spdiff = BLACK;
|
||||
}
|
||||
}
|
||||
}
|
||||
blobs--;
|
||||
blob_pixels -= bs->count;
|
||||
|
||||
bs->tag = 0;
|
||||
bs->count = 0;
|
||||
bs->lo_x = 0;
|
||||
bs->lo_y = 0;
|
||||
bs->hi_x = 0;
|
||||
bs->hi_y = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( bs->count )
|
||||
{
|
||||
if ( !min_blob_size || bs->count < min_blob_size ) min_blob_size = bs->count;
|
||||
if ( !max_blob_size || bs->count > max_blob_size ) max_blob_size = bs->count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !blobs ) return( false );
|
||||
if ( min_blobs && blobs < min_blobs ) return( false );
|
||||
if ( max_blobs && blobs > max_blobs ) return( false );
|
||||
|
||||
int alarm_lo_x = hi_x+1;
|
||||
int alarm_hi_x = lo_x-1;
|
||||
int alarm_lo_y = hi_y+1;
|
||||
int alarm_hi_y = lo_y-1;
|
||||
for ( int i = 1; i < WHITE; i++ )
|
||||
{
|
||||
BlobStats *bs = &blob_stats[i];
|
||||
if ( bs->count )
|
||||
{
|
||||
if ( alarm_lo_x > bs->lo_x ) alarm_lo_x = bs->lo_x;
|
||||
if ( alarm_lo_y > bs->lo_y ) alarm_lo_y = bs->lo_y;
|
||||
if ( alarm_hi_x < bs->hi_x ) alarm_hi_x = bs->hi_x;
|
||||
if ( alarm_hi_y < bs->hi_y ) alarm_hi_y = bs->hi_y;
|
||||
}
|
||||
}
|
||||
|
||||
alarm_pixels = alarm_pixels;
|
||||
alarm_filter_pixels = filter_pixels;
|
||||
alarm_blob_pixels = blob_pixels;
|
||||
alarm_blobs = blobs;
|
||||
min_blob_size = min_blob_size;
|
||||
max_blob_size = max_blob_size;
|
||||
alarm_box = Box( Coord( alarm_lo_x, alarm_lo_y ), Coord( alarm_hi_x, alarm_hi_y ) );
|
||||
score = ((100*blob_pixels)/blobs)/(limits.Size().X()*limits.Size().Y());
|
||||
if ( type == INCLUSIVE )
|
||||
{
|
||||
score /= 2;
|
||||
}
|
||||
else if ( type == EXCLUSIVE )
|
||||
{
|
||||
score *= 2;
|
||||
}
|
||||
score = score;
|
||||
|
||||
// Now outline the changed region
|
||||
if ( alarm_blobs )
|
||||
{
|
||||
alarm = true;
|
||||
Image *high_image = image = diff_image->HighlightEdges( alarm_rgb, &limits );
|
||||
|
||||
delete diff_image;
|
||||
//high_image->WriteJpeg( "diff4.jpg" );
|
||||
|
||||
Info(( "%s: Alarm Pixels: %d, Filter Pixels: %d, Blob Pixels: %d, Blobs: %d, Score: %d", Label(), alarm_pixels, filter_pixels, blob_pixels, blobs, score ));
|
||||
}
|
||||
return( true );
|
||||
}
|
||||
|
||||
int Zone::Load( Monitor *monitor, Zone **&zones )
|
||||
{
|
||||
static char sql[256];
|
||||
sprintf( sql, "select Id,Name,Type+0,Units,LoX,LoY,HiX,HiY,AlarmRGB,AlarmThreshold,MinAlarmPixels,MaxAlarmPixels,FilterX,FilterY,MinFilterPixels,MaxFilterPixels,MinBlobPixels,MaxBlobPixels,MinBlobs,MaxBlobs from Zones where MonitorId = %d order by Type, Id", monitor->Id() );
|
||||
if ( mysql_query( &dbconn, sql ) )
|
||||
{
|
||||
Error(( "Can't run query: %s", mysql_error( &dbconn ) ));
|
||||
exit( mysql_errno( &dbconn ) );
|
||||
}
|
||||
|
||||
MYSQL_RES *result = mysql_store_result( &dbconn );
|
||||
if ( !result )
|
||||
{
|
||||
Error(( "Can't use query result: %s", mysql_error( &dbconn ) ));
|
||||
exit( mysql_errno( &dbconn ) );
|
||||
}
|
||||
int n_zones = mysql_num_rows( result );
|
||||
Info(( "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++ )
|
||||
{
|
||||
int Id = atoi(dbrow[0]);
|
||||
const char *Name = dbrow[1];
|
||||
int Type = atoi(dbrow[2]);
|
||||
const char *Units = dbrow[3];
|
||||
int LoX = atoi(dbrow[4]);
|
||||
int LoY = atoi(dbrow[5]);
|
||||
int HiX = atoi(dbrow[6]);
|
||||
int HiY = atoi(dbrow[7]);
|
||||
int AlarmRGB = dbrow[8]?atoi(dbrow[8]):0;
|
||||
int AlarmThreshold = dbrow[9]?atoi(dbrow[9]):0;
|
||||
int MinAlarmPixels = dbrow[10]?atoi(dbrow[10]):0;
|
||||
int MaxAlarmPixels = dbrow[11]?atoi(dbrow[11]):0;
|
||||
int FilterX = dbrow[12]?atoi(dbrow[12]):0;
|
||||
int FilterY = dbrow[13]?atoi(dbrow[13]):0;
|
||||
int MinFilterPixels = dbrow[14]?atoi(dbrow[14]):0;
|
||||
int MaxFilterPixels = dbrow[15]?atoi(dbrow[15]):0;
|
||||
int MinBlobPixels = dbrow[16]?atoi(dbrow[16]):0;
|
||||
int MaxBlobPixels = dbrow[17]?atoi(dbrow[17]):0;
|
||||
int MinBlobs = dbrow[18]?atoi(dbrow[18]):0;
|
||||
int MaxBlobs = dbrow[19]?atoi(dbrow[19]):0;
|
||||
|
||||
if ( !strcmp( Units, "Percent" ) )
|
||||
{
|
||||
LoX = (LoX*(monitor->CameraWidth()-1))/100;
|
||||
LoY = (LoY*(monitor->CameraHeight()-1))/100;
|
||||
HiX = (HiX*(monitor->CameraWidth()-1))/100;
|
||||
HiY = (HiY*(monitor->CameraHeight()-1))/100;
|
||||
MinAlarmPixels = (MinAlarmPixels*monitor->CameraWidth()*monitor->CameraHeight())/100;
|
||||
MaxAlarmPixels = (MaxAlarmPixels*monitor->CameraWidth()*monitor->CameraHeight())/100;
|
||||
MinFilterPixels = (MinFilterPixels*monitor->CameraWidth()*monitor->CameraHeight())/100;
|
||||
MaxFilterPixels = (MaxFilterPixels*monitor->CameraWidth()*monitor->CameraHeight())/100;
|
||||
MinBlobPixels = (MinBlobPixels*monitor->CameraWidth()*monitor->CameraHeight())/100;
|
||||
MaxBlobPixels = (MaxBlobPixels*monitor->CameraWidth()*monitor->CameraHeight())/100;
|
||||
}
|
||||
|
||||
if ( atoi(dbrow[2]) == Zone::INACTIVE )
|
||||
{
|
||||
zones[i] = new Zone( monitor, Id, Name, Box( LoX, LoY, HiX, HiY ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
zones[i] = new Zone( monitor, Id, Name, (Zone::ZoneType)Type, Box( LoX, LoY, HiX, HiY ), AlarmRGB, AlarmThreshold, MinAlarmPixels, MaxAlarmPixels, Coord( FilterX, FilterY ), MinFilterPixels, MaxFilterPixels, MinBlobPixels, MaxBlobPixels, MinBlobs, MaxBlobs );
|
||||
}
|
||||
}
|
||||
if ( mysql_errno( &dbconn ) )
|
||||
{
|
||||
Error(( "Can't fetch row: %s", mysql_error( &dbconn ) ));
|
||||
exit( mysql_errno( &dbconn ) );
|
||||
}
|
||||
// Yadda yadda
|
||||
mysql_free_result( result );
|
||||
return( n_zones );
|
||||
}
|
||||
|
||||
bool Zone::DumpSettings( char *output, bool verbose )
|
||||
{
|
||||
output[0] = 0;
|
||||
|
||||
sprintf( output+strlen(output), " Id : %d\n", id );
|
||||
sprintf( output+strlen(output), " Label : %s\n", label );
|
||||
sprintf( output+strlen(output), " Type: %d - %s\n", type,
|
||||
type==ACTIVE?"Active":(
|
||||
type==INCLUSIVE?"Inclusive":(
|
||||
type==EXCLUSIVE?"Exclusive":(
|
||||
type==INACTIVE?"Inactive":"Unknown"
|
||||
))));
|
||||
sprintf( output+strlen(output), " Limits : %d,%d - %d,%d\n", limits.LoX(), limits.LoY(), limits.HiX(), limits.HiY() );
|
||||
sprintf( output+strlen(output), " Alarm RGB : %06x\n", alarm_rgb );
|
||||
sprintf( output+strlen(output), " Alarm Threshold : %d\n", alarm_threshold );
|
||||
sprintf( output+strlen(output), " Min Alarm Pixels : %d\n", min_alarm_pixels );
|
||||
sprintf( output+strlen(output), " Max Alarm Pixels : %d\n", max_alarm_pixels );
|
||||
sprintf( output+strlen(output), " Filter Box : %d,%d\n", filter_box.X(), filter_box.Y() );
|
||||
sprintf( output+strlen(output), " Min Filter Pixels : %d\n", min_filter_pixels );
|
||||
sprintf( output+strlen(output), " Max Filter Pixels : %d\n", max_filter_pixels );
|
||||
sprintf( output+strlen(output), " Min Blob Pixels : %d\n", min_blob_pixels );
|
||||
sprintf( output+strlen(output), " Max Blob Pixels : %d\n", max_blob_pixels );
|
||||
sprintf( output+strlen(output), " Min Blobs : %d\n", min_blobs );
|
||||
sprintf( output+strlen(output), " Max Blobs : %d\n", max_blobs );
|
||||
return( true );
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
//
|
||||
// ZoneMinder Zone Class Interfaces, $Date$, $Revision$
|
||||
// Copyright (C) 2003 Philip Coombes
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
//
|
||||
|
||||
#ifndef ZM_ZONE_H
|
||||
#define ZM_ZONE_H
|
||||
|
||||
#include "zm_rgb.h"
|
||||
#include "zm_coord.h"
|
||||
#include "zm_box.h"
|
||||
#include "zm_image.h"
|
||||
#include "zm_event.h"
|
||||
|
||||
class Monitor;
|
||||
|
||||
//
|
||||
// This describes a 'zone', or an area of an image that has certain
|
||||
// detection characteristics.
|
||||
//
|
||||
class Zone
|
||||
{
|
||||
public:
|
||||
typedef enum { ACTIVE=1, INCLUSIVE, EXCLUSIVE, INACTIVE } ZoneType;
|
||||
|
||||
protected:
|
||||
// Inputs
|
||||
Monitor *monitor;
|
||||
|
||||
int id;
|
||||
char *label;
|
||||
ZoneType type;
|
||||
Box limits;
|
||||
Rgb alarm_rgb;
|
||||
|
||||
int alarm_threshold;
|
||||
int min_alarm_pixels;
|
||||
int max_alarm_pixels;
|
||||
|
||||
Coord filter_box;
|
||||
int min_filter_pixels;
|
||||
int max_filter_pixels;
|
||||
|
||||
int min_blob_pixels;
|
||||
int max_blob_pixels;
|
||||
int min_blobs;
|
||||
int max_blobs;
|
||||
|
||||
// Outputs/Statistics
|
||||
bool alarmed;
|
||||
int alarm_pixels;
|
||||
int alarm_filter_pixels;
|
||||
int alarm_blob_pixels;
|
||||
int alarm_blobs;
|
||||
int min_blob_size;
|
||||
int max_blob_size;
|
||||
Box alarm_box;
|
||||
unsigned int score;
|
||||
Image *image;
|
||||
|
||||
protected:
|
||||
void Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Box &p_limits, const Rgb p_alarm_rgb, int p_alarm_threshold, int p_min_alarm_pixels, int p_max_alarm_pixels, const Coord &p_filter_box, int p_min_filter_pixels, int p_max_filter_pixels, int p_min_blob_pixels, int p_max_blob_pixels, int p_min_blobs, int p_max_blobs );
|
||||
|
||||
public:
|
||||
Zone( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Box &p_limits, const Rgb p_alarm_rgb, int p_alarm_threshold=15, int p_min_alarm_pixels=50, int p_max_alarm_pixels=75000, const Coord &p_filter_box=Coord( 3, 3 ), int p_min_filter_pixels=50, int p_max_filter_pixels=50000, int p_min_blob_pixels=10, int p_max_blob_pixels=0, int p_min_blobs=0, int p_max_blobs=0 )
|
||||
{
|
||||
Setup( p_monitor, p_id, p_label, p_type, p_limits, p_alarm_rgb, p_alarm_threshold, p_min_alarm_pixels, p_max_alarm_pixels, p_filter_box, p_min_filter_pixels, p_max_filter_pixels, p_min_blob_pixels, p_max_blob_pixels, p_min_blobs, p_max_blobs );
|
||||
}
|
||||
Zone( Monitor *p_monitor, int p_id, const char *p_label, const Box &p_limits, const Rgb p_alarm_rgb, int p_alarm_threshold=15, int p_min_alarm_pixels=50, int p_max_alarm_pixels=75000, const Coord &p_filter_box=Coord( 3, 3 ), int p_min_filter_pixels=50, int p_max_filter_pixels=50000, int p_min_blob_pixels=10, int p_max_blob_pixels=0, int p_min_blobs=0, int p_max_blobs=0 )
|
||||
{
|
||||
Setup( p_monitor, p_id, p_label, Zone::ACTIVE, p_limits, p_alarm_rgb, p_alarm_threshold, p_min_alarm_pixels, p_max_alarm_pixels, p_filter_box, p_min_filter_pixels, p_max_filter_pixels, p_min_blob_pixels, p_max_blob_pixels, p_min_blobs, p_max_blobs );
|
||||
}
|
||||
Zone( Monitor *p_monitor, int p_id, const char *p_label, const Box &p_limits )
|
||||
{
|
||||
Setup( p_monitor, p_id, p_label, Zone::INACTIVE, p_limits, RGB_BLACK, 0, 0, 0, Coord( 0, 0 ), 0, 0, 0, 0, 0, 0 );
|
||||
}
|
||||
|
||||
public:
|
||||
~Zone();
|
||||
|
||||
inline const char *Label() const { return( label ); }
|
||||
inline ZoneType Type() const { return( type ); }
|
||||
inline bool IsActive() const { return( type == ACTIVE ); }
|
||||
inline bool IsInclusive() const { return( type == INCLUSIVE ); }
|
||||
inline bool IsExclusive() const { return( type == EXCLUSIVE ); }
|
||||
inline bool IsInactive() const { return( type == INACTIVE ); }
|
||||
inline Image &AlarmImage() const { return( *image ); }
|
||||
inline const Box &Limits() const { return( limits ); }
|
||||
inline bool Alarmed() const { return( alarmed ); }
|
||||
inline void SetAlarm() { alarmed = true; }
|
||||
inline void ClearAlarm() { alarmed = false; }
|
||||
inline unsigned int Score() const { return( score ); }
|
||||
|
||||
inline void ResetStats()
|
||||
{
|
||||
alarmed = false;
|
||||
alarm_pixels = 0;
|
||||
alarm_filter_pixels = 0;
|
||||
alarm_blob_pixels = 0;
|
||||
alarm_blobs = 0;
|
||||
min_blob_size = 0;
|
||||
max_blob_size = 0;
|
||||
score = 0;
|
||||
}
|
||||
void RecordStats( const Event *event );
|
||||
bool CheckAlarms( const Image *delta_image );
|
||||
bool DumpSettings( char *output, bool verbose );
|
||||
|
||||
static int Load( Monitor *monitor, Zone **&zones );
|
||||
};
|
||||
|
||||
#endif // ZM_ZONE_H
|
Loading…
Reference in New Issue