52

I am a beginner in OpenCV. I want to do some image processing on the frames of a video which is being uploaded to my server. I just want to read the available frames and write them in a directory. Then, wait for the other part of the video to be uploaded and write the frames to the directory. And , I should wait for each frame to be completely uploaded then write it to a file.

Can you tell me how can I do it with OpenCV (Python)?

Edit 1: I wrote this code for capturing the video from a file, while new data are being appended at the end of the file. In other words, the out.mp4 file is not a complete video and another program is writing new frames on it. What I'm going to do is, wait for the other program to write new frames then read them and display them.

Here is my code:

import cv2
cap = cv2.VideoCapture("./out.mp4")

while True:
    if cap.grab():
        flag, frame = cap.retrieve()
        if not flag:
            continue
        else:
            cv2.imshow('video', frame)
    if cv2.waitKey(10) == 27:
        break

So the problem is the cap.grab() call! When there is no frame, it will return False! And it won't capture frames anymore, even if I wait for a long time.

4

7 回答 7

57

在阅读了VideoCapture. 我发现您可以告诉VideoCapture我们下次调用VideoCapture.read()(或VideoCapture.grab())时要处理哪个帧。

问题是当你想要read()一个没有准备好的框架时,VideoCapture对象卡在那个框架上并且永远不会继续。所以你必须强制它从前一帧重新开始。

这是代码

import cv2

cap = cv2.VideoCapture("./out.mp4")
while not cap.isOpened():
    cap = cv2.VideoCapture("./out.mp4")
    cv2.waitKey(1000)
    print "Wait for the header"

pos_frame = cap.get(cv2.cv.CV_CAP_PROP_POS_FRAMES)
while True:
    flag, frame = cap.read()
    if flag:
        # The frame is ready and already captured
        cv2.imshow('video', frame)
        pos_frame = cap.get(cv2.cv.CV_CAP_PROP_POS_FRAMES)
        print str(pos_frame)+" frames"
    else:
        # The next frame is not ready, so we try to read it again
        cap.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, pos_frame-1)
        print "frame is not ready"
        # It is better to wait for a while for the next frame to be ready
        cv2.waitKey(1000)

    if cv2.waitKey(10) == 27:
        break
    if cap.get(cv2.cv.CV_CAP_PROP_POS_FRAMES) == cap.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT):
        # If the number of captured frames is equal to the total number of frames,
        # we stop
        break
于 2013-09-29T20:08:42.183 回答
22

用这个:

import cv2
cap = cv2.VideoCapture('path to video file')
count = 0
while cap.isOpened():
    ret,frame = cap.read()
    cv2.imshow('window-name', frame)
    cv2.imwrite("frame%d.jpg" % count, frame)
    count = count + 1
    if cv2.waitKey(10) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows() # destroy all opened windows
于 2015-07-21T09:49:15.430 回答
9

根据 OpenCV 3.0 及更高版本的最新更新,您需要在 Mehran 的代码中更改Property Identifiers,如下所示:

cv2.cv.CV_CAP_PROP_POS_FRAMES

cv2.CAP_PROP_POS_FRAMES

同样适用于cv2.CAP_PROP_POS_FRAME_COUNT.

希望能帮助到你。

于 2016-06-30T19:51:21.893 回答
8

在 openCV 的文档中有一个逐帧获取视频的示例。它是用 c++ 编写的,但是很容易将示例移植到 python - 您可以搜索每个函数文档以查看如何在 python 中调用它们。

#include "opencv2/opencv.hpp"

using namespace cv;

int main(int, char**)
{
    VideoCapture cap(0); // open the default camera
    if(!cap.isOpened())  // check if we succeeded
        return -1;

    Mat edges;
    namedWindow("edges",1);
    for(;;)
    {
        Mat frame;
        cap >> frame; // get a new frame from camera
        cvtColor(frame, edges, CV_BGR2GRAY);
        GaussianBlur(edges, edges, Size(7,7), 1.5, 1.5);
        Canny(edges, edges, 0, 30, 3);
        imshow("edges", edges);
        if(waitKey(30) >= 0) break;
    }
    // the camera will be deinitialized automatically in VideoCapture destructor
    return 0;
}
于 2013-09-23T10:40:46.350 回答
2

这就是我开始解决这个问题的方法:

  1. 创建视频作者:

    import cv2.cv as cv
    videowriter = cv.CreateVideoWriter( filename, fourcc, fps, frameSize)
    

    在此处检查有效参数

  2. 循环检索 [1] 并写入帧:

    cv.WriteFrame( videowriter, frame )
    

    写帧文档

[1] zenpoy 已经指出了正确的方向。您只需要知道您可以从网络摄像头或文件中检索图像 :-)

希望我理解正确的要求。

于 2013-09-24T10:51:12.990 回答
2

我发现的唯一解决方案不是将索引设置为前一帧并等待(然后 OpenCV 无论如何都会停止读取帧),而是再初始化一次捕获。所以,它看起来像这样:

cap = cv2.VideoCapture(camera_url)
while True:
    ret, frame = cap.read()

    if not ret:
        cap = cv.VideoCapture(camera_url)
        continue

    # do your processing here

而且效果很好!

于 2017-11-16T10:12:07.777 回答
0

这是 a.mp4 是视频文件的示例

import cv2
cap = cv2.VideoCapture('a.mp4')
count = 0
while cap.isOpened():
    ret,frame = cap.read()
    if not ret:
        continue
    cv2.imshow('window-name', frame)
    #cv2.imwrite("frame%d.jpg" % count, frame)
    count = count + 1
    if cv2.waitKey(10) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()
于 2021-07-17T17:11:40.500 回答