/* * FlurCam v0.1 * ~~~~~~~~~~~~~~ * * Author: Mario Kicherer < http://empanyc.net > * * v0.1 released: 21.05.2005 * * Dependencies: * * SDL - http://www.libsdl.org/index.php (only needed with gui output, see SDL flag) * * jpeglib - for JPEG output * * Thanks to: * * the videodog project ( http://paginas.terra.com.br/informatica/gleicon/video4linux/videodog.html ) * * Usage: * * flurcam -d v4l_device -o count_offset -p directory * * Compile: * * gcc (-lSDL) -ljpeg flurcam.c -o flurcam (-lSDL only if a gui is wanted) * */ // if you wish a gui, compile with SDL #define SDL #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef SDL #include #endif #define DOT fprintf(stderr,"."); //// definitions //////////////////////////////////////// // settings char destination[128] = "final/"; unsigned char *v_device = "/dev/video0"; /* device */ int x=640,y=480,w=3,isize; // width,height,depth,size of raw picture int ystart=320,ymax=20; //hotspot: startline from top, endline from bottom int mpeak=25,mmax=50; // peak level of difference, maximum count of peaks int status=0; // 0 = no motion;1 = motion; 2= wait on motion end int interval=300; // grab interval int bsobel=0; // show sobelfilter 0/1 int brating=0; // show rating image 0/1 int btesting=0; // test mode 0/1 int debl=1; // debug level //// internal //// // motion related time_t mstart=0,mend=0; int mtimeout=10; unsigned char *firsti,*lasti, *rating; // SDL #ifdef SDL SDL_Surface *screen; SDL_Event event; #endif // V4L static struct video_picture grab_pic; static struct video_capability grab_cap; static struct video_channel grab_vid; /* escolher canal e NTSC */ static struct video_mmap grab_buf; static int grab_fd, grab_size; static unsigned char *grab_data; unsigned char *fin_data,*prev_data; char tverz[20]; int ende=0; int ctmp=-1; //// Code ///////////////////////////////////////////////// void addlog(char *tolog,int debuglevel) { if (debl >= debuglevel) { time_t rawtime; struct tm *timeinfo; time(&rawtime); timeinfo = (struct tm *) localtime (&rawtime); char bewf[128]; strftime(bewf,128,"[%Y-%m-%d][%H:%M:%S]",timeinfo); printf("%s %s \n",bewf,tolog); } } void swap_rgb24(unsigned char *mem, int n) { unsigned char c; unsigned char *r,*g,*b; int i; r = mem; g = r+1; b = g+1; for (i=0;i mpeak) { switch (i % 3) { case (0) : *idest=255;*(idest+1)=255;*(idest+2)=255; i+=2;idest+=3;idiff+=3;continue; break; case (1) : *idest=255;*(idest+1)=255;*(idest-1)=255; i+=1;idest+=2;idiff+=2;continue; break; case (2) : *idest=255;*(idest-1)=255;*(idest-2)=255; break; } //*idest = j; } idest++; idiff++; } } void diff2(unsigned char *dest_data, unsigned char *diff_data) { unsigned char *idiff,*idest; int dr,dg,db,d; idiff = diff_data+ystart; idest = dest_data+ystart; int i; for (i=0;i < isize-ystart-ymax; i+=3) { dr = abs(*idest - *idiff); dg = abs(*(idest+1) - *(idiff+1)); db = abs(*(idest+2) - *(idiff+2)); d = (dr+dg+db)/3; if ((abs(d-dr) >= mpeak) | (abs(d-dg) >= mpeak) | (abs(d-db) >= mpeak) | (d > mpeak)) { switch (i % 3) { case (0) : *idest=0;*(idest+1)=255;*(idest+2)=0; i+=2;idest+=3;idiff+=3;continue; break; case (1) : *idest=255;*(idest+1)=0;*(idest-1)=0; i+=1;idest+=2;idiff+=2;continue; break; case (2) : *idest=0;*(idest-1)=255;*(idest-2)=0; break; } //*idest = j; } idest+=3; idiff+=3; } } void sobel(unsigned char *dest_data, unsigned char *source_data) { unsigned char *d_i,*d_o,*d_u,*d_l,*d_r, *t_i; int i,j,dx,dy,os; t_i = dest_data+ystart; os = x*w; d_i = source_data+ystart+os; d_o = source_data+ystart; d_l = source_data+ystart+os-w; d_r = source_data+ystart+os+w; d_u = source_data+ystart+2*os; for (i=0;i < isize-(ystart+ymax); i++) { dx = 2*(*(d_r)) + *(d_o+w) + *(d_u+w) - 2*(*(d_l)) - *(d_o-w) - *(d_u-w); dy = *(d_o-w) + 2*(*d_o) + *(d_o+w) - *(d_u-w) - 2*(*d_u) - *(d_u+w); j = (abs(dx)+abs(dy))/3; if (j>255) j=255; switch (i % 3) { case (0) : *t_i=j;*(t_i+1)=j;*(t_i+2)=j; i+=2;t_i+=3;d_i+=3;d_o+=3;d_u+=3;d_l+=3;d_r+=3;continue; break; case (1) : *t_i=j;*(t_i+1)=j;*(t_i-1)=j; i+=1;t_i+=2;d_i+=2;d_o+=2;d_u+=2;d_l+=2;d_r+=2;continue; break; case (2) : *t_i=j;*(t_i-1)=j;*(t_i-2)=j; break; } t_i++;d_i++;d_o++;d_u++;d_l++;d_r++; } } int motion(unsigned char *actual, unsigned char *prev,int peak, int max) { int i, df,ch=0; unsigned char *ai,*pi; ai = actual+ystart; pi = prev+ystart; for (i=0;i < isize-(ystart+ymax); i++) { df = abs(*ai - *pi); if (df >= peak) { ch++; } if (ch >= max) i = isize-(ystart+ymax)-1; ai++; pi++; } if (ch >= max) {return 1;} else {return 0;} } int motion2(unsigned char *actual, unsigned char *prev,int peak, int max) { int i, dr,dg,db,ch=0,d; unsigned char *ai,*pi,*ri; ai = actual+ystart; pi = prev+ystart; ri = rating+ystart; for (i=0;i < (isize-(ystart+ymax)); i+=3) { dr = abs(*ai - *pi); dg = abs(*(ai+1) - *(pi+1)); db = abs(*(ai+2) - *(pi+2)); d = (dr+dg+db)/3; if ((abs(d-dr) >= peak) | (abs(d-dg) >= peak) | (abs(d-db) >= peak) | (d > peak)) { if (*ri == 255) { // vorläufig ch++; } } if (ch >= max) i = isize-(ystart+ymax)-1; ai+=3; pi+=3; ri+=3; } if (ch >= max) {return 1;} else {return 0;} } void draw(unsigned char* data) { unsigned char *iodata,*ibdata; time_t ztime; time_t rawtime; struct tm *timeinfo; char bewf[128], fin[128]; fin_data = memcpy(fin_data,data,isize); if ((motion2(fin_data,prev_data,mpeak,mmax) == 1) | (btesting==1)) { // motion if (status == 0) { time(&mstart); addlog("Motion detected",1); firsti = memcpy(firsti,prev_data,isize); ctmp++; sprintf(tverz,"temp/set%i/",ctmp); if (mkdir(tverz,0755) == -1) perror(tverz); status=1; } if (status == 2) { status=1; addlog("Resume",1); } time(&rawtime); timeinfo = (struct tm *) localtime (&rawtime); strftime(bewf,128,"o3FlurCam %Y-%m-%d %H:%M:%S",timeinfo); sprintf(fin,"%s%s",tverz,bewf); if (btesting==0) save_jpg(fin,data); if (debl > 0 ) fprintf(stderr,"."); if (bsobel==1) sobel(fin_data,data); if (brating==1) { blend(fin_data,rating,1); } #ifdef SDL screen->pixels = fin_data; SDL_UpdateRect(screen,0,0,0,0); #endif } else { // motion has ended if (status == 1) { time(&mend); status = 2; if (debl > 0 ) fprintf(stderr,"\n"); addlog("Motion ended",1); lasti = memcpy(lasti,data,isize); } if (status == 2) { time(&ztime); if (ztime >= mend+mtimeout) { status=0; addlog("Motion timeout. ",1); sprintf(fin,"%so3FlurCam First",tverz); save_jpg(fin,firsti); sprintf(fin,"%so3FlurCam Last",tverz); save_jpg(fin,lasti); diff2(firsti,lasti); sprintf(fin,"%so3FlurCam Diff",tverz); save_jpg(fin,firsti); if (motion2(firsti,lasti,mpeak,mmax) == 1) { // if (1==1) { time(&rawtime); timeinfo = (struct tm *)localtime (&rawtime); strftime(bewf,128,"%Y-%m-%d/",timeinfo); sprintf(fin,"%s%s",destination,bewf); mkdir(fin,0755); strftime(bewf,128,"%Y-%m-%d/%H_Uhr/",timeinfo); sprintf(fin,"%s%s",destination,bewf); mkdir(fin,0755); strftime(bewf,128,"%Y-%m-%d/%H_Uhr/",timeinfo); sprintf(fin,"mv %s %s%s",tverz,destination,bewf); system(fin); if (debl > 0 ) { time(&rawtime); timeinfo = (struct tm *) localtime (&rawtime); sprintf(fin,"Difference detected, save images in %sset%i/\n",bewf,ctmp); addlog(fin,1); } } else { sprintf(fin,"rm -r %s",tverz); system(fin); ctmp--; if (debl > 0 ) { time(&rawtime); timeinfo = (struct tm *) localtime (&rawtime); sprintf(fin,"No difference detected\n"); addlog(fin,1); } } } } } prev_data = memcpy(prev_data,data,isize); #ifdef SDL screen->pixels = NULL; #endif } int grab_init() { if ((grab_fd = open(v_device,O_RDWR)) == -1 ) { perror("open videodev"); perror(v_device); exit(1); } if (ioctl(grab_fd,VIDIOCGCAP,&grab_cap) == -1) { fprintf(stderr,"wrong device\n"); exit(1); } memset (&grab_pic, 0, sizeof(struct video_picture)); if (ioctl (grab_fd, VIDIOCGPICT, &grab_pic) == -1) { fprintf (stderr, "no pict"); exit(1); } switch (w) { case 1: grab_buf.format = VIDEO_PALETTE_GREY; break; case 2: grab_buf.format = VIDEO_PALETTE_RGB565; break; case 3: default: grab_buf.format = VIDEO_PALETTE_RGB24; break; } grab_buf.frame = 0; grab_buf.width = x; grab_buf.height = y; grab_size = x * y * w; grab_data = mmap(0,grab_size,PROT_READ|PROT_WRITE,MAP_SHARED,grab_fd,0); return(1); } unsigned char* grab_one(int *width, int *height) { for (;;) { if (-1 == ioctl(grab_fd,VIDIOCMCAPTURE,&grab_buf)) { perror("ioctl VIDIOCMCAPTURE");exit(-1); } else { if (-1 == ioctl(grab_fd,VIDIOCSYNC,&grab_buf)) { perror("ioctl VIDIOCSYNC");exit(-1); } else { *width = grab_buf.width; *height = grab_buf.height; return grab_data; } } } } void main_loop() { while(ende == 0) { draw(grab_one(&x,&y)); #ifdef SDL SDL_Delay(interval); while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_KEYDOWN: if (event.key.keysym.sym == SDLK_ESCAPE) { ende=1; } else if (event.key.keysym.sym == 's') { if (bsobel==1) {bsobel = 0;} else {bsobel=1;} } else if (event.key.keysym.sym == 'r') { if (brating==1) {brating = 0;} else {brating=1;} } if (event.key.keysym.sym == 't') { if (btesting==1) {btesting = 0;} else {btesting=1;} } break; case SDL_QUIT: ende=1; break; } } #endif } } int main (int argc, char **argv) { int c; signal (SIGINT, _sighandler); while ((c = getopt (argc, argv, "d:o:p:")) != EOF) switch (c) { case 'd': // set device v_device= (char *)malloc ((strlen(optarg) * sizeof(char))+1); memset(v_device, 0, strlen(optarg)); strncpy(v_device, optarg, strlen(optarg) ); break; case 'o': // offset of picturesets ctmp = atoi(optarg); break; case 'p': // destination path strncpy(destination, optarg, strlen(optarg) ); break; } isize = x*y*w; prev_data = malloc(isize); fin_data = malloc(isize); firsti = malloc(isize); lasti = malloc(isize); rating = malloc(isize); ystart = ystart*x*w; ymax = ymax*x*w; status=0; if (load_pnm("rating.pnm",rating) == -1) { memset(rating,0,isize); unsigned char *ri; ri = rating+ystart; for (c=0;c < (isize-(ystart+ymax)); c++) { *ri = 255; *ri++; } save_pnm("rating",rating); } printf("FlurCam v0.1 by anYc (M. Kicherer)\n\n"); printf("Width: %i Height: %i Width: %i\n",x,y,w); printf("Interval: %i\n\n",interval); mkdir("temp/",755); mkdir(destination,755); ///// dirty - to be replaced system("echo asd >> temp/temp"); system("rm -r temp/*"); //////////////// SDL #ifdef SDL Uint32 bgrab_flags; bgrab_flags = SDL_DOUBLEBUF; if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) { fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError()); exit(1); } atexit(SDL_Quit); screen = SDL_SetVideoMode(x, y, w*8, bgrab_flags); if ( screen == NULL ) { fprintf(stderr, "Couldn't set %dx%dx%d bgrab mode: %s\n", x, y, w*8, SDL_GetError()); exit(1); } SDL_WM_SetCaption("FlurCam", "flurcam"); #endif ////////////////////V4l grab_init(); // set_picture(); // set_channel(); // wait on cam initialized and copy first image on screen grab_one(&x,&y); prev_data = memcpy(prev_data,grab_one(&x,&y),isize); #ifdef SDL screen->pixels = prev_data; SDL_UpdateRect(screen,0,0,0,0); #endif main_loop(); free(v_device); free(fin_data); free(prev_data); free(firsti); free(lasti); free(rating); close (grab_fd); munmap(grab_data, grab_size); }