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

📄 main.c

📁 基于V4L开发的一个运动监测的程序
💻 C
📖 第 1 页 / 共 2 页
字号:
// main.c// This is a quick and dirty console version of gspy that does not use X or// gnome libraries. Its primary use is on servers that may have no user// interface. The only non standard library you may need to install is libjpeg// see http://www.rpmfind.net/linux/rpm2html/search.php?query=libjpeg// There is one x86 assembler file used for converting image formats. This could be // eliminated if your webcam kernel driver provides RGB data format.// Build this file using   cc -o cspy -ljpeg -lm main.c ccvt.S// the executable will be called cspy/* Copyright (C) 1998 Lawrence Glaister VE7IT <ve7ot@shaw.ca>  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 <stdio.h>#include <stdlib.h>#include <sys/ioctl.h>#include <sys/mman.h>		// for munmap declarations#include <linux/videodev.h>#include <time.h>#include <string.h>#include <jpeglib.h>#include <fcntl.h>#include <errno.h>#include <math.h>#define DEF_WIDTH	640#define DEF_HEIGHT	480#define IN_TV			0#define IN_COMPOSITE	1#define IN_COMPOSITE2	2#define IN_SVIDEO		3#define IN_DEFAULT		8#define NORM_PAL		0#define NORM_NTSC		1#define NORM_SECAM		2#define NORM_DEFAULT	0#define TRUE 1#define FALSE 0#define QUAL_DEFAULT	80	// jpeg quality factorstruct alarm_zone{	int x1;						// 0..319 1st pixel with alarm blob	int x2;						// 0..319 last pixel with alarm blob	int y1;						// 0..239 1st pixel with alarm blob	int y2;						// 0..239 last pixel with alarm blob};static unsigned char rgb_buf[3*640*480];	// main 640x480 live display image bufferstatic unsigned char ds_buf[3*320*240];	    // temp for downsized live imagestatic unsigned char ds1_buf[3*320*240];	// temp for downsized live image corrected for avg intensitystatic unsigned char ref_buf[3*320*240];	// temp for reference picture buffer (time averaged)static unsigned char res_buf[3*320*240];	// temp for motion analysis picture buffer (graphical results)struct video_picture v_pict;		// used to store prefered webcam palettechar full_name[350];        // a hack!. full path/filename of last written picturechar image_directory[1024];	// where the jpg's get putchar image_label[] = {"Room 204 %Y-%m-%d %H:%M:%S"};			// used by strftime to date stamp imagechar video_device[] = {"/dev/video0"};		// opened to read images via v4lint picture_interval = 2;			// seconds between picturesfloat ref_update_fraction = 0.2;	// amount a new image contributes to								    // reference image each cycleint alarm_threshold = 70;			// percent of graph for alarmfloat sig_pix_threshold = 25.0;		// amount pixel must be different								    // (x*avg difference)		int periodic_save_interval = 300;	// force a save every xx snapshots//int beep_on_alarm = TRUE;		    // console beep on alarmint show_target_box = TRUE;         // puts active area on pictureschar alarm_command[] = {"echo CSPY -- Motion Detected"}; // user command to execute on alarmsint dev;						// handle for v4l video camera devicestruct alarm_zone alarm_zone;unsigned int  	avg_ref_intensity;unsigned int	avg_ds_intensity;unsigned int	avg_ds1_intensity;unsigned int	alarm_pix = 0;int  v4l_open(char *device);void v4l_close(int dev);char *get_image(int dev,  int width, int height,                int input,int norm,  int fmt, int *size);/* ---------------------------------------------------------------------- * This routine extracted and modified from webcam project by Gerd Knorr * (c) 1998-2000 Gerd Knorr * Modified for colored text by L.P. Glaister July 2000*/ # define CHAR_HEIGHT  11# define CHAR_WIDTH   6# define CHAR_START   4# include "font_6x11.h"void add_rgb_text(char *image, int width, int height, int alrm){    time_t      t;    struct tm  *tm;    char        line[128],*ptr;    int         i,x,y,f,len;	    time(&t);    tm = localtime(&t);    len = strftime(line,127,image_label,tm);    for (y = 0; y < CHAR_HEIGHT; y++) 	{		// locate text in lower left corner of image		ptr = image + 3 * width * (height-CHAR_HEIGHT-2+y) + 12;							// loop for each character in the string		for (x = 0; x < len; x++) 		{	    	// locate the character in the fontdata array			f = fontdata[line[x] * CHAR_HEIGHT + y];						// loop for each column of font data	    	for (i = CHAR_WIDTH-1; i >= 0; i--) 			{				// write a black background under text				// comment out the following block to get white letters on picture background	    		ptr[0] = 0;	    		ptr[1] = 0;		    	ptr[2] = 0;				if (f & (CHAR_START << i)) 				{					if (alrm)					{						// red text		    			ptr[0] = 255;		    			ptr[1] = 64;		    			ptr[2] = 64;					}					else					{						// white text		    			ptr[0] = 255;		    			ptr[1] = 255;		    			ptr[2] = 255;					}							}				ptr += 3;	    	}		}    }}/* */void put_image_jpeg(char *filename, char *image, int width, int height, int quality){	int y, line_width;	JSAMPROW row_ptr[1];	struct jpeg_compress_struct cjpeg;	struct jpeg_error_mgr jerr;	char *line;	FILE *fp;    time_t      t;    struct tm  *tm;    int         len;	char dir_name[350];		// create the directory name as a combination of the user selected prefix + year,month,day	sprintf(full_name,"%s%%Y%%m%%d/",image_directory);	    time(&t);    tm = localtime(&t);    len = strftime(dir_name,sizeof(dir_name)-1,full_name,tm);		// make the directory that user wants pictures stored in to insure it exists	// you may want to make dir permission 0700, so other users cannot see pix	if (-1 == mkdir(dir_name,0777))	{		if (errno != EEXIST )		{			perror("put_image_jpeg() Unable to create file save directory");		}	}		strncpy(full_name,dir_name,sizeof(full_name)-1);	strncat(full_name,filename,sizeof(full_name)-strlen(full_name)-1);		line = malloc (width * 3);	if (!line)		return;		    if ((fp = fopen(full_name, "wb")) == NULL)     {	    fprintf(stderr, "can't open %s for binary write", full_name);		perror(" and the reason is");	    return;    }   //    fprintf(stderr, "   writing image to %s\n", full_name);    cjpeg.err = jpeg_std_error(&jerr);  // errors get written to stderr 	jpeg_create_compress (&cjpeg);	cjpeg.image_width = width;	cjpeg.image_height= height;	cjpeg.input_components = 3;	cjpeg.in_color_space = JCS_RGB;	jpeg_set_defaults (&cjpeg);	jpeg_set_quality (&cjpeg, quality, TRUE);	cjpeg.dct_method = JDCT_FASTEST;//	jpeg_stdio_dest (&cjpeg, stdout);    jpeg_stdio_dest (&cjpeg, fp);  	  // data written to file	jpeg_start_compress (&cjpeg, TRUE);	row_ptr[0] = line;	line_width = width * 3;	for ( y = 0; y < height; y++) 	{		memcpy(line,image,line_width);		jpeg_write_scanlines (&cjpeg, row_ptr, 1);		image += line_width;	}	jpeg_finish_compress (&cjpeg);	jpeg_destroy_compress (&cjpeg);	free (line);		if (fp)	{		fflush(fp);		fclose(fp);	}}//=====================================================================// given a box containing the alarm window, modify pixels in main// display window to show box. Note main display is displayed at twice// the x and y dimensions so scaling of the alarm_zone is required.//=====================================================================void mark_alarm_zone( struct alarm_zone *zone ){	int x,y;	char *p1,*p2;	if (zone->x1 < 0 || zone->x2 < 0 || zone->y1 < 0 || zone->y2 < 0 )		return;	if (zone->x1 > 639 || zone->x2 > 639 || zone->y1 > 479 || zone->y2 > 479 )		return;			p1 = rgb_buf + (zone->y1 * 2)*640*3;	p2 = rgb_buf + (zone->y2 * 2)*640*3;	for( x = 0; x < 640; x++)	{		*p1 = ~*p1;			// invert red component		*(p1+1) = ~*(p1+1);	// invert green		*(p1+2) = ~*(p1+2);	// invert blue		*p2 = ~*p2;			// draw both horizontal lines		*(p2+1) = ~*(p2+1);		*(p2+2) = ~*(p2+2);			p1 += 3;		p2 += 3;	}	p1 = rgb_buf + (zone->x1 * 2)*3;	p2 = rgb_buf + (zone->x2 * 2)*3;		for( y = 0; y < 480; y++)	{		*p1 = ~*p1;			// invert red component		*(p1+1) = ~*(p1+1);	// invert green		*(p1+2) = ~*(p1+2);	// invert blue		*p2 = ~*p2;			// draw both vertical lines		*(p2+1) = ~*(p2+1);		*(p2+2) = ~*(p2+2);					p1 += 640*3;		p2 += 640*3;		}}//=====================================================================// convert 640x480 picture down to 320x240// use pixel averaging for best quality instead of subsampling// 2 output buffers are filled...// ds_buf[] has the downsampled image// ds1_buf[] has a copy of the downsampled image corrected for// 	intensity to make its avg intensity match the reference image//=====================================================================void down_sample_image(void){	int x,y;	unsigned char *p0;	unsigned char *p1;	unsigned char *p2;	unsigned char *p3;	unsigned char *p4;	unsigned char *pdest;	unsigned int   avg = 0;	unsigned char correction;		pdest = &ds_buf[0];	for (y=0; y< 240; y++)	{		p1 = rgb_buf + (y*2) * 640 * 3;		// upper left cell		p2 = p1 + 3;			            // upper right cell		p3 = p1 + (640 * 3);				// lower left cell		p4 = p3 + 3;						// lower right cell		for (x=0; x<320; x++)		{			*pdest++ = (*p1++ + *p2++ + *p3++ + *p4++) / 4;	//red cells avg			*pdest++ = (*p1++ + *p2++ + *p3++ + *p4++) / 4;	//grn cells avg			*pdest++ = (*p1++ + *p2++ + *p3++ + *p4++) / 4;	//blu cells avg			p1 += 3;			p2 += 3;			p3 += 3;			p4 += 3;		}	}		for ( p1 = &ds_buf[0]; p1 < &ds_buf[0]+sizeof(ds_buf); p1++ )	{		avg += *p1;	}	avg /= sizeof(ds_buf);	avg_ds_intensity = avg;//    printf("downsampled image avg intensity = %u\n",avg);	// now generate an intensity normalized image	p0 = &ds_buf[0];	p1 = &ds1_buf[0];	if (avg_ds_intensity < avg_ref_intensity)	{		correction = avg_ref_intensity - avg_ds_intensity;//		printf("making image lighter by %d\n",correction);				// make ds1 image brighter to match ref image		for ( ; p1 < &ds1_buf[0]+sizeof(ds1_buf);p1++,p0++ )		{			*p1 = *p0 + correction;			// fix up overflows			if ( *p1 < *p0 ) *p1 = 255;		}	}	else if(avg_ds_intensity == avg_ref_intensity)	{		// make exact copy//		printf("no image correction required\n");				memcpy(p1,p0,sizeof(ds1_buf));	}		else if(avg_ds_intensity > avg_ref_intensity)	{		correction = avg_ds_intensity - avg_ref_intensity;//		printf("making image darker by %d\n",correction);		// make ds1 image darker to match ref image		for (; p1 < &ds1_buf[0]+sizeof(ds1_buf); p1++,p0++ )		{			*p1 = *p0 - correction;			// fix up underflows			if ( *p1 > *p0 ) *p1 = 0;		}		}		// for debug, its nice to know the avg intensity of the corrected buffer	// it should be close to the ref buffer unless clipping occured due to	// saturation at 0 or 255 limits	for ( p1 = &ds1_buf[0]; p1 < &ds1_buf[0]+sizeof(ds1_buf); p1++ )	{		avg += *p1;	}	avg /= sizeof(ds1_buf);	avg_ds1_intensity = avg;}//=====================================================================// This procedure adds some of the new image in with lots of the old // image. This gives us a long time constant average reference picture.// This allows the system to adapt to new items in the image over time// but still alarm again if they move in the picture. Also, changing// lighting conditions are less of a problem.//=====================================================================void update_reference_image(void){	int x,y;	unsigned char *pdest;	unsigned char *psrc;	float old;	unsigned int avg = 0;	unsigned char *p1;	static int first = 1;		if ( first == 1 )	{		// on first pass, the first picture becomes the reference picture		memcpy(ref_buf,ds_buf,sizeof(ref_buf));		first = 0;	}	else	{				// now update reference buffer by using some of old image and some of new		psrc  = &ds_buf[0];		pdest = &ref_buf[0];			old = 1.0 - ref_update_fraction;		for (y=0; y<240; y++)		{			for (x=0; x<320; x++)			{				// give the fpu something to do...				*pdest++ = old * *pdest + ref_update_fraction * *psrc++ + 0.5;	// red				*pdest++ = old * *pdest + ref_update_fraction * *psrc++ + 0.5;	// green				*pdest++ = old * *pdest + ref_update_fraction * *psrc++ + 0.5;	// blue			}		}	}

⌨️ 快捷键说明

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