/* GLUT Capture Sample Uses GLUT for user interface OpenGL for drawing IM for image I/O and capture Needs "glut32.lib", "vfw32.lib", "strmiids.lib", "im.lib", "im_capture.lib", "im_avi.lib" and "im_process.lib". Control Keys: - Terminates - Activates/Deactivates the capturing. , , , etc - Shows capture configuration dialogs, in general 2, but can have more. - Starts to save every frame in an AVI file. - Process a background image using an average of N frames. - Saves the background image in a BMP file. <1>, <2>, etc - Activates an processing operation. Only operation 1 is working, it subtracts the background image if one was created. <0> - Deactivates all the processing operations. ATENTION: These keys works at the GLUT window. But the text input in done at the console window. Check the correct window focus before typing keys. */ #include #include #include #include #include #include #include #include #include #include #include #include /* Global Variables */ imVideoCapture* myVideoCap; /* capture control */ imImage* image = NULL; /* capture buffer */ unsigned char* gl_data = NULL; /* opengl display buffer */ char video_filename[512] = ""; imFile* video_file = NULL; imImage* back_image = NULL; /* background image */ imImage* back_acum = NULL; /* aux image for background image calculation */ int back_count = 0; /* number of images to average */ int back_index = 0; /* average image counter */ int user_key[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; static void SimpleBackSub(imbyte *map, imbyte *back_map, int count, float tol) { int i; for (i = 0; i < count; i++) { int diff = map[i] - back_map[i]; if (diff < 0) diff = -diff; if(diff <= tol) map[i] = 0; } } static float tol = 10; /* you should use some key to change this */ void capture_process(int* user_key, imImage* image, imImage* back_image) { if (user_key[0] && back_image) /* '1' */ { int i; for (i = 0; i < image->depth; i++) /* notice that here depth is always 3 */ { SimpleBackSub((imbyte*)image->data[i], (imbyte*)back_image->data[i], image->count, tol); } } /***** call other operations here ******/ } /* Aux to draw a number in the display */ void display_number(int num) { int i; char msg[30]; sprintf(msg,"%4d", num); glColor3f(1.0f,0.0f,0.0f); glRasterPos2f(10.f,10.f); for(i = 0; msg[i]; i++) glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, msg[i]); } /* GLUT display callback */ /* called everytime the window needs to be updated */ void display(void) { if (!image) return; /* Draws the captured image at (0,0) */ glRasterPos2f(0.f, 0.f); glDrawPixels(image->width, image->height, GL_RGB, GL_UNSIGNED_BYTE, gl_data); glutSwapBuffers(); } /* GLUT reshape callback */ /* called everytime the window changes its size */ void reshape(int w, int h) { glViewport(0, 0, w, h); } /* GLUT idle callback */ /* called when there is no events to be processed */ void idle(void) { if (imVideoCaptureLive(myVideoCap, -1)) { imVideoCaptureFrame(myVideoCap, image->data[0], IM_RGB, 1000); if (back_image && back_index < back_count) { /* calculating the background image */ imProcessUnArithmeticOp(image, back_acum, IM_UN_INC); /* back_image += image */ back_index++; if (back_index == back_count) /* last sum, divide by N */ { imProcessArithmeticConstOp(back_acum, (float)back_count, back_image, IM_BIN_DIV); printf("Background image updated.\n"); } } else { /* call some processing */ capture_process(user_key, image, back_image); if (video_file) imFileWriteImageData(video_file, image->data[0]); } imConvertPacking(image->data[0], gl_data, image->width, image->height, image->depth, image->data_type, 0); display(); } } /* OpenGL initialization */ void glinit(void) { if (!image) return; glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D (0.0, (GLdouble)image->width, 0.0, (GLdouble)image->height); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } /* updates the capture image size and display buffer size */ void updatebuffer(void) { int width, height; /* retrieve the image size */ imVideoCaptureGetImageSize(myVideoCap, &width, &height); if (width != image->width || height != image->height) { /* fix the buffer size */ imImageReshape(image, width, height); gl_data = realloc(gl_data, image->size); /* fix the window size */ glutReshapeWindow(image->width, image->height); /* re-inititalizes the OpenGL */ glinit(); } } /* GLUT function key callback */ /* called everytime a function key is pressed */ void parsefunckey(int key, int x, int y) { switch (key) { case GLUT_KEY_F1: /* F1, F2, F.. = shows the capture configuration dialogs */ case GLUT_KEY_F2: case GLUT_KEY_F3: case GLUT_KEY_F4: case GLUT_KEY_F5: case GLUT_KEY_F6: case GLUT_KEY_F7: case GLUT_KEY_F8: imVideoCaptureLive(myVideoCap, 0); /* deactivate the capture before calling the dialog */ imVideoCaptureShowDialog(myVideoCap, key - GLUT_KEY_F1, NULL); updatebuffer(); imVideoCaptureLive(myVideoCap, 1); break; } } /* GLUT key callback */ /* called everytime an ASCII key is pressed */ void parsekey(unsigned char key, int x, int y) { int error, index; switch (key) { case 27: /* Esc = terminates */ printf("\nTerminating...\n"); imVideoCaptureDisconnect(myVideoCap); imVideoCaptureDestroy(myVideoCap); imImageDestroy(image); if (video_file) { imFileClose(video_file); printf("AVI file created.\n"); } free(gl_data); exit(1); case ' ': /* Space = activates/deactivates the capturing */ if (imVideoCaptureLive(myVideoCap, -1)) imVideoCaptureLive(myVideoCap, 0); else imVideoCaptureLive(myVideoCap, 1); break; case 'v': if (video_file) { imFileClose(video_file); printf("AVI file created.\n"); video_file = NULL; break; } printf("Enter the AVI file name:\n >"); scanf("%s", video_filename); video_file = imFileNew(video_filename, "AVI", &error); if (!video_file) printf("Error creating video file.\n"); else { imFileSetInfo(video_file, "CUSTOM"); /* shows the compression options dialog */ imFileWriteImageInfo(video_file, image->width, image->height, IM_RGB, IM_BYTE); } break; case 'b': if (back_image) { imImageDestroy(back_image); imImageDestroy(back_acum); } printf("Enter the number of images to average:\n >"); scanf("%d", &back_count); back_acum = imImageCreate(image->width, image->height, IM_RGB, IM_USHORT); back_image = imImageClone(image); back_index = 0; break; case 's': if (back_image) { char filename[512]; imFile* ifile; printf("Enter the BMP file name:\n >"); scanf("%s", filename); ifile = imFileNew(filename, "BMP", &error); if (!ifile) { printf("Error creating image file.\n"); return; } imFileSaveImage(ifile, back_image); imFileClose(ifile); printf("BMP file created.\n"); } break; case '0': memset(user_key, 0, 9*sizeof(int)); break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': index = key - '1'; user_key[index] = user_key[index]? 0: 1; /* switch state */ if (user_key[index]) printf("Processing %c activated. \n", key); else printf("Processing %c deactivated. \n", key); return; default: glutPostRedisplay(); return; } } /* Returns a capture device */ int getcapture(void) { int i; int cap_count = imVideoCaptureDeviceCount(); if (cap_count == 1) /* only one device */ return 0; printf("Enter the capture device number to use:\n"); for (i = 0; i < cap_count; i++) { printf(" %s\n", imVideoCaptureDeviceDesc(i)); } printf(" > "); scanf("%d", &i); if (i < 0 || i >= cap_count) return 0; return i; } /* Initializes the capture device */ int initcapture(void) { int width, height; /* creates an IM video capture manager */ myVideoCap = imVideoCaptureCreate(); if (!myVideoCap) { printf("No capture device found.\n"); return 0; } /* conects the device */ if (!imVideoCaptureConnect(myVideoCap, getcapture())) { imVideoCaptureDestroy(myVideoCap); printf("Can not connect to capture device.\n"); return 0; } if (!imVideoCaptureLive(myVideoCap, 1)) { imVideoCaptureDisconnect(myVideoCap); imVideoCaptureDestroy(myVideoCap); printf("Can not activate capturing.\n"); return 0; } /* retrieve the image size */ imVideoCaptureGetImageSize(myVideoCap, &width, &height); /* alocates the buffers */ image = imImageCreate(width, height, IM_RGB, IM_BYTE); gl_data = malloc(image->size); return 1; } int main(int argc, char* argv[]) { printf("GLUT Capture\n"); printf(" - Terminates.\n" " - Activates/Deactivates the capturing.\n" " , , , ... - Shows capture configuration dialogs.\n" " - Starts to save every frame in an AVI file.\n" " - Process a background image using an average of N frames.\n" " - Saves the background image in a BMP file.\n" " <1>, <2>, ... - Activates an processing operation.\n" " <0> - Deactivates all the processing operations.\n\n"); /* Initializes the capture device */ if (!initcapture()) return 1; imFormatRegisterAVI(); /* GLUT initialization */ glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); glutInitWindowPosition(100, 100); glutInitWindowSize(image->width, image->height); glutCreateWindow("GLUT Capture"); glClearColor(0., 0., 0., 1.0); /* window background */ glPixelStorei(GL_UNPACK_ALIGNMENT, 1); /* data alignment is 1 */ /* register GLUT callbacks */ glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(parsekey); glutSpecialFunc(parsefunckey); glutIdleFunc(idle); /* OpenGL initialization */ glinit(); /* GLUT message loop */ glutMainLoop(); return 0; }