[英]Accessing Beaglebone python opencv usb camera but the display showing black screen
[英]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
組態:
在使用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.