⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 motion.c

📁 外国人写的一个很好的嵌入式视频采集源程序。
💻 C
字号:
/* Motion detection package *  (c) Gleicon S. Moraes * *  The simpliest algorithm to do it is: * *  [Get 1st frame] *  [Copy to reference buffer] *  loop: *      [Get frame] *      [Compare with reference buffer +- tolerance] *      if (changed) *      		[Store it back in the reference buffer] *      		[Signal back] *		[Loop] *      else  *      		[goto loop] *  * * More advanced forms can use a statistical approach and divide the image in  * small blocks to keep things balanced. the _tolerance_ factor is an attempt in * to dealing with subtle changes that should not be interpreted as movement * A mask with the region of interest can be taken in consideration * This method uses a *element* concept, which is the complete pixel, and calculates if all sub-elements were modified, or just * one of them. Statistically, if there is no change in one of the sub-elements within a pixel, chances are high its just a noise or * light variation. If all sub elements are affected, then the average counter is incremented. Testing shows that average * rates above 5% of the total image size are significant motion. */#include "_motion.h"#define DEBUG#define DOT fprintf(stderr,".");// provides automagic testing for more than 1 channel#define MAXCHAN 4int multi_motion(struct vd_video *vd, unsigned char tolerance) {        static int first=1;        static struct image_motion _stored_image[MAXCHAN], _cur_image;        int a, img_size, my_average;        img_size=vd->grab_size;	if (first) { // aloca, etc		for (a=0; a<vd->grab_cap.channels; a++) {			_stored_image[a].image=malloc(img_size);			_stored_image[a].x=vd->x;			_stored_image[a].y=vd->y;			_stored_image[a].depth=vd->w;			if (_stored_image[a].image==NULL) {				 perror("malloc: stored_image\n");				 return -1;			}		}		first=0;	}        // seleciona input e compara        _cur_image.image=vd->image;        _cur_image.x=vd->x;        _cur_image.y=vd->y;        _cur_image.depth=vd->w;        my_average=detect_motion(&_stored_image[vd->channel], &_cur_image, tolerance); // our tolerance at +-tolerance	return my_average;}																					int detect_motion (struct image_motion *_reference_image, struct image_motion *_local_img, char _tolerance) {	int a, pixel,  _img_size, b;	unsigned char ref_elem, given_elem;	unsigned int _average=0, sub_avg;		b=0;		_average=sub_avg=0;		_img_size=_reference_image->x * _reference_image->y * _reference_image->depth;	if (_img_size != _local_img->x * _local_img->y * _local_img->depth) {		#ifdef DEBUG		fprintf(stderr,"unmatched images\n\n");		#endif		return FALSE;		}	// clean it up	_local_img->left=_local_img->right=0;		/* travels through the image`s elements */	for (a=0; a< _img_size; a=a+_reference_image->depth) {		sub_avg=0;		/* travels through the element */		for (pixel=0; pixel< _reference_image->depth; pixel++) {			ref_elem=*(_reference_image->image+a+pixel);			given_elem=*(_local_img->image+a+pixel);			if (ref_elem != given_elem) {  				/* checks the tolerance */				if (ref_elem > (given_elem + _tolerance) || 				    ref_elem < (given_elem - _tolerance))	sub_avg++;						}			if (sub_avg==_local_img->depth) {				//_average++;				if (b / _local_img->y < (_local_img->x /2)) _local_img->left++;				else _local_img->right++;			}				}	b++;	}  	/* replaces the image - it can be substituted by an average or composed image */	/* all changes: */	_average=_local_img->left + _local_img->right;	memcpy (_reference_image->image, _local_img->image,_img_size);	_reference_image->x=_local_img->x;	_reference_image->y=_local_img->y;	_reference_image->depth=_local_img->depth;	_reference_image->left=_local_img->left;	_reference_image->right=_local_img->right;	return (_average); /* returns the count of pixels changed beyond the tolerance ( full elements ) */}/* subtracts one image from another */int subtract_motion (struct image_motion *_reference_image, struct image_motion *_local_img, char _tolerance) {	struct image_motion	_temp_image; // temp buffer	int a, pixel,  _img_size;	unsigned char ref_elem, given_elem;	unsigned int _average=0, sub_avg;			_average=sub_avg=0;		_img_size=_reference_image->x * _reference_image->y * _reference_image->depth;	if (_img_size != _local_img->x * _local_img->y * _local_img->depth) {		#ifdef DEBUG		fprintf(stderr,"unmatched images\n\n");		#endif		return FALSE;		}		_temp_image.image=malloc(_img_size * sizeof(unsigned char));	if ((_temp_image.image == (unsigned char *)NULL)) {		perror("subtract_image: malloc");		return(-1);	}		memcpy (_temp_image.image, _local_img->image,_img_size);	_temp_image.x=_local_img->x;	_temp_image.y=_local_img->y;	_temp_image.depth=_local_img->depth;	/* travels through the image`s elements */	for (a=0; a< _img_size; a=a+_reference_image->depth) {		sub_avg=0;		/* travels through the element */		for (pixel=0; pixel< _reference_image->depth; pixel++) {			ref_elem=*(_reference_image->image+a+pixel);			given_elem=*(_local_img->image+a+pixel);						/* checks the tolerance */			if (ref_elem != given_elem) {  				if (ref_elem > (given_elem + _tolerance) || 			    		ref_elem < (given_elem - _tolerance))	sub_avg++;						}		}						if (sub_avg==_reference_image->depth) {	//		*(_local_img->image+a+pixel)=(*(_reference_image->image+a+pixel) + *(_local_img->image+a+pixel)) / 2;			//		*(_local_img->image+a+pixel-1)=(*(_reference_image->image+a+pixel-1) + *(_local_img->image+a+pixel-1)) /2 ;			//		*(_local_img->image+a+pixel-2)=(*(_reference_image->image+a+pixel-2) + *(_local_img->image+a+pixel-2)) /2 ;					_average++;		} else {			*(_local_img->image+a+pixel)=0;					*(_local_img->image+a+pixel-1)=0;			*(_local_img->image+a+pixel-2)=0;				}	}  	/* replaces the image - it can be substituted by an average or composed image */	memcpy (_reference_image->image, _temp_image.image,_img_size);	_reference_image->x=_temp_image.x;	_reference_image->y=_temp_image.y;	_reference_image->depth=_temp_image.depth;		free(_temp_image.image);	return (_average); /* returns the count of pixels changed beyond the tolerance ( full elements ) */}/* load PHM file */int load_pnm(char *wot, struct image_motion *bufo){        FILE *fp;	int x, y, m, depth=1;	unsigned char ui[4];	if (!bufo->image) {		fprintf(stderr,"Buffer is null \n");		exit(0);	}	if (!(fp=fopen(wot, "rb"))) {		perror("file");		exit(0);	}	fscanf(fp, "%s\n%d %d\n%d\n", ui, &x, &y, &m); // header	fread(bufo->image, x * y * depth, 1, fp);	//fprintf(stderr,"X: %d\nY: %d\n",  x , y );	fclose(fp);	bufo->x=x;	bufo->y=y;	bufo->depth=1; // grayscale images only plz}int detect_motion_mask (struct image_motion *_reference_image, struct image_motion *_local_img, struct image_motion *mask, char _tolerance) {	int a, pixel,  _img_size, b;	unsigned char ref_elem, given_elem;	unsigned int _average=0, sub_avg;		b=0;		_average=sub_avg=0;		_img_size=_reference_image->x * _reference_image->y * _reference_image->depth;	if (_img_size != _local_img->x * _local_img->y * _local_img->depth) {		#ifdef DEBUG		fprintf(stderr,"unmatched images\n\n");		#endif		return FALSE;		}	if (mask->image==NULL || mask->x != _local_img->x || mask->y != _local_img->y) {		#ifdef DEBUG		fprintf(stderr,"fix the mask x:%d y:%d depth:%d\n", mask->x, mask->y, mask->depth);		#endif		return -1;	}		// clean it up	_local_img->left=_local_img->right=0;		/* travels through the image`s elements */	for (a=0; a< _img_size; a=a+_reference_image->depth) {		if (*(mask->image +b) != 255) {			b++;			continue; // skips if pixel is 0		}		sub_avg=0;		/* travels through the element */		for (pixel=0; pixel< _reference_image->depth; pixel++) {			ref_elem=*(_reference_image->image+a+pixel);			given_elem=*(_local_img->image+a+pixel);			if (ref_elem != given_elem) {  				/* checks the tolerance */				if (ref_elem > (given_elem + _tolerance) || 				    ref_elem < (given_elem - _tolerance))	sub_avg++;						}			if (sub_avg==_local_img->depth) {				//_average++;				if (b / _local_img->y < (_local_img->x /2)) _local_img->left++;				else _local_img->right++;			}				}	b++;	}  	/* replaces the image - it can be substituted by an average or composed image */	/* all changes: */	_average=_local_img->left + _local_img->right;	memcpy (_reference_image->image, _local_img->image,_img_size);	_reference_image->x=_local_img->x;	_reference_image->y=_local_img->y;	_reference_image->depth=_local_img->depth;	_reference_image->left=_local_img->left;	_reference_image->right=_local_img->right;	return (_average); /* returns the count of pixels changed beyond the tolerance ( full elements ) */}																		      

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -