如何使用 OpenCV 和 Python 在视频流中逐帧处理视频图像

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18954889/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 12:23:55  来源:igfitidea点击:

How to process images of a video, frame by frame, in video streaming using OpenCV and Python

pythonopencvvideovideo-streaming

提问by Mehran

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.

我是 OpenCV 的初学者。我想对上传到我的服务器的视频的帧进行一些图像处理。我只想读取可用的帧并将它们写入目录中。然后,等待视频的另一部分上传并将帧写入目录。并且,我应该等待每一帧完全上传然后将其写入文件。

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

你能告诉我如何用 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.mp4file 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.

编辑 1:我编写了这段代码,用于从文件中捕获视频,同时将新数据附加到文件末尾。换句话说,该out.mp4文件不是一个完整的视频,另一个程序正在其上写入新的帧。我要做的是,等待其他程序写入新的帧,然后读取它们并显示它们。

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.

所以问题是cap.grab()调用!当没有框架时,它会返回False!即使我等了很长时间,它也不会再捕获帧了。

采纳答案by Mehran

After reading the documentation of VideoCapture. I figured out that you can tell VideoCapture, which frame to process next time we call VideoCapture.read()(or VideoCapture.grab()).

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

The problem is that when you want to read()a frame which is not ready, the VideoCaptureobject stuck on that frame and never proceed. So you have to force it to start again from the previous frame.

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

Here is the code

这是代码

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

回答by zenpoy

In openCV's documentation there is an examplefor getting video frame by frame. It is written in c++ but it is very easy to port the example to python - you can search for each fumction documentation to see how to call them in python.

在 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;
}

回答by Robert Caspary

This is how I would start to solve this:

这是我将如何开始解决这个问题:

  1. Create a video writer:

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

    Check here for valid parameters

  2. Loop to retrieve[1] and write the frames:

    cv.WriteFrame( videowriter, frame )
    

    WriteFrame doc

  1. 创建视频编写器:

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

    在此处检查有效参数

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

    cv.WriteFrame( videowriter, frame )
    

    写框架文档

[1] zenpoy already pointed in the correct direction. You just need to know that you can retrieve images from a webcam or a file :-)

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

Hopefully I understood the requirements correct.

希望我理解正确的要求。

回答by prtkp

use this -

用这个 -

import cv2
cap = cv2.VideoCapture('path of 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 the opened windows

回答by srihegde

According to the latest updates for OpenCV 3.0 and higher, you need to change the Property Identifiersas follows in the code by Mehran:

根据 OpenCV 3.0 及更高版本的最新更新,您需要在 Mehran 的代码中更改属性标识符,如下所示:

cv2.cv.CV_CAP_PROP_POS_FRAMES

to

cv2.CAP_PROP_POS_FRAMES

and same applies to cv2.CAP_PROP_POS_FRAME_COUNT.

同样适用于cv2.CAP_PROP_POS_FRAME_COUNT.

Hope it helps.

希望能帮助到你。

回答by Alexander Lysenko

The only solution I have found is not to set the index to a previous frame and wait (then OpenCV stops reading frames, anyway), but to initialize the capture one more time. So, it looks like this:

我找到的唯一解决方案不是将索引设置为前一帧并等待(然后 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

And it works perfectly!

它完美地工作!