![](/img/trans.png)
[英]MTCNN_face_detection_alignment lagging in IP camera, Convention behind opencv cv2 videocapture frame matrix
[英]OpenCV (cv2 in Python) VideoCapture not releasing camera after deletion
我對 Python 比較陌生,剛剛在過去一個月左右的時間里學習了它,並根據我在網上找到的示例和其他人的代碼將其一起破解。
我得到了一個 Tkinter GUI 來將來自網絡攝像頭的提要顯示為畫布上不斷更新的圖像循環。 每隔一次退出 GUI 並重新運行腳本會導致此錯誤:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1410, in __call__
return self.func(*args)
File "C:\Python27\lib\lib-tk\Tkinter.py", line 495, in callit
func(*args)
File "C:\...\cv2_cam_v8.py", line 20, in update_video
(self.readsuccessful,self.f) = self.cam.read()
SystemError: NULL object passed to Py_BuildValue
當錯誤發生時,不會讀取任何圖像,視頻源也不會收到任何圖像來更新畫布。 腳本第一次和第二次都正常運行,沒有錯誤。 從之前使用 cv2 模塊中的 VideoCapture 函數進行的測試中,我發現我必須刪除相機對象才能釋放它,以便后續運行能夠毫無問題地捕獲相機流。 通過在控制台中輸入who
來檢查命名空間不顯示cam
所以我知道它在 GUI 關閉后被正確刪除。 我不明白為什么 cv2 的 read 函數會出錯。 我認為它只會每兩次發生一次,因為當錯誤發生時,一些垃圾收集或錯誤處理會刪除或釋放與相機有關的東西,但我不知道這是什么......
這是我的代碼:
import cv2
import Tkinter as tk
from PIL import Image, ImageTk
class vid():
def __init__(self,cam,root,canvas):
self.cam = cam
self.root = root
self.canvas = canvas
def update_video(self):
(self.readsuccessful,self.f) = self.cam.read()
self.gray_im = cv2.cvtColor(self.f, cv2.COLOR_RGB2GRAY)
self.a = Image.fromarray(self.gray_im)
self.b = ImageTk.PhotoImage(image=self.a)
self.canvas.create_image(0,0,image=self.b,anchor=tk.NW)
self.root.update()
self.root.after(33,self.update_video)
if __name__ == '__main__':
root = tk.Tk()
videoframe = tk.LabelFrame(root,text='Captured video')
videoframe.grid(column=0,row=0,columnspan=1,rowspan=1,padx=5, pady=5, ipadx=5, ipady=5)
canvas = tk.Canvas(videoframe, width=640,height=480)
canvas.grid(column=0,row=0)
cam = cv2.VideoCapture(2)
x = vid(cam,root,canvas)
root.after(0,x.update_video)
button = tk.Button(text='Quit',master=videoframe,command=root.destroy)
button.grid(column=0,row=1)
root.mainloop()
del cam
像這樣重構代碼:
def update_video(cam,root,canvas):
(readsuccessful,f) = cam.read()
gray_im = cv2.cvtColor(f, cv2.COLOR_RGB2GRAY)
a = Image.fromarray(gray_im)
b = ImageTk.PhotoImage(image=a)
canvas.create_image(0,0,image=b,anchor=tk.NW)
root.update()
root.after(33,update_video(cam,root,canvas))
if __name__ == '__main__':
root = tk.Tk()
videoframe = tk.LabelFrame(root,text='Captured video')
videoframe.grid(column=0,row=0,columnspan=1,rowspan=1,padx=5, pady=5, ipadx=5, ipady=5)
canvas = tk.Canvas(videoframe, width=640,height=480)
canvas.grid(column=0,row=0)
cam = cv2.VideoCapture(2)
root.after(0,update_video(cam,root,canvas))
button = tk.Button(text='Quit',master=videoframe,command=root.destroy)
button.grid(column=0,row=1)
root.mainloop()
del cam
不在 GUI 中顯示按鈕並在關閉窗口后出現此錯誤:
RuntimeError: Too early to create image
我有3個問題
1 -
如何防止任何異常?
更新:將“root.after(0,update_video(cam,root,canvas))”更改為“root.after(0,lambda: update_video(cam,root,canvas))”和“update_video(cam,root,canvas)” " 到 "update_video(cam,root,canvas,event=None)" 或使用以下格式將參數傳遞給回調: "root.after(time_to_wait, callback, arguments, master)" 修復了第二個錯誤(以及我做過的其他錯誤)不張貼)。 同樣正如 kobejohn 所指出的,添加一個 try: except 塊也修復了第二個錯誤。 有關更多詳細信息,請參閱他的回答。
2 -
cv2 中是否有比 .read() 更快、更有效的函數?
編輯:有沒有辦法重構我的代碼以獲得更高的幀率?
read 函數是文檔中唯一列出的函數,我只是在某處讀到,如果它不在文檔中,則它不可用。
這種方法只給我大約 5fps,其中 10-20fps 會更容易接受。
更新:從 kobejohn 的測試和我的不同相機的測試之間的差異來看,低幀率是網絡攝像頭質量差的結果。 質量更好的網絡攝像頭產生更高的幀率。
3 -
我一直在讀應該盡可能避免 update() 但是我如何讓畫布重新繪制圖像(或使用此代碼實現 update_idletasks() )?
我必須實現某種線程還是可以避免這種情況?
更新:我已經讓代碼在不使用 update() 方法的情況下工作,但無論如何必須考慮實現線程,因為當我從主 GUI 的按鈕開始錄制視頻時,它會凍結/變得無響應。
完成的程序將用於 Ubuntu 和 Windows(也可能在 Mac 上)。 我運行的是 Windows 7,IDE 是 Spyder 2.1.11(Python 2.7.3)。
在此先感謝您,任何建議和/或解決方案將不勝感激!
問候,
S. Chia
解決了! Python 中的 OpenCV 2.4.2/ cv2
由於一些奇怪的原因,我之前和其他論壇都找不到'release'方法,頁面特別提到opencv的python綁定不包含release方法。 也許這僅在使用“導入 cv”時適用。 我使用后者進行了最初的原型設計,但由於某種原因,我在尋找 ReleaseCapture 方法時錯過了 cv2 中的“release”方法。
剛剛在文檔中找到它: http : //docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html
import cv2
cam=cv2.VideoCapture(0)
cam.release
你能試試這個代碼,看看你得到了多少 FPS? 我包括了 FPS 計算,以便我們可以比較筆記。 (編輯:還有什么錯誤。我沒有得到你在原始代碼中得到的錯誤,我在下面的代碼中得到零錯誤)
我從頭開始只是想看看我是否想出了一些不同的東西。 有一些區別:
cv2.COLOR_RGB2GRAY
--> cv2.COLOR_BGR2GRAY
更改您的灰度轉換。 您可以在VideoCapture 示例中看到它們做了類似的事情。使用此代碼,我在 Windows 7 上獲得 15 FPS 且沒有錯誤:
from collections import deque
import cv2
import Image, ImageTk
import time
import Tkinter as tk
def quit_(root):
root.destroy()
def update_image(image_label, cam):
(readsuccessful, f) = cam.read()
gray_im = cv2.cvtColor(f, cv2.COLOR_BGR2GRAY)
a = Image.fromarray(gray_im)
b = ImageTk.PhotoImage(image=a)
image_label.configure(image=b)
image_label._image_cache = b # avoid garbage collection
root.update()
def update_fps(fps_label):
frame_times = fps_label._frame_times
frame_times.rotate()
frame_times[0] = time.time()
sum_of_deltas = frame_times[0] - frame_times[-1]
count_of_deltas = len(frame_times) - 1
try:
fps = int(float(count_of_deltas) / sum_of_deltas)
except ZeroDivisionError:
fps = 0
fps_label.configure(text='FPS: {}'.format(fps))
def update_all(root, image_label, cam, fps_label):
update_image(image_label, cam)
update_fps(fps_label)
root.after(20, func=lambda: update_all(root, image_label, cam, fps_label))
if __name__ == '__main__':
root = tk.Tk()
# label for the video frame
image_label = tk.Label(master=root)
image_label.pack()
# camera
cam = cv2.VideoCapture(0)
# label for fps
fps_label = tk.Label(master=root)
fps_label._frame_times = deque([0]*5) # arbitrary 5 frame average FPS
fps_label.pack()
# quit button
quit_button = tk.Button(master=root, text='Quit',
command=lambda: quit_(root))
quit_button.pack()
# setup the update callback
root.after(0, func=lambda: update_all(root, image_label, cam, fps_label))
root.mainloop()
在 opencv 中初始化相機對象之前設置環境變量。
os.environ['OPENCV_VIDEOIO_PRIORITY_MSMF'] = '0'
即使在我的代碼中關閉相機對象后,這也釋放了相機。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.