私はOpenCVの初心者です。サーバーにアップロードされているビデオのフレームで画像処理を行いたいです。使用可能なフレームを読み取り、ディレクトリに書き込みたいだけです。そして、ビデオの他の部分がアップロードされるのを待って、ディレクトリにフレームを書き込みます。そして、各フレームが完全にアップロードされるのを待ってから、ファイルに書き込みます。
OpenCV(Python)でどうすればいいですか?
編集1:ファイルからビデオをキャプチャするためにこのコードを書きましたが、ファイルの最後に新しいデータが追加されています。つまり、out.mp4
ファイルは完全なビデオではなく、別のプログラムが新しいフレームを書き込んでいます。私がやろうとしているのは、他のプログラムが新しいフレームを書き込むのを待ってから、それらを読み取って表示することです。
ここに私のコードがあります:
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
したがって、問題はcap.grab()
呼び出しです!フレームがない場合、False
を返します!そして、たとえ私が長い間待っていても、それはもうフレームをキャプチャしません。
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
これを使って -
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
OpenCV 3.0以降の最新の更新プログラムによると、MehranのコードでProperty Identifiersを次のように変更する必要があります。
cv2.cv.CV_CAP_PROP_POS_FRAMES
に
cv2.CAP_PROP_POS_FRAMES
cv2.CAP_PROP_POS_FRAME_COUNT
にも同じことが当てはまります。
それが役に立てば幸い。
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;
}
これは私がこれを解決し始める方法です:
ビデオライターを作成します。
import cv2.cv as cv
videowriter = cv.CreateVideoWriter( filename, fourcc, fps, frameSize)
ループして取得し[1]、フレームを書き込みます。
cv.WriteFrame( videowriter, frame )
[1] zenpoyはすでに正しい方向を指していました。あなたはウェブカメラまたはファイルから画像を取得できることを知っている必要があります:-)
要件が正しいことを理解したことを願っています。
私が見つけた唯一の解決策は、インデックスを前のフレームに設定して待機することではなく(その後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
そして、それは完全に機能します!