You are here

VidRecord C++ source notes

The required includes for OpenCV are just "core" and "highgui".

#include < opencv2/core/core.hpp >
#include < opencv2/highgui/highgui.hpp >

Remainder of the includes are just standard cpp libraries for iostream, some string manipulations and time routines.

Included is simplistic class called "Config.cpp" for retrieving configuration parameters from the command line arguments or from a configuration file called (no surprise) ".vidrecordrc". It has a number overloaded function "getters" for retrieving various parameter types, int, double, bool, and string.

/**
  * Get configuration value for a parameter
  * @param name Name of the parameter
  * @param default Default value for the parameter if not set
  * @return the parameter's value as an integer
  */
int Config::getVal(string name, int defaultVal) {
	int retVal = defaultVal;

	if (vals.count(name) > 0) {
		istringstream iss(vals[name]);
		iss >> retVal;
	}

	return retVal;
}

We use get parameters previously set from command line arguments or previously loaded from a config file. For example, the configuration parameters for image writing are retrieved as follows:

    imgDir = config.getVal("imgdir", imgDir);
    imgFmt = config.getVal("imgfmt", imgFmt);
    imgInterval = config.getVal("imgint", imgInterval);
    imgNum = config.getVal("imgnum", imgNum);

We open the video device connected to our allsky camera as follows:

    // Open video device, set video frame width and height as driver often does not
    VideoCapture cap = VideoCapture(vidDevice);

    if (cap.isOpened()) {
        cap.set(CV_CAP_PROP_FRAME_WIDTH, 640);
        cap.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
    } else {
    	cerr << "Error: Could not open video device "<< vidDevice << endl;
        return 1;   
    } 

Frames from the video device are moved to our image frame

    // Frame capture loop
    while(isEnabled) {
        cap >> frame;
        ....

We then write the frame to the video file, calculate the time interval passed and based on whether or not to create a new file:

        if (isRecordingEnabled) {
            writer.write(frame);
            vidDelta = sec - vidTime;
            cout << "vidDelta "<= "<= vidInterval) {
                isRecording = false;
                vidTotal = vidTotal + 1;
                ....
        if ((isRecordingEnabled) && (!isRecording)) {
            int width = (int)cap.get(CV_CAP_PROP_FRAME_WIDTH);
            int height = (int)cap.get(CV_CAP_PROP_FRAME_HEIGHT);
            writer = createVideoFile(vidDir, width, height, vidFps, fourcc, sec);
            vidTime = sec;
            isRecording = true;
            frameNum = 0;
        }

The "createVideoFile function creates a new VideoWriter object that starts writing passing it a file name with current time stamp.

VideoWriter createVideoFile(String vidDir, int width, int height, int fps, int fourcc, time_t sec) {

    string timeStr = currentTimeString(&sec);
    string fileName = vidDir + timeStr + ".avi";
	cout << "Video file name = " << fileName << endl;
	Size frameSize = Size(width, height);
    VideoWriter vidWriter = VideoWriter(fileName, fourcc, fps,
        frameSize);
	return vidWriter;
}

The "currentTimeString" function uses the current time in seconds and uses the gmtime function to return the current time.

string currentTimeString(time_t *sec) {
    struct tm *ptm = gmtime (sec);
    ostringstream ostr;
    ostr<tm_year + 1900)<< "-" << setw(2)<< (ptm->tm_mon+1)
            << "-" << setw(2)<tm_mday << "T"<tm_hour
            << "h" <tm_min << "m" << setw(2) << ptm->tm_sec;
    return ostr.str();
}

The writeImageFile uses the cuirrentTimeString as well to create new png, jpg, tiff, etc image files at periodic intervals. Logic as to when to write them is very similar to how its done for video. See source code referenced above for details.