/** * cvbase C module implementation * * See cvbase.h for details. * * @author vona **/ #include "cvbase.h" #include #include #include #ifdef _MSC_VER #define snprintf sprintf_s #endif CvCapture *cap = 0; float maxFPS = DEF_MAX_FPS; int minDelayMS = DEF_MIN_DELAY_MS; const char *appname = DEF_APPNAME; IplImage *saveImage = 0; IplImage *capImage = 0; IplImage *procImage = 0; int frameN = -1; double msPerTick = -1; int paused = 0; int dbg = 0; double nowMS() { return cvGetTickCount()*msPerTick; } void cmdHelp() { int cio = camIndexOptional(); printf("%s -?|-h -- display this help\n", appname); printf("%s %sI [W H]%s %s-- use cam index I (def -1) [at WxH, def %dx%d]\n", appname, cio?"[":"", cio?"]":"", cmdHelpExtParams(), DEF_CAM_W, DEF_CAM_H); printf("%s path %s-- read frames from video file at path\n", appname, cmdHelpExtParams()); cmdHelpExt(); } void guiHelp() { printf("h -- display this help\n"); printf("q,ESC -- quit\n"); printf("SPACE -- toggle run/pause\n"); printf("g -- debug next frame\n"); printf("c -- save last captured image\n"); printf("p -- save last processed image\n"); guiHelpExt(); } int handleKey(int code) { switch (code) { case 'h': { guiHelp(); break; } case 27: case 'q': return 0; case ' ': { paused = !paused; break; } case 'g': { dbg = 1; break; } case 'c': { char fn[256]; snprintf(fn, 256, "%s-c%d.png", appname, frameN); if (capImage == 0) { fprintf(stderr, "no capture image\n"); break; } printf("saving capture image to %s\n", fn); if (!save(fn, capImage)) fprintf(stderr, "error saving image\n"); break; } case 'p': { char fn[256]; snprintf(fn, 256, "%s-p%d.png", appname, frameN); if (procImage == 0) { fprintf(stderr, "no processed image\n"); break; } printf("saving processed image to %s\n", fn); if (!save(fn, procImage)) fprintf(stderr, "error saving image\n"); break; } default: return handleKeyExt(code); } return 1; } int save(const char *filename, IplImage *image) { /* (re-)allocate saveImage if necessary, since cvSaveImage can handle only 8-bit 1 or 3 channel images (it also assumes BGR order in the latter case) */ if ((image->depth != IPL_DEPTH_8U) || ((image->nChannels != 1) && (image->nChannels != 3))) { int w = image->width, h = image->height; int nc = (image->nChannels > 1) ? 3 : 1; if ((saveImage == 0) || (saveImage->width != w) || (saveImage->height != h) || (saveImage->nChannels != nc)) { if (saveImage != 0) cvReleaseImage(&saveImage); saveImage = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, nc); } } if (saveImage != 0) { cvConvertImage(image, saveImage, 0); image = saveImage; } return cvSaveImage(filename, image, 0); } void cleanup() { cleanupExt(); cvDestroyAllWindows(); if (saveImage != 0) cvReleaseImage(&saveImage); if (cap != 0) cvReleaseCapture(&cap); } int init(int argc, char *argv[]) { int ate = 0, i; long index = -2; char *ep; const char *input; printf("OpenCV %s (%d.%d.%d)\n", CV_VERSION, CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION); msPerTick = (1.0/1000.0)*(1.0/cvGetTickFrequency()); atexit(cleanup); for (i = 1; i < argc; i++) if ((strncmp("-h", argv[i], 2) == 0) || (strncmp("-?", argv[i], 2) == 0)) { cmdHelp(); exit(0); } input = (argc >= 2) ? argv[1] : DEF_INPUT; if (argc >= 2) ate++; index = strtol(input, &ep, 10); if (*ep == '\0') { long w = DEF_CAM_W, h = DEF_CAM_H, v; int rw, rh; /* either no args or first arg parsed as an int; open a camera */ if (argc >= 4) { v = strtol(argv[2], &ep, 10); if (*ep == '\0') { w = v; ate++; v = strtol(argv[3], &ep, 10); if (*ep == '\0') { h = v; ate++; } } } cap = cvCaptureFromCAM(index); if (!cap) { fprintf(stderr, "error opening camera %ld\n", index); exit(-1); } rw = cvSetCaptureProperty(cap, CV_CAP_PROP_FRAME_WIDTH, w); rh = cvSetCaptureProperty(cap, CV_CAP_PROP_FRAME_HEIGHT, h); if (!rw || !rh) { fprintf(stderr, "W: error setting camera to %ldx%ld\n", w, h); } if (index >= 0) printf("reading frames from camera %ld\n", index); else printf("reading frames from first available camera\n"); } else { /* input specifier did not parse as an int, try to open it as a video file */ cap = cvCaptureFromFile(input); if (!cap) { fprintf(stderr, "error opening file \"%s\"\n", input); exit(-1); } printf("reading frames from file \"%s\"\n", input); } if (!cvNamedWindow(appname, CV_WINDOW_AUTOSIZE)) { fprintf(stderr, "W: error opening window\n"); } cvMoveWindow(appname, 0, 0); return initExt(argc, argv, ate); } void mainLoop() { double frameStartMS, startMS; int minFrameMS = 1000.0/maxFPS, waitUntilMS, wasDbg, w, c; frameN = -1; for (;;) { frameStartMS = nowMS(); if (!paused) { if (dbg) printf("-- capturing frame %d\n", frameN); startMS = nowMS(); capImage = cvQueryFrame(cap); if (capImage != 0) { if (dbg) printf("captured %dx%d frame (%.3fms)\n", capImage->width, capImage->height, nowMS()-startMS); if (frameN == 0) printf("capture size %dx%d, %d channels, %d bits, %s\n", capImage->width, capImage->height, capImage->nChannels, ((capImage->depth)&(~IPL_DEPTH_SIGN)), (((capImage->depth)&IPL_DEPTH_SIGN)?"signed":"unsigned")); frameN++; } else { fprintf(stderr, "W: error capturing frame\n"); } } else if (dbg) printf("-- paused on frame %d\n", frameN); if (dbg) printf("processing...\n"); startMS = nowMS(); procImage = process(capImage); if (dbg) printf("processed into %dx%d image (%.3fms)\n", procImage->width, procImage->height, nowMS()-startMS); if (cvGetWindowHandle(appname) == 0) { printf("main window closed, exiting\n"); break; } if (procImage != 0) { /* note: small race condition here; if user closes window now, it will be reopened when we call cvShowImage() */ if (dbg) printf("displaying processed image\n"); startMS = nowMS(); /* note: if necessary, this call will deal with whatever bit depth or number of channels the image may have (it will assume BGR order for 3 channel images) */ cvShowImage(appname, procImage); if (dbg) printf("displayed %dx%d image (%.3fms)\n", procImage->width, procImage->height, nowMS()-startMS); } if (dbg) printf("frame time %.3fms\n", nowMS()-frameStartMS); waitUntilMS = frameStartMS + minFrameMS; if (waitUntilMS < nowMS()) waitUntilMS = nowMS()+minDelayMS; if (dbg) printf("-- finished frame %d (%.3f FPS)\n", (paused ? frameN : (frameN-1)), 1000.0/(waitUntilMS-frameStartMS)); wasDbg = dbg; for (w = waitUntilMS-nowMS(); w > 0; w = waitUntilMS-nowMS()) { if (dbg) printf("waiting %dms (or until keypress)\n", w); c = cvWaitKey(w); if (c < 0) break; /* cvWaitKey timed out */ if (!handleKey(c)) { fflush(stdout); return; } } fflush(stdout); if (wasDbg) dbg = 0; } }