我不斷地從 Python 中的 OpenCV 相機讀取影像并從主程式中讀取最新影像。這是需要的,因為有問題的硬體。
在搞亂執行緒并獲得非常低的效率(呃!)之后,我想切換到多處理。
這是執行緒版本:
class WebcamStream:
# initialization method
def __init__(self, stream_id=0):
self.stream_id = stream_id # default is 0 for main camera
# opening video capture stream
self.camera = cv2.VideoCapture(self.stream_id)
self.camera.set(cv2.CAP_PROP_FRAME_WIDTH, 3840)
self.camera.set(cv2.CAP_PROP_FRAME_HEIGHT, 2880)
if self.camera.isOpened() is False:
print("[Exiting]: Error accessing webcam stream.")
exit(0)
# reading a single frame from camera stream for initializing
_, self.frame = self.camera.read()
# self.stopped is initialized to False
self.stopped = True
# thread instantiation
self.t = Thread(target=self.update, args=())
self.t.daemon = True # daemon threads run in background
# method to start thread
def start(self):
self.stopped = False
self.t.start()
# method passed to thread to read next available frame
def update(self):
while True:
if self.stopped is True:
break
_, self.frame = self.camera.read()
self.camera.release()
# method to return latest read frame
def read(self):
return self.frame
# method to stop reading frames
def stop(self):
self.stopped = True
和 -
if __name__ == "__main__":
main_camera_stream = WebcamStream(stream_id=0)
main_camera_stream.start()
frame = main_camera_stream.read()
有人可以幫我把它翻譯成多行程土地嗎?
謝謝!
uj5u.com熱心網友回復:
我已經為類似問題撰寫了幾個解決方案,但是已經有一段時間了,所以我們開始吧:
我將shared_memory用作緩沖區來讀取幀,然后可以由另一個行程讀取。我的第一個傾向是在子行程中初始化相機并讀取幀,因為這似乎是一種“設定它并忘記它”的事情。
from multiprocessing import Process, Lock, Queue
from multiprocessing.shared_memory import SharedMemory
import cv2
import numpy as np
from time import sleep
class Shared_Arr: #helper class to make shared_memory arrays easier <https://stackoverflow.com/a/71769491/3220135>
def __init__(self, shape, dtype, shm=None):
self.shape=shape
self.dtype=dtype
if shm is None:
n_bytes = int(np.dtype(dtype).itemsize * np.prod(shape))
self.shm = SharedMemory(create=True, size=n_bytes)
self.owner = True
else:
self.shm = shm
self.owner = False
self.close = self.shm.close
self.unlink = self.shm.unlink
self.arr = np.ndarray(self.shape, self.dtype, buffer=self.shm.buf)
def __reduce__(self): #make it picklable so it can be sent to a child process correctly
return (self.__class__, (self.shape, self.dtype, self.shm))
def __enter__(self): #context manager is mostly for cleanup so __enter__ is uninteresting
return self
def __exit__(self, exc_type, exc_value, traceback):
self.close() #closes the memory-mapped file
if self.owner:
self.unlink() #tell the OS to delete the file
class Frame_Producer(Process):
def __init__(self):
super().__init__()
self.q = Queue()
self.l = Lock()
self.daemon = True
def run(self):
vid_device = r"D:\Videos\movies\GhostintheShell.mp4" #a great movie
#get the first frame to calculate size
cap = cv2.VideoCapture(vid_device)
success, frame = cap.read()
if not success:
raise Exception("error reading from video")
with Shared_Arr(frame.shape, frame.dtype) as framebuffer:
self.q.put(framebuffer) #send back to main #if we knew the frame size in advance we could simplify this process by creating it in main
try:
while True:
sleep(1/30) #video framerate
with self.l: #lock the framebuffer while we write to it
cap.read(framebuffer.arr)
except KeyboardInterrupt: #this gets propogated from the parent on some systems, making "daemon" redundant
pass
def start(self):
super().start()
self.framebuffer = self.q.get()
def __enter__(self):
self.start()
return self
def __exit__(self, exc_type, exc_value, traceback):
self.framebuffer.__exit__(exc_type, exc_value, traceback) #cleanup
self.terminate()
def get(self):
with self.l:
return np.copy(self.framebuffer.arr) #return a copy which won't be overwritten unexpectedly
if __name__ == "__main__":
with Frame_Producer() as fp:
try:
while True:
cv2.imshow("frame", fp.get())
cv2.waitKey(1000) #main process consumes frames more slowly than producer process provides them
except KeyboardInterrupt:
pass
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/485004.html
上一篇:由response.download()回應的檔案并下載為包含未定義的blob
下一篇:多執行緒編程更慢
