Ask Your Question

easy video process but very slow

asked 2017-05-19 08:26:04 -0600

psykomusic gravatar image

updated 2017-05-19 08:57:09 -0600

Hi guys ! I did a small code to record the moving part of a video. In fact i open a video, I process the opticalflow and I threshold the norm of the vector. When their is enough motion i record the frame in a videowritter. The code do what i want but I find it very slow, like 2min for 2min video. I found this sort of problem on this link but I'm already using ffmpeg with opencv. I don't know if it related but at the begining of the run an error occured (but no crash).

OpenCV: FFMPEG: tag 0x34363258/'X264' is not supported with codec id 28 and format 'mp4 / MP4 (MPEG-4 Part 14)' OpenCV: FFMPEG: fallback to use tag 0x00000021/'!???'

Because code is better than explanation:

int main ( argc, const char** argv)
    VideoCapture cap("../Video/6880.mp4");
    int fourcc = CV_FOURCC('X','2','6','4');
    int fps = cap.get(CV_CAP_PROP_FPS);
    Size S = Size((int) cap.get(CAP_PROP_FRAME_WIDTH),    // Acquire input size
           (int) cap.get(CAP_PROP_FRAME_HEIGHT));
    VideoWriter out("output.mp4",fourcc, fps ,S, true);
    Mat flow;
    UMat  flowUmat, prevgray;
    bool catchframe;
    for (;;)
        bool Is = cap.grab();
        double millis = cap.get(CV_CAP_PROP_POS_MSEC); // capture time in frame
        if (Is == false)
            cout << "Video Capture Fail" << endl;
           Mat img ;
           millis /= 1000;
           // capture frame from video file
           cap.retrieve(img, CV_CAP_OPENNI_BGR_IMAGE);
           resize(img, img, Size(640, 480));
           // save original for later
           cvtColor(img, img, COLOR_BGR2GRAY);
           if (prevgray.empty() == false ) 
                // calculate optical flow
                calcOpticalFlowFarneback(prevgray, img, flowUmat, 0.4, 1, 12, 2, 8, 1.2, 0);
                // copy Umat container to standard Mat
                catchframe = false;
                // By y += 5, x += 5 you can specify the grid
                for (int y = 0; y < original.rows; y += 5) 
                    for (int x = 0; x < original.cols; x += 5)
                                const Point2f flowatxy =<Point2f>(y, x) * 10;
                                double norm = sqrt((flowatxy.x*flowatxy.x + flowatxy.y*flowatxy.y) * (flowatxy.x*flowatxy.x + flowatxy.y*flowatxy.y)  );
                                if (norm > 2000)
                                    catchframe = true;
                if (catchframe)
                    timeRejected += millis;
                    putText(original, format("%4.3f", millis),Point(20,20), FONT_HERSHEY_PLAIN, 1.0, CV_RGB(0,255,0), 2.0);
                    resize(original, original, S);
            else                                 // fill previous image in case prevgray.empty() == true

My Question is, why my code is very slow with an intel I7, and how can I resolve the error ?

edit retag flag offensive close merge delete


dense optical flow might be total overkill, if all you want is a coarse estimation of global motion to trigger a videowriter

berak gravatar imageberak ( 2017-05-19 10:39:45 -0600 )edit

Thank you for your answer. Indeed the dense optical flow seems to be overkill for the thing i want to do. Maybe i'll use 1616 block instead of 55. Psykomusic

psykomusic gravatar imagepsykomusic ( 2017-05-22 01:49:21 -0600 )edit

a simple sum(absdiff(curr,prev)) > threshold would do here, imho.

berak gravatar imageberak ( 2017-05-22 01:52:24 -0600 )edit

Yeah, it's a good idea ! I tried the result is less good than the optical flow. In fact my camera is static and I want record when animals or objects comes in the field, and I want to see the object moves. With your method the sum of the diff is not very high when the object moves that's why the threshold is lot more complicated and the result bad. Your way is a lot faster (1min to 6sec for a 2min video) and I'll continue to invistigate.

psykomusic gravatar imagepsykomusic ( 2017-05-22 02:57:46 -0600 )edit

1 answer

Sort by ยป oldest newest most voted

answered 2017-05-19 09:59:17 -0600

VideoCurious gravatar image

updated 2017-05-19 10:42:13 -0600

I'm leaning towards the optical flow calculation, but you should add duration calculations to various operations to narrow down what operations are taking more time.

I've seen the type of errors you mentioned. I believe this has something to do with lack of codec-container support in OpenCV. Try changing your output video filename to end in ".avi". See further discussion in the thread Videowriter recording MP4 + X264 (OpenCV 3.1).

OpenCV: FFMPEG: tag 0x34363258/'X264' is not supported with codec id 28 and format 'mp4 / MP4 (MPEG-4 Part 14)' OpenCV: FFMPEG: fallback to use tag 0x00000021/'!???'

edit flag offensive delete link more


Thank you for your answer. :) I don't want to change for .avi, because mp4 + h264 seems to be the lightest, it's strange because i have this error but the file is written and complete. Psykomusic

psykomusic gravatar imagepsykomusic ( 2017-05-22 01:49:43 -0600 )edit

I resolve the error by replace the fourcc by 0x00000021

psykomusic gravatar imagepsykomusic ( 2017-05-22 03:14:29 -0600 )edit

0x00000021 appears to be H263I if I counted the enum values correctly, that is AV_CODEC_ID_H263I. See AVCodecID enum in FFmpeg/libavcodec/avcodec.h. Also see opencv/modules/videoio/src/ffmpeg_codecs.hpp.

VideoCurious gravatar imageVideoCurious ( 2017-06-02 11:51:45 -0600 )edit

Question Tools

1 follower


Asked: 2017-05-19 08:26:04 -0600

Seen: 1,502 times

Last updated: May 19 '17