日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python 多线程并发编程(生产者、消费者模式),边读图像,边处理图像,处理完后保存图像实现提高处理效率

發布時間:2023/12/10 python 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python 多线程并发编程(生产者、消费者模式),边读图像,边处理图像,处理完后保存图像实现提高处理效率 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 需求
    • 實現
      • 先導入本次需要用到的包
      • 一些輔助函數
        • 如下函數是得到指定后綴的文件
        • 如下的函數一個是讀圖像,一個是把RGB轉成BGR
      • 下面是主要的幾個處理函數
      • 在上面幾個函數構建對應的處理函數
      • main函數
      • 按順序執行
    • 結果

需求

本次的需求是邊讀圖像,邊處理圖像(各種變組合),處理完后還要把處理好的圖像保存到指定的文件夾。而且圖像也挺多的,如果按順序一個一個處理,那肯定要不少時間。所以就想到了多線程并發編程。

實現

先導入本次需要用到的包

import os import threading from queue import Queue import cv2

一些輔助函數

如下函數是得到指定后綴的文件

IMG_EXTENSIONS = ('.jpg', '.jpeg', '.png', '.ppm', '.bmp', '.pgm', '.tif', '.tiff', '.webp')def get_all_files(base, extensions):"""get all files in extensions from base folder, it's a generator"""for root, _, files in sorted(os.walk(base, followlinks=True)):for file in sorted(files):if file.endswith(extensions):yield os.path.join(root, file)def get_all_images(base, image_extensions):"""get all images"""return get_all_files(base, image_extensions)

如下的函數一個是讀圖像,一個是把RGB轉成BGR

def default_loader_cv2(path):return cv2.cvtColor(cv2.imread(path), cv2.COLOR_BGR2RGB)def rgb_2_bgr(img):return cv2.cvtColor(img, cv2.COLOR_RGB2BGR)

下面是主要的幾個處理函數

def load_image(target_dir, source_file):"""load image here"""target_file = get_save_path(target_dir, source_file)img = default_loader_cv2(source_file)return (target_file, img)def transform(stain_normalizer, img):"""Description:- transform image method, basic resize here, you could do other transform here"""return cv2.resize(img, (256, 256))def save(save_path, img):"""save image method"""cv2.imwrite(save_path, rgb_2_bgr(img))

在上面幾個函數構建對應的處理函數

def do_load_image(load_queue: Queue, trainsform_queue: Queue, target_dir:str):while True:file = load_queue.get()if file is None: breaktarget_file = os.path.join(target_dir, source_file)if not os.path.exists(target_file): # skip all the transformed imagesimg = default_loader_cv2(file)trainsform_queue.put((target_file, img))else:passdef do_transforms(trainsform_queue: Queue, save_queue: Queue, stain_normalizer):while True:data = trainsform_queue.get()if data is None: breaktarget_file, img = dataimg_norm = transform(stain_normalizer, img)save_queue.put((target_file, img_norm))def do_save(save_queue:Queue):while True:data = save_queue.get()if data is None: breaktarget_file, img_norm = datasave(target_file, img_norm)

main函數

在這里,是整個程度的啟動,特別注意線程的啟動與結束順序,不要搞錯了,不然程序會進行死循環。
一般生產者消費者,大家看到的都是只有兩個函數(一個生產者,一個消費者),這里實行的是3個函數,load是transform的生產者,transform是save的生產者,這里利用隊列實行了3個隊列,實行了數據間的傳遞。可以利用這種思想實行更多層級的生產者與消費者模式。

def main(source_dir, target_dir):# 4104 image, took 224.6297sfiles = get_all_images(source_dir, IMG_EXTENSIONS) # generator could only be iterated 1 time# transform will be the slowest, so load queue would be too much data if you donot maximizeload_queue = Queue(maxsize=5000) trainsform_queue = Queue()save_queue = Queue()for file in files:load_queue.put(file)# start load_threadsload_threads = []for _ in range(2):t = threading.Thread(target=do_load_image,args=(load_queue, trainsform_queue, target_dir))t.start()load_threads.append(t)# start transform_threadstransform_threads = []for _ in range(6):t = threading.Thread(target=do_transforms,args=(trainsform_queue, save_queue, stain_normalizer))t.start()transform_threads.append(t)# start save_threadssave_threads = []for _ in range(4):t = threading.Thread(target=do_save,args=(save_queue,))t.start()save_threads.append(t)# put sentinel load_threads to break the loop# DONOT put thread.join() under this loopfor _ in load_threads:load_queue.put(None)for thread in load_threads:thread.join()# put sentinel transform_threads to break the loop# DONOT put thread.join() under this loopfor thread in transform_threads:trainsform_queue.put(None)for thread in transform_threads:thread.join()# put sentinel transform_threads to break the loop# DONOT put thread.join() under this loopfor thread in save_threads:save_queue.put(None)for thread in save_threads:thread.join()

按順序執行

def single_thread(source_dir, target_dir):# 4104 image, took 486.4547sfiles = get_all_images(source_dir, IMG_EXTENSIONS)for file in files:target_file, img = load_image(target_dir, file)img_transform = transform(stain_normalizer, img)save(target_file, img_transform)

結果

從代碼來看,單線程的順序執行比多線程少不小的代碼,而且結果也相對簡單,基本上不會出什么問題。然后單線程的所要花費的時間卻是多線程的2倍還要多。圖像一共是4104張512x512的3通道png圖像。單線程花費時間是486.4547s,而多線程花費時間是224.6297s。是雖然多線程的代碼多了點,但是從性能上來說,還是比單線程順序執行快不少,還是蠻值得的

總結

以上是生活随笔為你收集整理的python 多线程并发编程(生产者、消费者模式),边读图像,边处理图像,处理完后保存图像实现提高处理效率的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。