【发布时间】:2020-07-20 09:43:14
【问题描述】:
我开发了一个 Python 多线程程序,一个生产者线程以高 fps(大约 75 fps)获取帧(512 x 640, 16uint),两个消费者线程,一个用于实时可视化,另一个用于保存为 16 位 tiff。对于每个消费者,我使用不同的队列。
实时可视化效果很好,但在视频停止后保存需要很长时间(2 分钟的录制甚至需要 20 秒)。为了保存,我使用了 tifffile 库或 cv2,具有类似的性能。
更新信息
图像是灰度 16 位 numpy 数组,直接放入队列中,不压缩,使用 tifffile.imsave 保存。可视化的第二个队列实时正常工作,因此保存必须是最慢的过程。我需要独立保存每张图像,保存 3D 暂时不是一个选项。使用不同的线程进行保存可能会破坏我的采集顺序。
考虑到我需要以与记录相同的顺序保存它们,有什么方法可以在 Python 和/或 OS (windows10) 中加速该过程?我有一个 SSD 970 EVO 磁盘驱动器
class VideoGet():
def __init__(self,input_dict,folder,record):
self.handle=input_dict['handle']
self.frame_t=input_dict['frametype']
self.frameSize= input_dict['frameSize']
# self.buffer = np.zeros(shape=(513,640), dtype=np.uint16)
self.record = record
self.save = False
self.done=False
self.counter=0
self.folder = folder
def displayer(self,q2):
while self.record is True:
if q2.empty() is True:
pass
else:
framedisplay = q2.get()
cv2.namedWindow("Video", cv2.WINDOW_NORMAL)
cv2.imshow("Video", framedisplay[:-1,:])
cv2.waitKey(1)
q2.task_done()
cv2.destroyAllWindows()
def consumer(self,q):
data=[]
while True:
if q.empty():
time.sleep(0.002)
pass
else:
frame_get = q.get()
if frame_get is None:
print('gone')
break
imsave(os.path.join(self.folder,(str(self.counter).zfill(5)+'.tiff')), frame_get[:-1,:])
if self.counter==0:
TS=1.0e-3 *struct.unpack('Q',(frame_get[-1,6:10]).tobytes())[0]
entr=[str(self.counter).zfill(5),str(round(1.0e3*(1.0e-3 *struct.unpack('Q',(frame_get[-1,6:10]).tobytes())[0]-TS)))]
data.append(entr)
self.counter=self.counter+1
q.task_done()
if data:
df = pd.DataFrame(data, columns = ['Picture', 'Timestamp'])
df.to_csv(os.path.join(self.folder,'timestamps.txt'), header=False, index=False, sep=' ')
print('done')
self.done=True
def producer(self,buffer,q,q2):
while self.record is True:
buffer=np.empty_like(buffer)
if camera.properties.get_frame(self.handle,self.frame_t,4,buffer,self.frameSize)==0:
frame=buffer
q2.put(frame)
if self.save is True:
q.put(frame)
del frame
print('None')
q.put(None)
def run(self,buffer,q,q2):
prod_thread=Thread(target=self.producer,args=(buffer,q,q2,))
display_thread=Thread(target=self.displayer,args=(q2,))
con_thread= Thread(target=self.consumer, args=(q,))
prod_thread.start()
display_thread.start()
con_thread.start()
【问题讨论】:
-
请添加更多详细信息。你如何使用tifffile?你使用压缩吗?您知道创建 TIFF 文件时的图像数量吗?使用 TiffWriter.save 连续追加未压缩的图像应该接近 C stdlib I/O 速度。还要确保将 TIFF 文件排除在(例如)按访问病毒扫描、索引服务和资源管理器预览之外。
-
请添加更多详细信息。您的图像是彩色的还是灰度的?您是否尝试过运行 2、3 或 4 个 TIFF 写入器线程来读取共享队列?您是在队列中传递整个图像还是只是一个更快的缓冲区地址?你确定是 TIFF 写作让你放慢了速度,而不是排队?
-
@cgohlke 信息已更新
-
从两个线程中保存会如何改变获取的顺序?您的采集线程确定是按顺序一个接一个地获取图像吗?
-
tifffile.imsave有很多的开销。我已经提到,使用TiffWriter.save将未压缩的图像连续附加到同一个文件应该与使用 tifffile 一样快。
标签: python multithreading image save tiff