多线程实现摄像头读取和显示
实现多线程的摄像头的视频读取和显示,两个线程同步并行处理
from multiprocessing import Process,Queue,shared_memory,Value
import cv2
import numpy as np
class CameraBroadcaster:
def __init__(self, camera_info):
self.height = camera_info.get('height', 720)
self.width = camera_info.get('width', 1280)
self.fps = camera_info.get('fps', 30)
self.id = camera_info.get("id",0)
self.stop_sign = Value(c_bool, False)
#关键代码,在对象内存中开辟一个空间用于存储图像
self.frame = shared_memory.SharedMemory(create=True, size=np.zeros(shape=(self.height, self.width, 3),
dtype=np.uint8).nbytes)
self.memory_name = self.frame.name
def run(self,data_value):
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, self.width)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, self.height)
sender = np.ndarray((self.height, self.width, 3), dtype=np.uint8, buffer=self.frame.buf)
print("finish open the camera")
try:
while True:
if self.stop_sign.value:
self.frame.close()
self.frame.unlink()
break
ret, frame = cap.read()
#将获得的图像,保存在共享内存中
np.copyto(sender,frame)
data_value.value = True
end2 = datetime.now()
except (KeyboardInterrupt, SystemExit):
# log.info('Cam broadcaster closing')
self.frame.close()
self.frame.unlink()
代码测试
def test_multi_camera(camera_info):
msg_queue = Queue()
camera = CameraBroadcaster(camera_info)
data_value = Value('b',False)
camera_process = Process(target=camera.run,args=(data_value,))
camera_process.start()
print(camera_info)
while cv2.waitKey(1) == -1:
# if not data_value.value:
# continue
#
#必须从camera对象中获取内存,如果有内容,则直接访问,之后边自助释放
frame = np.ndarray((camera.height, camera.width, 3), dtype=np.uint8, buffer=camera.frame.buf)
img = frame.copy()
data_value.value = False
camera_process.join()
下面进行升级,需要将读取的图像放入到缓存buffer中,然后另一个线程就行处理。
import cv2
import numpy as np
from multiprocessing import Queue
from threading import Thread
class BaseThreadedProcess(Thread):
def __init__(self, queue):
super(BaseThreadedProcess, self).__init__()
self.queue = queue
def run(self):
raise NotImplementedError("Subclasses must implement the 'run' method.")
class CameraReader(BaseThreadedProcess):
def __init__(self, queue):
super(CameraReader, self).__init__(queue)
def run(self):
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if not ret:
break
# 将图像数据放入队列
self.queue.put(frame)
cap.release()
class FrameProcessor(BaseThreadedProcess):
def __init__(self, queue):
super(FrameProcessor, self).__init__(queue)
def run(self):
while True:
# 从队列中获取图像数据
frame = self.queue.get()
# 在这里可以进行任意图像处理操作
# 这里只是简单地将图像转换为灰度图像
gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 在这里显示处理后的图像
cv2.imshow("Processed Frame", gray_frame)
# 检测键盘输入,按下"q"键退出循环
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
if __name__ == "__main__":
# 创建队列
frame_queue = Queue()
# 创建线程,并将共享队列传递给两个线程实例
camera_reader = CameraReader(frame_queue)
frame_processor = FrameProcessor(frame_queue)
# 启动线程
camera_reader.start()
frame_processor.start()
# 等待线程结束
camera_reader.join()
frame_processor.join()
重点讲解了线程的继承和队列的使用。