簡體   English   中英

在磁盤上更快地保存圖像

[英]Saving images faster on disk

我開發了一個 Python 多線程程序,一個生產者線程以高 fps(約 75 fps)獲取幀(512 x 640、16uint),以及兩個消費者線程,一個用於實時可視化,另一個用於保存為 16 -bit tiff。 對於每個消費者,我使用不同的隊列。

實時可視化效果很好,但在視頻停止后保存需要很長時間(2 分鍾的錄制甚至需要 20 秒)。 為了保存,我使用了具有類似性能的 tifffile 庫或 cv2。

更新信息

圖片為灰度16位numpy arrays直接放入隊列,不壓縮,使用tifffile.imsave保存。 可視化的第二個隊列實時正常工作,因此保存必須是最慢的過程。 我需要獨立保存每張圖片,保存 3D 暫時不是一個選項。 使用不同的線程進行保存可能會破壞我的采集順序。

考慮到我需要以與記錄相同的順序保存它們,有什么方法可以在 Python 和/或操作系統(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()

當您不顯示代碼時,很難說出了什么問題。 此外,我不清楚為什么如果您有多個作家,收購順序會改變。

這是一個腳本,用於生成與圖像大小相同的合成幀,並將它們按順序保存為 TIFF 文件。 它的速度隨着更多編寫器線程的增加而呈線性增長:

NFRAMES      NWRITERS       TIME(s)
1000            1             1.48
1000            2             0.78
1000            4             0.48

#!/usr/bin/env python3

import time
import numpy as np
import threading, queue
from tifffile import imsave

def writer(q):
    print('[WRITER] Started')
    total = 0
    while True:
        (frameNum, im) = q.get()
        if frameNum < 0:
            break
        # Save as TIFF
        imsave(f'frame-{frameNum}.tif', im)
        total += 1
    print(f'[WRITER] Complete: wrote {total} frames')

if __name__ == "__main__":

    # Edit these to suit
    NFRAMES = 1000
    NWRITERS= 4

    # Create dummy image of correct size
    h, w = 640, 512
    im = np.random.randint(0, 65536, (h,w), dtype=np.uint16)

    # Create a queue to pass frames to writer(s)
    q = queue.Queue(16)

    print('[MAIN] Started')
    start = time.time()

    # Create and start writer thread(s)
    threads = []
    for _ in range(NWRITERS):
        t = threading.Thread(target=writer, args=(q,))
        t.start()
        threads.append(t)

    # Generate a large number of frames to store
    for frameNum in range(NFRAMES):
        # Put a tuple of frameNum and image in queue
        q.put((frameNum, im))

    # Sentinel to tell each writer to exit
    for _ in range(NWRITERS):
        q.put((-1,-1))

    # Wait for our writer thread(s) to exit
    for thread in threads:
       thread.join()

    elapsed = time.time() - start;
    print(f'[MAIN] Complete: {NFRAMES} frames, with {NWRITERS} writers in {elapsed} seconds')

樣品 Output

[MAIN] Started
[WRITER] Started
[WRITER] Started
[WRITER] Started
[WRITER] Started
[WRITER] Complete: wrote 250 frames
[WRITER] Complete: wrote 250 frames
[WRITER] Complete: wrote 250 frames
[WRITER] Complete: wrote 250 frames
[MAIN] Complete: 1000 frames, with 4 writers in 0.4869719505310059 seconds

我注意到的一件事是,如果將tifffile.imsave()替換為:

np.save(f'frame-{frameNum}.npy', im)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM