本次对“视频捕获(VideoCapture)模块”做出分析,给出源代码和对应的程序流程框架。
视频捕获模块的主要功能是设置视频或相机参数,并读取设置配置参数,最后进入帧处理模块的process进程,该模块的源码如下,请重点关注start()函数:
#include "VideoCapture.h" namespace bgslibrary { namespace VC_ROI { IplImage* img_input1 = 0; IplImage* img_input2 = 0; int roi_x0 = 0; int roi_y0 = 0; int roi_x1 = 0; int roi_y1 = 0; int numOfRec = 0; int startDraw = 0; bool roi_defined = false; bool use_roi = true; bool disable_event = false; void reset(void) { disable_event = false; startDraw = false; } void VideoCapture_on_mouse(int evt, int x, int y, int flag, void* param) { if (use_roi == false || disable_event == true) return; if (evt == CV_EVENT_LBUTTONDOWN) { if (!startDraw) { roi_x0 = x; roi_y0 = y; startDraw = 1; } else { roi_x1 = x; roi_y1 = y; startDraw = 0; roi_defined = true; disable_event = true; } } if (evt == CV_EVENT_MOUSEMOVE && startDraw) { //redraw ROI selection img_input2 = cvCloneImage(img_input1); cvRectangle(img_input2, cvPoint(roi_x0, roi_y0), cvPoint(x, y), CV_RGB(255, 0, 0), 1); cvShowImage("Input", img_input2); cvReleaseImage(&img_input2); //startDraw = false; //disable_event = true; } } } VideoCapture::VideoCapture() : key(0), start_time(0), delta_time(0), freq(0), fps(0), frameNumber(0), stopAt(0), useCamera(false), useVideo(false), input_resize_percent(100), showOutput(true), enableFlip(false) { std::cout << "VideoCapture()" << std::endl; } VideoCapture::~VideoCapture() { std::cout << "~VideoCapture()" << std::endl; } void VideoCapture::setFrameProcessor(IFrameProcessor* frameProcessorPtr) { frameProcessor = frameProcessorPtr; } void VideoCapture::setCamera(int index) { useCamera = true; cameraIndex = index; useVideo = false; } void VideoCapture::setUpCamera() { std::cout << "Camera index:" << cameraIndex << std::endl; capture = cvCaptureFromCAM(cameraIndex); if (!capture) std::cerr << "Cannot open initialize webcam!\n" << std::endl; } void VideoCapture::setVideo(std::string filename) { useVideo = true; videoFileName = filename; useCamera = false; } void VideoCapture::setUpVideo() { capture = cvCaptureFromFile(videoFileName.c_str()); if (!capture) std::cerr << "Cannot open video file " << videoFileName << std::endl; } void VideoCapture::start() { ///////////////loadConfig loadConfig(); ///////////////setUpCamera if (useCamera) setUpCamera(); ///////////////setUpVideo if (useVideo) setUpVideo(); if (!capture) std::cerr << "Capture error..." << std::endl; int input_fps = cvGetCaptureProperty(capture, CV_CAP_PROP_FPS); std::cout << "input->fps:" << input_fps << std::endl; IplImage* frame1 = cvQueryFrame(capture); frame = cvCreateImage(cvSize((int)((frame1->width*input_resize_percent) / 100), (int)((frame1->height*input_resize_percent) / 100)), frame1->depth, frame1->nChannels); //cvCreateImage(cvSize(frame1->width/input_resize_factor, frame1->height/input_resize_factor), frame1->depth, frame1->nChannels); std::cout << "input->resize_percent:" << input_resize_percent << std::endl; std::cout << "input->width:" << frame->width << std::endl; std::cout << "input->height:" << frame->height << std::endl; double loopDelay = 33.333; if (input_fps > 0) loopDelay = (1. / input_fps)*1000.; std::cout << "loopDelay:" << loopDelay << std::endl; std::cout << "Press 'ESC' to stop..." << std::endl; bool firstTime = true; do { frameNumber++; frame1 = cvQueryFrame(capture); if (!frame1) break; cvResize(frame1, frame); if (enableFlip) cvFlip(frame, frame, 0); if (VC_ROI::use_roi == true && VC_ROI::roi_defined == false && firstTime == true) { VC_ROI::reset(); do { cv::Mat img_input(frame); if (showOutput) { cv::imshow("Input", img_input); std::cout << "Set ROI (press ESC to skip)" << std::endl; VC_ROI::img_input1 = new IplImage(img_input); cvSetMouseCallback("Input", VC_ROI::VideoCapture_on_mouse, NULL); key = cvWaitKey(0); delete VC_ROI::img_input1; } else key = KEY_ESC; if (key == KEY_ESC) { std::cout << "ROI disabled" << std::endl; VC_ROI::reset(); VC_ROI::use_roi = false; break; } if (VC_ROI::roi_defined) { std::cout << "ROI defined (" << VC_ROI::roi_x0 << "," << VC_ROI::roi_y0 << "," << VC_ROI::roi_x1 << "," << VC_ROI::roi_y1 << ")" << std::endl; break; } else std::cout << "ROI undefined" << std::endl; } while (1); } if (VC_ROI::use_roi == true && VC_ROI::roi_defined == true) { CvRect rect = cvRect(VC_ROI::roi_x0, VC_ROI::roi_y0, VC_ROI::roi_x1 - VC_ROI::roi_x0, VC_ROI::roi_y1 - VC_ROI::roi_y0); cvSetImageROI(frame, rect); } cv::Mat img_input(frame); if (showOutput) cv::imshow("Input", img_input); ///////////////saveConfig if (firstTime) saveConfig(); start_time = cv::getTickCount(); ///////////////frameProcessor,start "Background Modeling" frameProcessor->process(img_input); int64 delta_time = cv::getTickCount() - start_time; freq = cv::getTickFrequency(); fps = freq / delta_time; //std::cout << "FPS: " << fps << std::endl; cvResetImageROI(frame); key = cvWaitKey(loopDelay); //std::cout << "key: " << key << std::endl; if (key == KEY_SPACE) key = cvWaitKey(0); if (key == KEY_ESC) break; if (stopAt > 0 && stopAt == frameNumber) key = cvWaitKey(0); firstTime = false; } while (1); cvReleaseCapture(&capture); } void VideoCapture::saveConfig() { CvFileStorage* fs = cvOpenFileStorage("./config/VideoCapture.xml", 0, CV_STORAGE_WRITE); cvWriteInt(fs, "stopAt", stopAt); cvWriteInt(fs, "input_resize_percent", input_resize_percent); cvWriteInt(fs, "enableFlip", enableFlip); cvWriteInt(fs, "use_roi", VC_ROI::use_roi); cvWriteInt(fs, "roi_defined", VC_ROI::roi_defined); cvWriteInt(fs, "roi_x0", VC_ROI::roi_x0); cvWriteInt(fs, "roi_y0", VC_ROI::roi_y0); cvWriteInt(fs, "roi_x1", VC_ROI::roi_x1); cvWriteInt(fs, "roi_y1", VC_ROI::roi_y1); cvWriteInt(fs, "showOutput", showOutput); cvReleaseFileStorage(&fs); } void VideoCapture::loadConfig() { CvFileStorage* fs = cvOpenFileStorage("./config/VideoCapture.xml", 0, CV_STORAGE_READ); stopAt = cvReadIntByName(fs, 0, "stopAt", 0); input_resize_percent = cvReadIntByName(fs, 0, "input_resize_percent", 100); enableFlip = cvReadIntByName(fs, 0, "enableFlip", false); VC_ROI::use_roi = cvReadIntByName(fs, 0, "use_roi", true); VC_ROI::roi_defined = cvReadIntByName(fs, 0, "roi_defined", false); VC_ROI::roi_x0 = cvReadIntByName(fs, 0, "roi_x0", 0); VC_ROI::roi_y0 = cvReadIntByName(fs, 0, "roi_y0", 0); VC_ROI::roi_x1 = cvReadIntByName(fs, 0, "roi_x1", 0); VC_ROI::roi_y1 = cvReadIntByName(fs, 0, "roi_y1", 0); showOutput = cvReadIntByName(fs, 0, "showOutput", true); cvReleaseFileStorage(&fs); } }
对应的流程框架如下图: