簡體   English   中英

以較低的幀率解析視頻

[英]Parse video at lower frame rate

我目前正在做一個項目,我需要解析視頻並將其傳遞給多個模型。 視頻以 60fps 的速度播放。 我不需要通過模型運行每一幀。 我在嘗試跳過不需要的幀時遇到了一些問題。 我嘗試了兩種方法,它們都相當慢。

方法 1 代碼片段:這里的問題是我仍在閱讀視頻的每一幀。 只有每 4 幀通過我的模型運行。

  cap = cv2.VideoCapture(self.video)    
    while cap.isOpened():
                    success, frame = cap.read()

                    if count % 4 !=0:
                        count += 1
                        continue

                    if success:
                        ''Run frame through models''
                    else:
                        break

方法 2 代碼片段:此方法較慢。 在這種情況下,我試圖避免閱讀不必要的幀。

cap = cv2.VideoCapture(video)
count=0

while True:

    if count % 4 != 0:
        cap.set(cv2.CV_CAP_PROP_POS_FRAMES, count*15)
        count+=1
        success, frame = cap.read()

關於如何以最有效的方式實現這一目標的任何建議將不勝感激。

由於視頻壓縮的工作方式:通過使用關鍵幀,通過更改 CV_CAP_PROP_POS_FRAMES 來獲取和設置幀不准確(而且速度很慢)。

根本不使用 read() 函數可能會有所幫助。 而是使用grab() 並且只檢索() 所需的幀。 來自文檔:(讀取)方法/函數在一次調用中結合了 VideoCapture::grab() 和 VideoCapture::retrieve()。

Grab()獲取幀數據,然后retrieve() 對其進行解碼(計算量很大的部分)。 您可能想要做的只是抓取要跳過的幀而不是檢索它們。

根據您的系統和 opencv 版本,您還可以使用硬件加速對視頻進行 ffmpeg 解碼。

據我所知,您正在嘗試每四幀處理一次。 您正在使用條件:

if count % 4 != 0

而是在 4 幀中觸發 3 幀(您正在處理幀 1、2、3、5、6、7 等)! 使用相反的:

if count % 4 == 0

此外,盡管代碼片段,這兩種方法似乎沒有處理相同的幀。 盡管在這兩種情況下,您的計數器似乎在每一幀中都增加了 1,但您實際上在第二種情況下指向了該計數器的 15xframe ( cap.set(cv2.CV_CAP_PROP_POS_FRAMES, count*15)

對你的代碼也有一些評論(也許我誤解了一些東西):

情況1:

while cap.isOpened():
                success, frame = cap.read()
                if count % 4 !=0:
                    count += 1
                    continue

在這里,您似乎只計算了一些幀(如上所述,4 中的 3 個),因為跳過了 4 的倍數的幀:在這種情況下,不滿足條件count % 4 !=0並且您的計數器沒有更新,盡管您閱讀了一個幀. 所以,你這里有一個不准確的計數器。 雖然沒有顯示您如何以及在何處處理幀以判斷該部分。

案例2:

while True:
    if count % 4 != 0:
        cap.set(cv2.CV_CAP_PROP_POS_FRAMES, count*15)
        count+=1
        success, frame = cap.read()

在這里,您僅在滿足條件時才讀取幀,因此在此代碼片段中,您實際上並未讀取任何幀,因為第 0 幀不會觸發條件! 如果您在 if 范圍之外更新計數器,則此處不清楚。 但如果你這樣做,你也應該在那里閱讀一個框架。 無論如何,應該透露更多的代碼來說明。

作為一般建議,您應該在每次讀取幀時更新計數器。

與其對幀數設置閾值,這將使 opencv 處理所有幀(您正確指出,這會減慢視頻處理速度),最好使用CAP_PROP_POS_MSEC 鏈接並將該處理卸載到cv2 通過使用此選項,您可以將cv2配置為每第 n 毫秒采樣 1 幀。 因此,在vidcap.set(cv2.CAP_PROP_POS_MSEC, (frame_count * subsample_rate))設置subsample_rate=1000將每 1 秒采樣 1 幀(因為 1000 毫秒等於 1 秒)。 希望這可以提高您的視頻處理速度。

def extractImagesFromVideo(path_in, subsample_rate, path_out, saveImage, resize=(), debug=False):
    vidcap = cv2.VideoCapture(path_in)
    if not vidcap.isOpened():
        raise IOError

    if debug:
        length = int(vidcap.get(cv2.cv2.CAP_PROP_FRAME_COUNT))
        width  = int(vidcap.get(cv2.cv2.CAP_PROP_FRAME_WIDTH))
        height = int(vidcap.get(cv2.cv2.CAP_PROP_FRAME_HEIGHT))
        fps    = vidcap.get(cv2.cv2.CAP_PROP_FPS)
        print 'Length: %.2f | Width: %.2f | Height: %.2f | Fps: %.2f' % (length, width, height, fps)

    success, image = vidcap.read() #extract first frame.
    frame_count = 0
    while success:
        vidcap.set(cv2.CAP_PROP_POS_MSEC, (frame_count*subsample_rate))
        success, image = vidcap.read()
        if saveImage and np.any(image):
            cv2.imwrite(os.path.join(path_out, "%s_%d.png" % (frame_count)), image)
        frame_count = frame_count + 1
    return frame_count

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM