簡體   English   中英

BeagleBone Black OpenCV Python太慢了

[英]BeagleBone Black OpenCV Python is too slow

我嘗試用opencv和python從網絡攝像頭獲取圖像。 代碼是如此基本:

import cv2
import time
cap=cv2.VideoCapture(0)
cap.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH,640)
cap.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT,480)
cap.set(cv2.cv.CV_CAP_PROP_FPS, 20)

a=30
t=time.time()
while (a>0):
        now=time.time()
        print now-t
        t=now
        ret,frame=cap.read()
        #Some processes
        print a,ret
        print frame.shape
        a=a-1
        k=cv2.waitKey(20)
        if k==27:
                break
cv2.destroyAllWindows()

但它運作緩慢。 程序輸出:

VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
HIGHGUI ERROR: V4L: Property <unknown property string>(5) not supported by device
8.82148742676e-06
select timeout
30 True
(480, 640, 3)
2.10035800934
select timeout
29 True
(480, 640, 3)
2.06729602814
select timeout
28 True
(480, 640, 3)
2.07144904137
select timeout

組態:

  • Beaglebone Black RevC
  • Debian的wheezly
  • opencv 2.4
  • python 2.7

在使用OpenCV處理視頻流時獲得更高FPS的“秘密”是將I / O(即,從相機傳感器讀取幀)移動到單獨的線程。

當調用read()方法和cv2.VideoCapture函數時,它會使整個過程非常慢,因為它必須等待每個I / O操作完成才能繼續下一個( 阻塞過程 )。

為了實現FPS增加/延遲減少,我們的目標是將幀的讀取從網絡攝像頭或USB設備移動到完全不同的線程,完全獨立於我們的主Python腳本。

這將允許從I / O線程連續讀取幀,同時我們的根線程處理當前幀。 一旦根線程完成處理它的幀,它只需要從I / O線程中獲取當前幀。 無需等待阻止I / O操作即可完成此操作。

您可以閱讀使用Python和OpenCV增加網絡攝像頭FPS以了解實現線程的步驟。


編輯

根據我們評論中的討論,我覺得您可以按如下方式重寫代碼:

import cv2

cv2.namedWindow("output")
cap = cv2.VideoCapture(0)

if cap.isOpened():              # Getting the first frame
    ret, frame = cap.read()
else:
    ret = False

while ret:
    cv2.imshow("output", frame)
    ret, frame = cap.read()
    key = cv2.waitKey(20)
    if key == 27:                    # exit on Escape key
        break
cv2.destroyWindow("output")

當我在英特爾Edison平台上使用OpenCV 2.4.9開展項目時,我遇到了類似的問題。 在進行任何處理之前,僅需要大約80ms來執行幀抓取。 事實證明,OpenCV的Linux攝像頭捕獲邏輯似乎沒有得到正確實現,至少在2.4.9版本中是這樣。 底層驅動程序只使用一個緩沖區,因此無法在應用程序層中使用多線程來解決它 - 直到您嘗試獲取下一幀,V4L2驅動程序中唯一的緩沖區被鎖定。

解決方案是不使用OpenCV的VideoCapture類。 也許修復了在某些時候使用合理數量的緩沖區,但從2.4.9開始,它不是。 事實上,如果你看一下條由同一作者通過@Nickil Maveli提供的鏈接,你會馬上發現,他提供了一種提高對樹莓派FPS的建議,他將停止使用的OpenCV的VideoCapture。 我不相信這是巧合。

以下是我在英特爾Edison論壇上發布的帖子: https//communities.intel.com/thread/58544

我基本上編寫了自己的類來處理幀抓取,直接使用V4L2。 這樣,您可以提供循環緩沖區列表,並允許幀抓取和應用程序邏輯正確解耦。 對於C ++應用程序,這在C ++中完成。 假設上述鏈接兌現了它的承諾,這可能是一種更容易的方法。 我不確定它是否適用於BeagleBone,但也許有類似於PiCamera的東西。 祝好運。

編輯:我看了一下OpenCV 2.4.11的源代碼。 看起來他們現在默認使用4個緩沖區,但您必須使用V4L2來利用它。 如果仔細查看錯誤消息HIGHGUI ERROR: V4L: Property... ,您會看到它引用的是V4L,而不是V4L2。 這意味着你正在使用的OpenCV的構建正在回歸舊的V4L驅動程序。 除了導致性能問題的單一緩沖區之外,您還使用了一個古老的驅動程序,它本身可能存在許多限制和性能問題。

您最好的選擇是自己構建OpenCV以確保它使用V4L2。 如果我沒記錯的話,OpenCV配置過程會檢查機器上是否安裝了V4L2驅動程序並相應地構建它,因此您需要確保在用於構建OpenCV的機器上安裝了V4L2和任何相關的開發包。

試試這個吧! 我替換了cap.set()部分中的一些代碼

import cv2
import time
cap=cv2.VideoCapture(0)
cap.set(3,640)
cap.set(4,480)
cap.set(5, 20)

a=30
t=time.time()
while (a>0):
        now=time.time()
        print now-t
        t=now
        ret,frame=cap.read()
        #Some processes
        print a,ret
        print frame.shape
        a=a-1
        k=cv2.waitKey(20)
        if k==27:
                break
cv2.destroyAllWindows()

輸出(電腦攝像頭)你的代碼對我來說是錯誤的。

>>0.0
>>30 True
>>(480, 640, 3)
>>0.246999979019
>>29 True
>>(480, 640, 3)
>>0.0249998569489
>>28 True
>>(480, 640, 3)
>>0.0280001163483
>>27 True
>>(480, 640, 3)
>>0.0320000648499

暫無
暫無

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

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