如何使用 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
How to process images of a video, frame by frame, in video streaming using OpenCV and Python
提问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.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.
编辑 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 VideoCapture
object 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:
这是我将如何开始解决这个问题:
Create a video writer:
import cv2.cv as cv videowriter = cv.CreateVideoWriter( filename, fourcc, fps, frameSize)
Loop to retrieve[1] and write the frames:
cv.WriteFrame( videowriter, frame )
创建视频编写器:
import cv2.cv as cv videowriter = cv.CreateVideoWriter( filename, fourcc, fps, frameSize)
循环检索 [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!
它完美地工作!