Ask Your Question

Revision history [back]

Can't read in full video

I have been using openCV for image processing, which entails reading in a video and then looking for a certain color in each frame (see below). It's been working fine until recently when I had to process a few mp4 files from a GoPro. The videos were about 10 mins long, filmed under 48 frames per second. They played normally when viewed with Quicktime, but when I imported those videos in openCV using VideoCapture, the process ended after frame 44 without any error message, as if frame 44 had been the last frame. I am not sure why this happened and was hoping to get some insights.

Many thanks!

  /**
 * @CheckMotionParallel
 * @Motion detection using color detection and image thresholding
 */

//opencv
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/videoio.hpp"
#include <opencv2/highgui.hpp>
#include <opencv2/video.hpp>
#include <fstream>
//C
#include <stdio.h>
//C++
#include <iostream>
#include <sstream>
#include "tbb/blocked_range.h"
#include "tbb/parallel_for.h"
#include "tbb/parallel_reduce.h"
#include "tbb/task_scheduler_init.h"
#include "tbb/mutex.h"
#include "tbb/tbb_thread.h"
#include "tbb/blocked_range2d.h"

using namespace cv;
using namespace std;
using namespace tbb;

void help();
void help()
{
    cout
    << "--------------------------------------------------------------------------" << endl
    << "Note for program CheckMotion" << endl
    << "CheckMotion does the following"  << endl
    << "1) It searches each frame in a video and looks for a specified range of colors in the frame"                                                                   << endl
    << "2) Pixels falling within the range will be converted to white while everything else is turned to black"                     << endl
    << "3) For each frame, the program gives: frame number/time stamp, total pixel count, and white pixel count"                                       << endl
    << "4) For frames whose white pixel count exceeds a threshold, it will export those frames as individial png files" << endl
    << "--------------------------------------------------------------------------" << endl
    << endl;
}

int64 startTime;

int NumThreads = task_scheduler_init::default_num_threads();

int main(int argc, char**)
{
    //Print out program note
    help();

    ///Part I: Read-in the video

    VideoCapture cap("/Users/chi/Desktop/Video analyses/GP080007.mp4");
    //VideoCapture cap("/Volumes/CHI/GP080007.mp4");

    //Error message if the video cannot be opened
    //Create an object denoting the frames
    //Create a window for showing the video as CheckMotion runs
    //For loop looking through frames

    if(cap.isOpened()) {

    startTime = getTickCount();

    Mat frame;
    for(;;)
    {
        //Show each frame in the video window previously created
        double tfreq = getTickFrequency();
        double secs = ((double) getTickCount()-startTime)/tfreq;

        cap >> frame;

//            namedWindow("Frame");
//            imshow("Frame",frame);
//
        waitKey(10);
        //Create a string for frame number that gets updated for each cycle of the loop
        stringstream ss;
        ss << cap.get(CAP_PROP_POS_FRAMES);
        string FrameNumberString = ss.str();

        stringstream maskedfilename;
        stringstream rawfilename;
        //Create filenames for later use in result output and image save using frame number as ref
        maskedfilename << "/Users/chi/Desktop/test/masked" << FrameNumberString.c_str() << ".png";
        rawfilename << "/Users/chi/Desktop/test/raw" << FrameNumberString.c_str() << ".png";

        ///Part II: Image thresholding and image saving

        //Create an object representing new images after thresholding
        Mat masked;
        //inRange function that convert the pixels that fall within the specified range to white and everything else to black
        //The Range is specified by a lower [Scalar(10,0,90)] and an upper [Scalar(50,50,170)] threshold
        //In openCV, a color is defined by its BGR score
        //The thresholded images will then be represented by the object "masked"
        inRange(frame, Scalar(155,115,75), Scalar(250,170,85), masked);

        //Creating integer variables for total pixel count and white pixel count for each frame
        int totalpixel;
        int whitepixel;

        //Total pixel count equals the number of rows and columns of the frame
        totalpixel = frame.rows*frame.cols;
        //Using countNonZero function to count the number of white pixels
        whitepixel = countNonZero(masked);
        //Output frame number, total pixel count and white pixel count for each frame

        //Exit the loop when reaching the last frame (i.e. pixel count drops to 0)
        if(totalpixel==0){
            cap.release();
            cout << "End of the video" << endl;
            cout << "Number of threads: " << NumThreads << endl;
            break;
        }

        else {
            cout
            << "Frame:" << ss.str() << endl
            << "Number of total pixels:" << totalpixel << endl
            << "Pixels of target colors:" << whitepixel << endl
            << "Run time = " << fixed << secs << "seconds" << endl
            << endl;
            //Save the frames with white pixel count larger than a user-determined value (50 in present case)
            //Save both the orignal as well as the procesed images
            if (whitepixel > 0){
            imwrite(rawfilename.str(),frame);
            imwrite(maskedfilename.str(),masked);
            }
        }
    }
  }
}