矩形结构体的各个元素的取值范围是[0 ~ 999] ,代表[0.000 ~ 0.999] , 注意是闭区间。
参数2:ID号不能重复。/*
* Motion detecting
*
* File: motion_detect.h
*
* Author: Hugui
* E-Mail: y_y_z_l @ 163.com
* Date: 2012.7.6
*
* Changing Log:
*
*/
/*
* Coordinate system of jpeg blocks.
*
* +---------------> x
* |
* |
* |
* |
* V
* y
*
/---> JPEG BLOCK
/
/
/
/
/
/ | | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
0 | 1 | 2 | | | | | | | 7 | ...
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
-----------------------------------------------------------------------------------------
| | | | | | | | | |
| | | | | | | | | |
| | ####################################################### |
| | # | | | | | | | # |
| | # | | | | | | | # |
| | # | | | | | | | # |
| | # | | | | | | | # |
-------------------#-----------------------------------------------------#---------------
| | # | | | | | | | # |
| | # | | | | | | | # |
| | # | | | | | | | # | /--> Selected zone 1#
| | # | | | | | | | # | /
| | # | | | | | | ---------------/
| | # | ########################################### | # |
| | # | # | | | | | # | # |
-------------------#-----#-----------------------------------------#-----#---------------
| | # | # | | | | | # | # |
| | # | # | | | | | # | # |
| | ####################################################### |
| | | # | | | | | # | |
| | | # | | | | | # | |
| | | # | | | ######################### |
| | | # | | | # | | # | # |
-------------------------#--------------------------#--------------#--------#------------
| | | # | | | # | | # | # |
| | | # | | | # | | # | # |
| ########################## | | # | | # | # | /--> Selected zone 2#
| # | | # | # | | # | | # | # | /
| # | | # | # | | # | | # | ---------/
| # | | # | # | | | # | | # | # |
| # | | # | # | | | # | | # | # |
---------#---------------#--------#--------|--------#--------------#--------#------------
| # | | # | # | | | # | | # | # |
| # | | ##################|######################## | # |
. | # | | | # | | | # | | | # |
. | # | | | | # | | | ######################### |
. | # | | | | # | | | | | | |
| ##########|############### | | | | | | |
| | | | | | | | | | | |
| \.
\ \---> Selected zone 4#
\--> Selected zone 3#
*/
/*
* Coordinate system of alarm zone.
*
* +--------------------------> x
* | (left, top)
* | +---------------------+
* | | |
* | | .p1(x1,y1) |
* | | .p2(x2,y2) |
* | | |
* | +---------------------+ (right, bottom)
* |
* V
* y
*
* p1(250,300) --> (0.250 * img_width, 0.3 * img_height)
* p2(350,600) --> (0.350 * img_width, 0.6 * img_height)
*
* Coordinate by thousandths.
* Example:
* value | actual coordinate
* ------+---------------------------------
* 100 | 0.1 * img_width(img_height)
* 50 | 0.05 * img_width(img_height)
* 500 | 0.5 * img_width(img_height)
* 1 | 0.001 * img_width(img_height)
*/
#ifndef _H_MOTION_DETECT_H_
#define _H_MOTION_DETECT_H_
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* The maximum length of image */
#define IMG_WIDTH_MAX 640
#define IMG_HEIGHT_MAX 480
/* The minimum length of image */
#define IMG_WIDTH_MIN 160
#define IMG_HEIGHT_MIN 120
/* JPEG image block dimention: 8pixels * 8pixels */
#define JPEG_BLOCK_DIM 8
/* Indicating whether the pointer parameter is INPUT or OUTPUT */
#define __INPUT__
#define __OUTPUT__
/* How many zones which are being monitored */
#define ALARM_ZONE_MAX 20
/* Don't be great than 5 */
#define ALARM_SENSITY_LEVEL_MAX 5
/*
* ----------------------- level 5 The least sensitive
*
* ----------------------- level 4
*
* ----------------------- level 3
* | ALARM_SENSITY_STEP_VAL
* ----------------------- level 2
*
* ----------------------- ALARM_SENSITY_START_VAL, start threshold,
* level 1, The most sensitive
*
* ----------------------- zero, means no changing.
*/
/* The start threshold */
#define ALARM_SENSITY_START_VAL 5
/* The stepping value of each sensity level */
#define ALARM_SENSITY_STEP_VAL 10
/* Each level */
#if ALARM_SENSITY_LEVEL_MAX > 5
#error "ALARM_SENSITY_LEVEL_MAX is not allowed to be great than 5"
#elif ALARM_SENSITY_LEVEL_MAX < 1
#error "ALARM_SENSITY_LEVEL_MAX is not allowed to be less than 1"
#else
#if ALARM_SENSITY_LEVEL_MAX >= 1
#define ALARM_SENSITY_LV1 1
#define ALARM_SENSITY_VAL_LV1 ALARM_SENSITY_START_VAL
#define USING_ALARM_LV1
#endif
#if ALARM_SENSITY_LEVEL_MAX >= 2
#define ALARM_SENSITY_LV2 2
#define ALARM_SENSITY_VAL_LV2 (ALARM_SENSITY_START_VAL + \
ALARM_SENSITY_STEP_VAL * (ALARM_SENSITY_LV2 - 1))
#define USING_ALARM_LV2
#endif
#if ALARM_SENSITY_LEVEL_MAX >= 3
#define ALARM_SENSITY_LV3 3
#define ALARM_SENSITY_VAL_LV3 (ALARM_SENSITY_START_VAL + \
ALARM_SENSITY_STEP_VAL * (ALARM_SENSITY_LV3 - 1))
#define USING_ALARM_LV3
#endif
#if ALARM_SENSITY_LEVEL_MAX >= 4
#define ALARM_SENSITY_LV4 4
#define ALARM_SENSITY_VAL_LV4 (ALARM_SENSITY_START_VAL + \
ALARM_SENSITY_STEP_VAL * (ALARM_SENSITY_LV4 - 1))
#define USING_ALARM_LV4
#endif
#if ALARM_SENSITY_LEVEL_MAX >= 5
#define ALARM_SENSITY_LV5 5
#define ALARM_SENSITY_VAL_LV5 (ALARM_SENSITY_START_VAL + \
ALARM_SENSITY_STEP_VAL * (ALARM_SENSITY_LV5 - 1))
#define USING_ALARM_LV5
#endif
#endif
/* Error code */
#define EC_MEM 1 /* No memery */
#define EC_ID 2 /* ID error */
#define EC_NO_SLOT 3 /* Alarm table full */
#define EC_FRAM1 4 /* Not ready */
#define EC_FRAM2 5 /* Not ready */
#define EC_STATE 6 /* Error state */
#define EC_DIM 7 /* Dimention Error */
#define EC_DIM_CHANG 8 /* Dimention changed but no notify */
/*
* Bits operation
*
* dat: the target byte.
* pos: the position you want to operate.
* len: the width of bits.
* val: the value you want to set or test.
*
* Example:
* dat | operation | result
* ---------+-------------------------------+----------
* 11010001 | SET_BYTE_BITS(dat, 2, 2, 3) | 11011101
* 11010001 | SET_BYTE_BITS(dat, 4, 2, 3) | 11110001
* 10110111 | TEST_BYTE_BITS(dat, 3, 2, 1) | flase
* 10110111 | TEST_BYTE_BITS(dat, 3, 2, 2) | true
*/
#define SET_BYTE_BITS(dat, pos, len, val) do { \
(dat) &= ~( (~(0xFF<<(len))) << (pos) ); /* Set to zero */ \
(dat) |= ( ((val)&(~(0xFF<<(len)))) << (pos) ); /* Set val */ \
} while (0)
#define TEST_BYTE_BITS(dat, pos, len, val) \
( (((val)&(~(0xFF<<(len)))) << (pos)) == \
( (dat) & ( (~(0xFF<<(len))) << (pos) ) ) )
/* Rectangle define */
typedef struct _tag_rect {
unsigned short left;
unsigned short right;
unsigned short top;
unsigned short bottom;
} Rect, *PRect;
/* Image define */
typedef struct _tag_image {
unsigned char * pbuf;
int len;
} Image, *PImage;
/* Define the alarm zone */
typedef struct _tag_alarm_zone {
int id;
Rect zone;
unsigned char alarm_level;
} AlarmZone, *PAlarmZone;
/*
* Return the alarm info into an array whose type is AlarmInfoArray when
* invoke motion_detect()
*/
typedef AlarmZone AlarmInfoArray[ALARM_ZONE_MAX];
/*
* ------ Interface -------
*/
/* Initial or reset the motion detecting system. */
int reset_motion_detect(void);
/*
* Set dimention of image
* When the dimention of image has changed, you should call this function.
* Default setting: 320 * 240
*/
int set_img_dim(unsigned short width, unsigned short height);
/* Add & remove alarm zone. Zone Cross or Zone Overlapping is OK */
int add_alarm_zone(Rect* zone, int id, unsigned char alarm_level);
int rm_alarm_zone(int id);
int rm_all_alarm(void);
/* Invoke this at every image frame */
int motion_detect(Image* __INPUT__ img,
AlarmInfoArray* __OUTPUT__ alarm_info, int* __OUTPUT__ alarm_count);
/*
* ------ Internal function --------
*/
/* Caculate the alarm level by y. */
unsigned char whichlevel(int delta_y);
/* Update the changed direction of y. */
void update_y_direction(int block_index, int delta_y);
/* Update the alarm table. */
void update_alarm_tbl(int block_index, int delta_y);
/* Scan the alarm table */
void generate_alarm(AlarmInfoArray* __OUTPUT__ alarm_info, int* __OUTPUT__ alarm_count);
/* Check whether the selected block zone contains valid alarm. */
bool is_alarm(Rect* blk_zone, unsigned char alarm_level);
/*
* Transfer the rectangle from image view coordinate system
* to jpeg block coordinate system.
*/
void coordinate_transfer(Rect* alarm_zone, Rect* __OUTPUT__ blk_zone);
#ifdef __cplusplus
}
#endif
/*
* Motion detecting
*
* File: motion_detect.c
*
* Author: Hugui
* E-Mail: y_y_z_l @ 163.com
* Date: 2012.7.6
*
* Changing Log:
*
*/
#include
#include
#include "motion_detect.h"
extern int decode_y(unsigned char * jpeg, int jpeglen, int * y);
/*
* The last changing direction of Y.
* 00: grayscale no changed.
* 01: grayscale increased.
* 10: grayscale decreased.
*
* last_y_direction[0][]
* byte0 byte1 byte2
* 01 00 10 01 10 10 00 01 10 10 00 01 ...
* |
* |
* V
* Start from here,This is the first block.
* last_y_direction[1][]
* ...
*
*/
#define BLK_Y_NO_CHANGE 0
#define BLK_Y_INCREASED 1
#define BLK_Y_DECREASED 2
unsigned char last_y_direction[ALARM_SENSITY_LEVEL_MAX][ \
(IMG_WIDTH_MAX / JPEG_BLOCK_DIM) * \
(IMG_HEIGHT_MAX / JPEG_BLOCK_DIM) / 4];
/* Last grayscale */
int last_y[(IMG_WIDTH_MAX / JPEG_BLOCK_DIM) * (IMG_HEIGHT_MAX / JPEG_BLOCK_DIM)];
int last_y_len;
/* Current graysacle, this variable is for temperary using. */
int crt_y[(IMG_WIDTH_MAX / JPEG_BLOCK_DIM) * (IMG_HEIGHT_MAX / JPEG_BLOCK_DIM)];
/*
* Alarm table.
*
* 0: no alarm.
* 1: ALARM !!!
*
* alarm_tbl[0][]
* byte0 byte1 byte2
* 01001001 10100001 10100001 ...
* |
* |
* V
* Start from here,This is the first block.
* alarm_tbl[1][]
* ...
*
*/
unsigned char alarm_tbl[ALARM_SENSITY_LEVEL_MAX][ \
(IMG_WIDTH_MAX / JPEG_BLOCK_DIM) * \
(IMG_HEIGHT_MAX / JPEG_BLOCK_DIM) / 8];
/* The current width & height of image */
unsigned short img_width = 320;
unsigned short img_height = 240;
/* State of motion detecting process */
#define MD_STATE_FRAM1 1
#define MD_STATE_FRAM2 2
#define MD_STATE_FRAM3 3
unsigned char motion_detect_state = MD_STATE_FRAM1;
/* Registered alarm zone */
PAlarmZone alarm_zone_tbl[ALARM_ZONE_MAX];
/*
* Initial or reset the motion detecting system.
*
* @return: 0 for OK
*/
int reset_motion_detect(void)
{
motion_detect_state = MD_STATE_FRAM1;
memset(last_y_direction, 0x00, sizeof(last_y_direction));
return 0;
}
/*
* Set dimention of image
* When the dimention of image has changed, you should call this function.
* Default setting: 320 * 240
*
* @width: width of image, unit by pixel
* @height: height
*
* @return: 0 for OK
*/
int set_img_dim(unsigned short width, unsigned short height)
{
if (width > IMG_WIDTH_MAX ||
height > IMG_HEIGHT_MAX )
return EC_DIM;
if (width < IMG_WIDTH_MIN ||
height < IMG_HEIGHT_MIN )
return EC_DIM;
img_width = width;
img_height = height;
reset_motion_detect();
return 0;
}
/*
* Add alarm zone.
*
* @zone: selected alarm zone, a rectangle(check header file for details).
* @id: Registered id.
* @alarm_level: use macro defined in the header file.
*
* @return: 0 for OK.
*/
int add_alarm_zone(Rect* zone, int id, unsigned char alarm_level)
{
PAlarmZone p;
int i;
/* Check the zone id, no repeated */
for (i = 0; i < ALARM_ZONE_MAX; i++) {
if (alarm_zone_tbl[i]) {
if (alarm_zone_tbl[i]->id == id)
return EC_ID;
}
}
/* Find an empty slot */
for (i = 0; i < ALARM_ZONE_MAX; i++) {
if (!alarm_zone_tbl[i])
break;
}
/* No empty slot */
if (i == ALARM_ZONE_MAX)
return EC_NO_SLOT;
/* Get memory */
p = (PAlarmZone )malloc(sizeof(AlarmZone));
if (!p) {
return EC_MEM;
}
/* Check the range of rectangle */
if (zone->left > 999) zone->left = 999;
if (zone->right > 999) zone->right = 999;
if (zone->top > 999) zone->top = 999;
if (zone->bottom > 999) zone->bottom = 999;
/* Initialize */
p->id = id;
p->alarm_level = alarm_level;
memcpy(&p->zone, zone, sizeof(Rect));
/* Insert to one empty slot */
alarm_zone_tbl[i] = p;
return 0;
}
/*
* Remove alarm zone by id.
*
* @id: id of alarm zone.
*
* @return: 0 for OK
*/
int rm_alarm_zone(int id)
{
int i;
for (i = 0; i < ALARM_ZONE_MAX; i++) {
if (alarm_zone_tbl[i]) {
if (alarm_zone_tbl[i]->id == id) {
free(alarm_zone_tbl[i]);
alarm_zone_tbl[i] = NULL;
return 0;
}
}
}
return EC_ID;
}
/*
* Remove all alarm zone .
*
* @return: 0 for OK
*/
int rm_all_alarm(void)
{
memset(alarm_zone_tbl, 0x00, sizeof(alarm_zone_tbl));
return 0;
}
/*
* Invoke this at every image frame
*
* @img: An image object pointer. Contains buffer and length.
* @alarm_info: Alarm info, this is an array.
* @alarm_count: The valid length of @alarm_info array.
*
* @return: 0 for OK. The output parameters are valid only when return 0.
*/
int motion_detect(Image* __INPUT__ img,
AlarmInfoArray* __OUTPUT__ alarm_info, int* __OUTPUT__ alarm_count)
{
int blocks;
int i;
int delta_y;
/* Decode grayscale */
blocks = decode_y(img->pbuf, img->len, crt_y);
switch (motion_detect_state) {
/* Not ready, only one frame. */
case MD_STATE_FRAM1:
last_y_len = blocks;
memcpy(last_y, crt_y, sizeof(crt_y));
motion_detect_state = MD_STATE_FRAM2;
return EC_FRAM1;
/* Not ready, only two frames. */
case MD_STATE_FRAM2:
/* Dimention of image has changed but didn't invoke set_img_dim() */
if (blocks != last_y_len) {
reset_motion_detect();
return EC_DIM_CHANG;
}
for (i = 0; i < blocks; i++) {
delta_y = crt_y[i] - last_y[i];
update_y_direction(i, delta_y);
}
last_y_len = blocks;
memcpy(last_y, crt_y, sizeof(crt_y));
motion_detect_state = MD_STATE_FRAM3;
return EC_FRAM2;
/* YES! Loops in this case */
case MD_STATE_FRAM3:
/* Dimention of image has changed but didn't invoke set_img_dim() */
if (blocks != last_y_len) {
reset_motion_detect();
return EC_DIM_CHANG;
}
for (i = 0; i < blocks; i++) {
delta_y = crt_y[i] - last_y[i];
update_alarm_tbl(i, delta_y);
}
last_y_len = blocks;
memcpy(last_y, crt_y, sizeof(crt_y));
generate_alarm(alarm_info, alarm_count);
return 0;
/* NOT expected */
default:
return EC_STATE;
}
}
/*
* Caculate the alarm level by y.
*
* @delta_y: grayscale changed.
*
* @return: Alarm level. Check the header file for details.
*/
unsigned char whichlevel(int delta_y)
{
if (delta_y < 0)
delta_y = -delta_y;
#if ALARM_SENSITY_LEVEL_MAX >= 5
if (delta_y >= ALARM_SENSITY_VAL_LV5)
return ALARM_SENSITY_LV5;
else
#endif
#if ALARM_SENSITY_LEVEL_MAX >= 4
if (delta_y >= ALARM_SENSITY_VAL_LV4)
return ALARM_SENSITY_LV4;
else
#if ALARM_SENSITY_LEVEL_MAX >= 3
#endif
if (delta_y >= ALARM_SENSITY_VAL_LV3)
return ALARM_SENSITY_LV3;
else
#if ALARM_SENSITY_LEVEL_MAX >= 2
#endif
if (delta_y >= ALARM_SENSITY_VAL_LV2)
return ALARM_SENSITY_LV2;
else
#endif
#if ALARM_SENSITY_LEVEL_MAX >= 1
if (delta_y >= ALARM_SENSITY_VAL_LV1)
return ALARM_SENSITY_LV1;
else
#endif
return 0; /* NO changing */
}
/*
* Update the changed direction of y.
* There are 4 blocks in one byte,each block own 2 bits.
*
* @block_index: which jepg block?
* @delta_y: y changed.
*/
void update_y_direction(int block_index, int delta_y)
{
int i;
unsigned char level;
level = whichlevel(delta_y);
switch (level) {
case 0:
/* NO changing. Update all of the table */
for (i = 0; i < ALARM_SENSITY_LEVEL_MAX; i++) {
SET_BYTE_BITS(last_y_direction[i][block_index / 4],
(block_index % 4) << 1, 2, BLK_Y_NO_CHANGE);
}
break;
#ifdef USING_ALARM_LV5
case ALARM_SENSITY_LV5:
SET_BYTE_BITS(last_y_direction[ALARM_SENSITY_LV5 - 1][block_index / 4],
(block_index % 4) << 1, 2, delta_y > 0 ? BLK_Y_INCREASED : BLK_Y_DECREASED);
#endif
#ifdef USING_ALARM_LV4
case ALARM_SENSITY_LV4:
SET_BYTE_BITS(last_y_direction[ALARM_SENSITY_LV4 - 1][block_index / 4],
(block_index % 4) << 1, 2, delta_y > 0 ? BLK_Y_INCREASED : BLK_Y_DECREASED);
#endif
#ifdef USING_ALARM_LV3
case ALARM_SENSITY_LV3:
SET_BYTE_BITS(last_y_direction[ALARM_SENSITY_LV3 - 1][block_index / 4],
(block_index % 4) << 1, 2, delta_y > 0 ? BLK_Y_INCREASED : BLK_Y_DECREASED);
#endif
#ifdef USING_ALARM_LV2
case ALARM_SENSITY_LV2:
SET_BYTE_BITS(last_y_direction[ALARM_SENSITY_LV2 - 1][block_index / 4],
(block_index % 4) << 1, 2, delta_y > 0 ? BLK_Y_INCREASED : BLK_Y_DECREASED);
#endif
#ifdef USING_ALARM_LV1
case ALARM_SENSITY_LV1:
SET_BYTE_BITS(last_y_direction[ALARM_SENSITY_LV1 - 1][block_index / 4],
(block_index % 4) << 1, 2, delta_y > 0 ? BLK_Y_INCREASED : BLK_Y_DECREASED);
#endif
break;
default:
; /* WARNING! */
}
}
/*
* Update the alarm table.
*
* @block_index: which jepg block?
* @delta_y: y changed.
*/
void update_alarm_tbl(int block_index, int delta_y)
{
unsigned char level;
level = whichlevel(delta_y);
switch (level) {
#ifdef USING_ALARM_LV5
case ALARM_SENSITY_LV5:
if (
/* Bright -> Dark -> Bright */
(delta_y > 0 && TEST_BYTE_BITS(
last_y_direction[ALARM_SENSITY_LV5 - 1][block_index / 4],
(block_index % 4) << 1, 2, BLK_Y_DECREASED)) ||
/* Dark -> Bright -> Dark */
(delta_y < 0 && TEST_BYTE_BITS(
last_y_direction[ALARM_SENSITY_LV5 - 1][block_index / 4],
(block_index % 4) << 1, 2, BLK_Y_INCREASED))
) {
alarm_tbl[ALARM_SENSITY_LV5 - 1][block_index / 8] |= 0x01 << (block_index % 8);
}
#endif
#ifdef USING_ALARM_LV4
case ALARM_SENSITY_LV4:
if (
/* Bright -> Dark -> Bright */
(delta_y > 0 && TEST_BYTE_BITS(
last_y_direction[ALARM_SENSITY_LV4 - 1][block_index / 4],
(block_index % 4) << 1, 2, BLK_Y_DECREASED)) ||
/* Dark -> Bright -> Dark */
(delta_y < 0 && TEST_BYTE_BITS(
last_y_direction[ALARM_SENSITY_LV4 - 1][block_index / 4],
(block_index % 4) << 1, 2, BLK_Y_INCREASED))
) {
alarm_tbl[ALARM_SENSITY_LV4 - 1][block_index / 8] |= 0x01 << (block_index % 8);
}
#endif
#ifdef USING_ALARM_LV3
case ALARM_SENSITY_LV3:
if (
/* Bright -> Dark -> Bright */
(delta_y > 0 && TEST_BYTE_BITS(
last_y_direction[ALARM_SENSITY_LV3 - 1][block_index / 4],
(block_index % 4) << 1, 2, BLK_Y_DECREASED)) ||
/* Dark -> Bright -> Dark */
(delta_y < 0 && TEST_BYTE_BITS(
last_y_direction[ALARM_SENSITY_LV3 - 1][block_index / 4],
(block_index % 4) << 1, 2, BLK_Y_INCREASED))
) {
alarm_tbl[ALARM_SENSITY_LV3 - 1][block_index / 8] |= 0x01 << (block_index % 8);
}
#endif
#ifdef USING_ALARM_LV2
case ALARM_SENSITY_LV2:
if (
/* Bright -> Dark -> Bright */
(delta_y > 0 && TEST_BYTE_BITS(
last_y_direction[ALARM_SENSITY_LV2 - 1][block_index / 4],
(block_index % 4) << 1, 2, BLK_Y_DECREASED)) ||
/* Dark -> Bright -> Dark */
(delta_y < 0 && TEST_BYTE_BITS(
last_y_direction[ALARM_SENSITY_LV2 - 1][block_index / 4],
(block_index % 4) << 1, 2, BLK_Y_INCREASED))
) {
alarm_tbl[ALARM_SENSITY_LV2 - 1][block_index / 8] |= 0x01 << (block_index % 8);
}
#endif
#ifdef USING_ALARM_LV1
case ALARM_SENSITY_LV1:
if (
/* Bright -> Dark -> Bright */
(delta_y > 0 && TEST_BYTE_BITS(
last_y_direction[ALARM_SENSITY_LV1 - 1][block_index / 4],
(block_index % 4) << 1, 2, BLK_Y_DECREASED)) ||
/* Dark -> Bright -> Dark */
(delta_y < 0 && TEST_BYTE_BITS(
last_y_direction[ALARM_SENSITY_LV1 - 1][block_index / 4],
(block_index % 4) << 1, 2, BLK_Y_INCREASED))
) {
alarm_tbl[ALARM_SENSITY_LV1 - 1][block_index / 8] |= 0x01 << (block_index % 8);
}
#endif
break;
default:
; /* WARNING! */
}
/* Cover the old table */
update_y_direction(block_index, delta_y);
}
/*
* Scan the alarm table, when valid and the corresponding area
* is registered, return alarm info.
*
* @alarm_info: Alarm info, this is an array.
* @alarm_count: The valid length of @alarm_info array.
*/
void generate_alarm(AlarmInfoArray* __OUTPUT__ alarm_info, int* __OUTPUT__ alarm_count)
{
int i;
Rect blk_zone;
int index = 0;
/* Reset the count */
*alarm_count = 0;
for (i = 0; i < ALARM_ZONE_MAX; i++) {
if (alarm_zone_tbl[i]) {
coordinate_transfer(&(alarm_zone_tbl[i]->zone), &blk_zone);
if (is_alarm(&blk_zone, alarm_zone_tbl[i]->alarm_level)) {
memcpy(&(*alarm_info)[index], alarm_zone_tbl[i], sizeof(AlarmZone));
index++;
}
}
}
*alarm_count = index;
/* Reset alarm_tbl. This is very IMPORTANT! */
memset(alarm_tbl, 0x00, sizeof(alarm_tbl));
}
/*
* Check whether the selected block zone contains valid alarm.
*
* @blk_zone: Rectangle descripted by jpeg block coordinate system.
* @alarm_level: which alarm level do you want to check?
*
* @return: true for ALARM and false for NO alarm.
*/
bool is_alarm(Rect* blk_zone, unsigned char alarm_level)
{
int row, col;
int blk_index;
for (row = blk_zone->top; row <= blk_zone->bottom; row++) {
for (col = blk_zone->left; col <= blk_zone->right; col++) {
blk_index = img_width / JPEG_BLOCK_DIM * row + col;
if (alarm_tbl[alarm_level - 1][blk_index / 8] & (0x01 << (blk_index % 8))) {
return true;
}
}
}
return false;
}
/*
* Transfer the rectangle from image view coordinate system to jpeg block coordinate system.
*
* @alarm_zone: Selected alarm zone.
* @blk_zone: jpeg block coordinate system. See header file for details.
*/
void coordinate_transfer(Rect* alarm_zone, Rect* __OUTPUT__ blk_zone)
{
blk_zone->left = img_width / JPEG_BLOCK_DIM * alarm_zone->left / 1000;
blk_zone->right = img_width / JPEG_BLOCK_DIM * alarm_zone->right / 1000;
blk_zone->top = img_height / JPEG_BLOCK_DIM * alarm_zone->top / 1000;
blk_zone->bottom = img_height / JPEG_BLOCK_DIM * alarm_zone->bottom / 1000;
}
在服务器端还有肤色识别以及轮廓识别甚至轨迹判断等算法。
参见:http://bbs.21ic.com/icview-359290-1-1.html