[英]How to process images of a video, frame by frame, in video streaming using OpenCV and Python
I am a beginner in OpenCV.我是 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)?你能告诉我如何用 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.编辑 1:我编写了这段代码,用于从文件中捕获视频,同时将新数据附加到文件末尾。 In other words, the
out.mp4
file is not a complete video and another program is writing new frames on it.换句话说,
out.mp4
文件不是一个完整的视频,另一个程序正在其上写入新的帧。 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!所以问题是
cap.grab()
调用! When there is no frame, it will return False
!当没有框架时,它将返回
False
! And it won't capture frames anymore, even if I wait for a long time.即使我等了很长时间,它也不会再捕获帧了。
After reading the documentation of VideoCapture
.阅读
VideoCapture
的文档后。 I figured out that you can tell VideoCapture
, which frame to process next time we call VideoCapture.read()
(or VideoCapture.grab()
).我发现您可以告诉
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.问题在于,当您想要
read()
未准备好的帧时, VideoCapture
对象会卡在该帧上并且永远不会继续。 So you have to force it to start again from the previous frame.所以你必须强制它从前一帧重新开始。
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
Use this:用这个:
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
According to the latest updates for OpenCV 3.0 and higher, you need to change the Property Identifiers as 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.希望能帮助到你。
In openCV's documentation there is an example for getting video frame by frame.在 openCV 的文档中有一个逐帧获取视频的示例。 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.
它是用 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;
}
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:循环检索 [1] 并写入帧:
cv.WriteFrame( videowriter, frame )
[1] zenpoy already pointed in the correct direction. [1] zenpoy 已经指出了正确的方向。 You just need to know that you can retrieve images from a webcam or a file :-)
您只需要知道您可以从网络摄像头或文件中检索图像:-)
Hopefully I understood the requirements correct.希望我理解正确的要求。
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.我找到的唯一解决方案不是将索引设置为前一帧并等待(然后 OpenCV 停止读取帧,无论如何),而是再次初始化捕获。 So, it looks like this:
所以,它看起来像这样:
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!它完美无缺!
This is example where a.mp4 is the video file这是一个示例,其中 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()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.