矩形结构体的各个元素的取值范围是[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 <string.h> #include <malloc.h> #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