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

📄 main.c

📁 基于V4L开发的一个运动监测的程序
💻 C
📖 第 1 页 / 共 2 页
字号:
	// compute new avg intensity for the reference buffer	for ( p1 = &ref_buf[0]; p1 < &ref_buf[0]+sizeof(ref_buf); p1++ )	{		avg += *p1;	}	avg /= sizeof(ref_buf);//	printf("reference image avg intensity = %u\n",avg);	avg_ref_intensity = (unsigned char)avg;	}//=====================================================================// routine to subtract downsized image from the reference image// this will give us an image with only the changes showing// its not quite a simple subtraction, we look at each color and// look for color changes as well. Significantly changed pixels are// set to bright white. Result is a b/w image with additional// blob filtering to look for areas of change (marked as red pixels).// Each blob is a pixel surrounded by 8 neighbors//=====================================================================float do_motion_analysis(void){	int x,y;	unsigned char *pdest;	unsigned char *psrc;	unsigned char *pref;	unsigned char red;	unsigned char green;	unsigned char blue;	unsigned char cresult;	float  fresult = 0.0f;	int		pixcnt;	unsigned char threshold;	int    blob_cnt;	int i;	    time_t      t;    struct tm  *tm;    char        line[128];	static	int image_cnt = 0;		// used to force saves on periodic basis	int context;	char sbuf[256];	static int first = 1;    char *cp;    char **toks;    char *new_cmd;            		// on the first pass, we dont have a ref image stored yet so	// we cannot do a difference that is meaningful.	if ( first == 1 )	{		first = 0;		return 0.0;	}		alarm_zone.x1 = 640;			// init bounding box of alarm blobs	alarm_zone.x2 = -1;	alarm_zone.y1 = 480;	alarm_zone.y2 = -1;//	printf("new image is %s, %u %u %u\n"),//			( avg_ds_intensity <= avg_ref_intensity ) ? "darker or ==" : "lighter",//			avg_ds_intensity, avg_ds1_intensity, avg_ref_intensity);		pref  = &ref_buf[0];			psrc  = &ds1_buf[0];	// intensity corrected buffer	pdest = &res_buf[0];		for (y=0; y<240; y++)	{		for (x=0; x<320; x++)		{					// give the cpu something to do...			// compute rms diff between all pixels			// detection of color or intensity changes detected			red = (*pref > *psrc) ? *pref- *psrc : *psrc- *pref;	// red			pref++; psrc++;			green = (*pref > *psrc) ? *pref- *psrc : *psrc- *pref;;	// green			pref++; psrc++;			blue  = (*pref > *psrc) ? *pref- *psrc : *psrc- *pref;;	// blue			pref++; psrc++;			cresult = sqrt((red*red + green*green + blue*blue)/3);			*pdest++ = cresult;		// make b/w image			*pdest++ = cresult;			*pdest++ = cresult;			fresult += (float)cresult;		}	}	// calculate normalized difference over picture	fresult = fresult/(float)(320*240);		// detect and mark pixels that are significantly different	threshold = (unsigned char)sig_pix_threshold;	pixcnt = 0;	psrc  = &res_buf[0];	while ( psrc < res_buf+sizeof(res_buf))	{		if ( *psrc > threshold )		{			pixcnt++;			*psrc = 255;		// alarm active areas in white			*(psrc+1) = 255;			*(psrc+2) = 255;		}					psrc += 3;			// only need to look at reds of each pixel							// because g and b are set to the same thing				}		// to eliminate small changes (wind blown objects) from causing so much	// havoc, we will try to eliminate false alarms by scanning for blobs		// A blob is a 3x3 pixel area, all must be 'hot' (white)	blob_cnt = 0;	psrc  = res_buf + 320 * 3;	while ( psrc < (res_buf+sizeof(res_buf)-320*3))	{		for (i=0;i<1;i++)		{			if (*psrc < 255) break;			// central pixel must be lite			if (*(psrc-320*3) < 255) break;	// pixel above must be lite			if (*(psrc+320*3) < 255) break;	// pixel below must be lite			if (*(psrc-3) < 255) break;		// pixel to left must be lite			if (*(psrc+3) < 255) break;		// pixel to right must be light			if (*(psrc-320*3+3) < 255) break;		// pixel to  NE must be light						if (*(psrc-320*3-3) < 255) break;		// pixel to  NW must be light									if (*(psrc+320*3+3) < 255) break;		// pixel to  SE must be light									if (*(psrc+320*3-3) < 255) break;		// pixel to  SW must be light									// mark blob as blob on screen			*(psrc+2) = 0;	// shut off blue			*(psrc+1) = 0;  // shut off green			blob_cnt++;			x = ((psrc - res_buf) % (320 * 3))/3;			y = (psrc - res_buf) / (320 * 3);			if ( x < alarm_zone.x1 )		// set first occurance location				alarm_zone.x1 = x;			if ( alarm_zone.x2 < x )		// keep highest occurance				alarm_zone.x2 = x;						if ( y < alarm_zone.y1 )		// set first occurance location				alarm_zone.y1 = y;			if ( alarm_zone.y2 < y )		// keep highest occurance				alarm_zone.y2 = y;					}		psrc += 3;	}	// label main view with time/date location stamp (display and filesave)	if (blob_cnt > alarm_threshold)	{		alarm_pix++;        if ( show_target_box )		    mark_alarm_zone(&alarm_zone);			// box in alarm window		add_rgb_text(rgb_buf,640,480, 1);		// red text lable on pix//		if (beep_on_alarm)						// wakeup the operator//			beep();	}	else		add_rgb_text(rgb_buf,640,480, 0);		// white text label on pix					image_cnt++;	// save image on motion or every xxx pictures	if (( blob_cnt > alarm_threshold ) || 		((image_cnt % periodic_save_interval) == 0))	{    	time(&t);    	tm = localtime(&t);    	strftime(line,sizeof(line)-1,"CSPY%H%M%S.jpg",tm);			put_image_jpeg(line, rgb_buf, 640, 480, 80);	}        // on each alarm, execute a user command    if (( blob_cnt > alarm_threshold ) &&        ( strlen(alarm_command) > 1 ) )    {        if ((cp = strstr(alarm_command,"%f%")) == NULL)            // no filename substitution required in user provided string            system(alarm_command);//        else//        {//            // user put filename(s) in command line using %f%, then we need//            // to insert the current filename into the user command string////            toks = g_strsplit(alarm_command,"%f%",0);//            new_cmd = g_strjoinv(full_name,toks);//           system(new_cmd);//            free(new_cmd);//            g_strfreev(toks);//        }    }    	return fresult;}/* * read rgb image from v4l device * return: mmap'ed buffer and size * * sample call: *	int size; *	char *image; *  int dev = v4l_open(VIDEO_DEV, IN_DEFAULT); *	image = get_image (dev, width, height, input, norm, palette, &size); *	// process rgb image buffer as required here *	// then dont forget to release buffers *	if (size) *		munmap(image, size); *	else if (image) *		free(image); *  v4l_close(dev);*/char *get_image(int dev, int width, int height, int input,int norm,int fmt,int *size){	struct video_capability vid_caps;	struct video_mbuf vid_buf;	struct video_mmap vid_mmap;	struct video_channel vid_chnl;	char *map = NULL;	int len;		*size = 0;		// keep caller happy on error returns	                // setting input = 1 gets some users going	if (ioctl (dev, VIDIOCGCAP, &vid_caps) == -1) 	{		printf("ioctl (VIDIOCGCAP) failed\n");		return (NULL);	}	if (input != IN_DEFAULT) 	{		vid_chnl.channel = -1;		if (ioctl (dev, VIDIOCGCHAN, &vid_chnl) == -1) 		{			printf("ioctl (VIDIOCGCHAN) failed\n");		} 		else 		{			vid_chnl.channel = input;			vid_chnl.norm    = norm;			if (ioctl (dev, VIDIOCSCHAN, &vid_chnl) == -1) 			{				printf("ioctl (VIDIOCSCHAN) failed");				return (NULL);			}		}	}		// if no video buffer set, then set it	//printf("before VIDIOCGMBUF vidbuf size=%d bytes\n",vid_buf.size);		if (ioctl (dev, VIDIOCGMBUF, &vid_buf) == -1) 	{		//printf("after VIDIOCGMBUF vidbuf size=%d bytes\n",vid_buf.size);				// to do a normal read()		map = malloc (width * height * 3);		len = read (dev, map, width * height * 3);		if (len <=  0) 		{			free (map);			return (NULL);		}		*size = 0;		return (map);	}	map = mmap (0, vid_buf.size, PROT_READ|PROT_WRITE,MAP_SHARED,dev,0);	if ((unsigned char *)-1 == (unsigned char *)map) 	{		printf("mmap() failed \n");		return (NULL);	}	vid_mmap.format = fmt;	vid_mmap.frame = 0;	vid_mmap.width = width;	vid_mmap.height =height;//printf("VIDIOCMCAPTURE started\n");	if (ioctl (dev, VIDIOCMCAPTURE, &vid_mmap) == -1) 	{		printf("VIDIOCMCAPTURE failed\n");		munmap (map, vid_buf.size);		return (NULL);	}//printf("VIDIOCSYNC started\n");	if (ioctl (dev, VIDIOCSYNC, &vid_mmap) == -1) 	{		printf("VIDIOCSYNC failed \n");		munmap (map, vid_buf.size);		return (NULL);	}//printf("VIDIOCSYNC finished %d bytes\n",vid_buf.size);		// vid_buf.size is actually the size of 2 frame buffers in the driver	*size = vid_buf.size;	return (map);}/* *  int v4l_open(char *device) *	example call  int dev = v4l_open(VIDEO_DEV); * * */int v4l_open(char *device){	int dev = -1;	int max_try = 5;	/* we try 5 seconds/times to open the device */	/* open the video4linux device */	while (max_try) 	{		dev = open (device, O_RDWR);		if (dev == -1) 		{			if (!--max_try) 			{				fprintf (stderr, "Can't open device %s\n", device);				exit (0);			}			sleep (1);		} 		else 		{			break;		}	}		return dev;}/* *  void v4l_close(int dev) *	example call  v4l_close(dev); * */void v4l_close(int dev){	if (dev > 0)		close(dev);}int main( int argc, char *argv[] ){	int size;	char *image;	char tmp;	char *img_ptr;	int cnt;    // used to store supported webcam palette mode    struct video_picture v_pict;    	v_pict.palette=0;					// mark supported palette unknown	dev = v4l_open(video_device);		// open the camera device	if (dev <= 0)	{		printf("Unable to use v4l camera device... open failed???");			return TRUE;	}	if(!v_pict.palette)	{		// get palette info		if(ioctl(dev, VIDIOCGPICT, &v_pict)==-1)		{			printf("Unable to get picture properties from webcam (VIDIOCGPICT failed)\n");			return TRUE;		}		if(v_pict.palette!=VIDEO_PALETTE_YUV420P && v_pict.palette!=VIDEO_PALETTE_RGB24)		{			// try to switch to RGB24 palette			v_pict.palette=VIDEO_PALETTE_RGB24;			if(ioctl(dev, VIDIOCSPICT, &v_pict)==-1)			{				// try to switch to YUV420P palette				printf("RGB24 not supported, trying YUV420P...\n");				v_pict.palette=VIDEO_PALETTE_YUV420P;				if(ioctl(dev, VIDIOCSPICT, &v_pict)==-1)				{					printf("YUV420P not supported. Unable to use this device\n");					return TRUE;				}			}					}	}	    for (;;)    {        //grab a v4l frame        	    image = get_image(dev,640,480,IN_DEFAULT,NORM_NTSC,v_pict.palette,&size);	    if ( image )	    {		    if(v_pict.palette==VIDEO_PALETTE_YUV420P)		        //YUV420P palette format			    ccvt_420p_rgb24(640,480,image,image+(640*480),image+(640*600),rgb_buf);		    else		    //BGR24 palette format		    {			    // grab a static memory copy for use in calcs and redraws			    memcpy(rgb_buf,image,sizeof(rgb_buf));			    // v4l returns bgr not rgb, so we need to swap red and blue			    // for our display			    img_ptr = rgb_buf;					    for (cnt=0; cnt < 640*480; cnt++)			    {				    tmp = img_ptr[0];			// get blue for safe keeping				    img_ptr[0] = img_ptr[2];	// move red into correct place				    img_ptr[2] = tmp;			// park blue in correct place				    img_ptr += 3;				// bump to next triplet			    }		    }        }	    else		    printf("image capture failed\n");		    // then dont forget to release buffers	    if (size)    	    munmap(image, size);	    else 	    if (image)    	    free(image);        down_sample_image();		// convert 640x480 pix to 320x240 in ds_buf	    do_motion_analysis();		// check difference between ds_buf and ref_buf		    update_reference_image();	// avg ds_buf into ref_buff                sleep( picture_interval );     }	    }

⌨️ 快捷键说明

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