//takes avi file (given on command line as only arg) and //reads in a specified number of frames //the does a "trimmed" mean of the time trajectory of a pixel //i.e., sort the pixels (i,j,t) for fixed i,j and varying t //chop off the ends of the sorted pixels and average the rest //should remove moving objects and reduce illumination changes //one (simple) way of getting a "background" image //NOTE: this example uses the Microsoft Video for Windows (VFW) //library for opening and reading from a file //THIS HAS TWO PROBLEMS // 1) you cannot use this on a machine that isn't running windows // 2) VFW is OLD and doesn't understand how to find CODECS for the // newer encodings - such as DV that you get from handy cams // THUS if the encoding IN the AVI file, is not recognised // THEN this program won't read it properly - CONVERT (using some // utility such as a video editor - to a simple format FIRST // //NOTE - since we are using MSwindoze stuff - we may as well keep //the image data in the DIB format they prefer - even if the alignment //is not guaranteed to be good for fast code //the Intel opencv/ipl libraries have functions for handling image data stored //in a DIB int startframe,endframe,end_drop; #include #include #include "aviread.h" // function prototypes void usage(void); int compare_pixels(const unsigned char * p1,const unsigned char *p2) { if (*(p1)<*(p2)) return -1; else return 1; } unsigned int pixsz,frame; unsigned char *lpColor,*clp; unsigned int palletized; unsigned int bpscanl, dib_offset,x,y; FILE *fp; unsigned char *pixel_time_line; unsigned char *output_image; LPBITMAPINFOHEADER *lpbi_array; PGETFRAME *pget_array; // globals int main(int argc, char **argv) { int i=0,j=0,t=0, err=0; char avifilename[100] = ""; AVIFILEINFO thisPfi; float fps; int sys_bit_specd = 0, sys_byte_specd = 0; PAVISTREAM pVideoStream; time_t current_time, el_time; if(argc < 2) { usage(); } // parse for paramters here strcpy(avifilename, argv[1]); // initialize AVI subsystem AVIFileInit(); // open avi file and validate file parameters hResult = AVIFileOpen(&pfile, avifilename, OF_READ, 0L); if(hResult) { fprintf(stderr, "\ncould not open filename %s!\n", avifilename); exit(7); } // get info structure on file hResult = AVIFileInfo(pfile, &thisPfi, sizeof(AVIFILEINFO)); if(hResult) { fprintf(stderr, "\n%s does not appear to be an AVI file!\n", avifilename); exit(8); } // open a stream hResult = AVIFileGetStream(pfile, &pVideoStream, streamtypeVIDEO, 0); if(hResult) { fprintf(stderr, "\ncould not retrieve video stream from %s!\n", avifilename); exit(31); } // prepare to decompress frames pget = AVIStreamGetFrameOpen(pVideoStream, NULL); // print details on input file fps = (float)thisPfi.dwRate/(float)thisPfi.dwScale; fprintf(stderr, "%s file details:\nWidth = %u, Height = %u, FPS = %4.2f", avifilename, thisPfi.dwWidth, thisPfi.dwHeight, fps); // now retrieve a video frame so we can identify details // get pointer to bitmap lpbi = AVIStreamGetFrame(pget, 0); if(!lpbi) { fprintf(stderr, "\ncould not retrieve video details for %s!",avifilename); fprintf(stderr, "\nyou probably do not have a codec for this compression scheme!"); fprintf(stderr, "\nor avi file may be corrupt!\n"); exit(9); } // we only handle non-palletized video pixsz = lpbi->biBitCount; if(pixsz!=8) { fprintf(stderr, "\ncan only handle 8 bit video!,"); fprintf(stderr, "\nthis file is %i bits!\n", pixsz); exit(10); } fprintf(stderr, ", Bits per pixel = %u", pixsz); if(thisPfi.dwWidth>4095) { fprintf(stderr, "\nHorizontal width must < 4096!"); err = 1; } if(thisPfi.dwHeight>4095) { fprintf(stderr, "\nVerical height must be < 4096!"); err = 1; } if(err) exit(11); fprintf(stderr, "\nTotal Video Frames = %u, ", thisPfi.dwLength); fprintf(stderr, "Length = %u sec.", (unsigned int)thisPfi.dwLength/(int)(fps+.5)); if (lpbi->biCompression != BI_RGB) { fprintf(stderr, "\ncan not handle compressed DIBs from codec!\n"); err = 1; } // locate color table - should there be one??? lpColor = (unsigned char *)lpbi + lpbi->biSize; fprintf(stderr,"pixel size (bits) %d\n",pixsz); // next, actual DIB if(pixsz==8) palletized=1; else palletized=0; if(palletized) dib_offset = sizeof(BITMAPINFOHEADER) + lpbi->biClrUsed * 4; else dib_offset = sizeof(BITMAPINFOHEADER); // offset past bitmap header lpbitmp = (unsigned char *)lpbi + dib_offset; // pointer to actual bitmap fprintf(stderr,"dib offset %d\n",dib_offset); switch(pixsz) { case 8: bpscanl = (unsigned int)(((lpbi->biWidth + 3)>>2)<<2); break; default: fprintf(stderr, "\ninternal error: illegal pixsz value\n"); exit(28); // should never occur } //Now to find out what range of frames should be averaged printf("startframe number? (numbering from 0)\n"); scanf("%d",&startframe); printf("endframe number?\n"); scanf("%d",&endframe); if ((startframe<0)||(endframe>thisPfi.dwLength)||(endframebiHeight)*(lpbi->biWidth)); lpbi_array = (LPBITMAPINFOHEADER *) malloc ((endframe-startframe)*sizeof(LPBITMAPINFOHEADER)); pget_array = (PGETFRAME *) malloc ((endframe-startframe)*sizeof(PGETFRAME)); //read in frames for (frame=startframe;frame< endframe;frame++) { fprintf(stderr,"about to read frame %d\n",frame); pget_array[frame-startframe] = AVIStreamGetFrameOpen(pVideoStream, NULL); lpbi_array[frame-startframe] = AVIStreamGetFrame(pget_array[frame-startframe], frame); } switch(pixsz) { case 8: //process frames for(y = 0; y < (lpbi->biHeight); y++) for(x = 0; x < (lpbi->biWidth); x++) { float ave=0.0; for (t=startframe;tbiWidth)+x); qsort(pixel_time_line,endframe-startframe,1,compare_pixels); //average - dropping ends for (t=startframe+end_drop;t<(endframe-end_drop);t++) ave+=pixel_time_line[t-startframe]; ave/= (endframe-startframe-2*end_drop); //place into output_image //- note windows bitmap is upside to w.r.t. pgm *(output_image+ ((lpbi->biHeight)-y-1)*(lpbi->biWidth)+x)= (unsigned char ) ave; }//for all pixels break; default: fprintf(stderr, "\ninternal error: illegal pixsz value\n"); exit(29); // should never occur }//case //clean up //save the average image fp=fopen("background.pgm","wb"); fprintf(fp,"P5\n%d %d\n255\n", lpbi->biWidth, lpbi->biHeight); fwrite(output_image, lpbi->biWidth, lpbi->biHeight,fp); fclose(fp); AVIStreamGetFrameClose(pget); AVIFileRelease(pfile); AVIFileExit(); return(0); } void usage() { fprintf(stderr,"give avifilename on commandline\n"); exit(0); }