如何使用Vimba Python异步抓取Allied Vision相机的帧并按需调用?
实现Vimba Python异步抓帧并通过队列按需获取
要实现异步抓帧并将帧存入队列按需获取,核心是利用Vimba的帧回调机制,配合线程安全的队列来缓存处理后的帧。以下是完整的实现方案:
关键思路
- 注册回调函数:相机每抓取一帧就触发该函数,在回调中完成帧转numpy数组、存入队列的操作,同时必须将帧归还给相机的帧池(避免内存耗尽)。
- 使用线程安全队列:由于回调函数运行在Vimba的内部线程中,主线程获取帧时需要线程安全的容器(比如
queue.Queue)。 - 按需消费:主线程可以从队列中阻塞/非阻塞获取帧,处理逻辑和抓帧逻辑完全解耦。
完整代码示例
import vimba import numpy as np import queue import time # 初始化线程安全队列,设置最大容量避免内存溢出 frame_queue = queue.Queue(maxsize=20) def frame_callback(frame: vimba.Frame): """相机帧回调函数:处理帧并存入队列""" try: # 将帧转换为numpy数组,注意这里要复制数组,否则后续帧会覆盖buffer内容 img = np.ndarray( buffer=frame._buffer, dtype=np.uint16, shape=(frame.height, frame.width) ).copy() # 将处理后的帧存入队列,若队列满则阻塞等待 frame_queue.put(img) finally: # 必须将帧归还给相机帧池,否则相机将无法继续抓取新帧 frame.queue() def main(): with vimba.Vimba.get_instance() as vimba_instance: # 枚举并打开相机(这里默认取第一个相机,可根据需要修改) cams = vimba_instance.get_all_cameras() if not cams: print("未找到相机") return with cams[0] as cam: # 配置相机参数(根据你的需求调整,比如像素格式、帧率等) cam.set_pixel_format(vimba.PixelFormat.Mono16) # 设置抓帧模式为异步,buffer_count为预分配的帧缓存数量 cam.start_streaming(callback=frame_callback, buffer_count=10) try: # 按需获取帧示例:这里模拟获取10帧并处理 for _ in range(10): # 阻塞等待队列中有帧 img = frame_queue.get() # 这里添加你的帧处理逻辑 print(f"获取到帧,尺寸:{img.shape}") # 标记任务完成(若使用队列的join()方法则需要) frame_queue.task_done() # 模拟处理耗时 time.sleep(0.1) finally: # 停止流传输,清理资源 cam.stop_streaming() # 等待队列中所有帧处理完成(可选) frame_queue.join() if __name__ == "__main__": main()
重要注意事项
- 必须归还帧:回调函数的
finally块中一定要调用frame.queue(),否则相机的帧池会被耗尽,导致无法继续抓帧。 - 数组复制:转换numpy数组时要调用
.copy(),因为Vimba的帧buffer是复用的,若不复制,后续新帧会覆盖当前数组的内容。 - 队列容量:设置
maxsize避免队列无限增长导致内存占用过高,当队列满时,frame_queue.put()会阻塞,直到队列有空闲位置。 - 相机参数匹配:根据相机型号和需求调整像素格式,确保和转换numpy数组时的
dtype对应(比如Mono16对应np.uint16)。
内容的提问来源于stack exchange,提问作者Eloi Canals Pascual
相关产品推荐
相关产品推荐

