2013-09-23 225 views
28

我是OpenCV的初學者。我想對正在上傳到服務器的視頻幀進行一些圖像處理。我只想讀取可用的幀並將它們寫入目錄中。等待視頻的其他部分上傳並將幀寫入目錄。我應該等待每一幀完全上傳,然後將其寫入文件。如何在視頻流中使用Opencv逐幀處理視頻圖像python

你能告訴我如何用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!即使我等了很長時間,它也不會捕獲幀。

+0

請添加更詳細的描述。上傳過程中或之後的'幀上的一些圖像處理'? '可用框架'在哪裏以及它們應該如何提供? '等待視頻的其他部分',所以只是追加?... –

+0

@RobertCaspary謝謝你的評論。 '對幀進行一些圖像處理':假設我想將幀寫入目錄中的文件。 '可用幀':假設視頻有100幀,但只有40幀被上傳,所以可用幀是前40幀。到目前爲止,我已將它們保存到特定目錄中的文件中。 '等待視頻的其他部分':等待第41幀上傳,然後將其保存到另一個文件,然後保存到第42幀,依此類推。 是否清楚? – Mehran

回答

37

閱讀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 
+0

這可以工作,但是在某個隨機點,幀會停止輸入流繼續。有些東西在這裏仍然被掛起 – Gulzar

7

在openCV的文檔中,有一個用於逐幀獲取視頻的example。它是用C++編寫的,但將示例移植到python非常簡單 - 您可以搜索每個fumction文檔以查看如何在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; 
} 
+0

非常感謝您的回答。 我在python中做了這個。但問題是,當你調用cap >> frame時, 它不會等待框架完全準備就緒!所以如果框架沒有準備好,那麼它將返回null。之後,它不捕獲任何其他幀。是否有意義? – Mehran

+2

@Mehran你會如此溫柔地分享python版本嗎? – user2239318

1

這是我將開始解決這個問題:

  1. 創建視頻作者:

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

    Check here for valid parameters

  2. 循環檢索[1]和寫框架:

    cv.WriteFrame(videowriter, frame) 
    

    WriteFrame doc

[1] zenpoy已經指出在正確的方向。你只需要知道你可以從網絡攝像頭或文件檢索圖像:-)

希望我瞭解的要求正確。

9

使用本 -

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() 
cap.destroyAllWindows() 
+0

我相信你的最後一行應該是:'cv2.destroyAllWindows()' –

6

根據對OpenCV的3.0和最新的更新更高的,你需要改變屬性標識符在代碼如下通過Mehran:

cv2.cv.CV_CAP_PROP_POS_FRAMES 

cv2.CAP_PROP_POS_FRAMES 

並且同樣適用於cv2.CAP_PROP_POS_FRAME_COUNT

希望它有幫助。

+0

這並不回答這個問題。 – JohnAllen

+0

@srihegde感謝您的信息 – Mehran

+0

包括一個鏈接到更多的信息將不勝感激。 – Richard

0

我發現的唯一解決方案不是將索引設置爲前一幀並等待(然後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 

而且它的功能完美!

+0

很好的解決方案。但是,重新初始化Capture的開銷是多少?我們需要確定銷燬對象並創建它並不會降低性能。 – Mehran

+0

它不會降低性能 - 它會減少幾幀。沒有拖拉或類似的東西,所以這爲我們工作。 –

+0

此解決方案在流(本例中爲Camera)始終從當前幀開始時起作用。在我的情況下,文件正在上傳到服務器並保存到out.mp4。因此,如果我重新初始化視頻捕獲,它將從視頻的第一幀開始,而不是最後一個可用幀。 – Mehran