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。是雖然多線程的代碼多了點,但是從性能上來說,還是比單線程順序執行快不少,還是蠻值得的

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/260464.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/260464.shtml
英文地址,請注明出處:http://en.pswp.cn/news/260464.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Sharepoint學習筆記—Site Definition系列-- 2、創建Content Type

Sharepoint本身就是一個豐富的大容器,里面存儲的所有信息我們可以稱其為“內容(Content)”,為了便于管理這些Conent,按照人類的正常邏輯就必然想到的是對此進行“分類”。分類所涉及到的層面又必然包括: 1、分類的標準或特征描述{即&#xf…

arduino byte轉string_Java數組轉List集合的三駕馬車

點擊上方 藍字關注我們來源:blog.csdn.net/x541211190/article/details/79597236前言本文中的代碼命名有的可能不太規范,是因為沒法排版的問題,小仙已經很努力去解決了,希望各位能多多點贊、分享。好了,不多bb了(不要讓…

ES6筆記(4)-- Symbol類型

系列文章 -- ES6筆記系列 Symbol是什么?中文意思是標志、記號,顧名思義,它可以用了做記號。 是的,它是一種標記的方法,被ES6引入作為一種新的數據類型,表示獨一無二的值。 由此,JS的數據類型多了…

mysql類型說明_MYSQL 數據類型說明

MySQL支持大量的列類型,它可以被分為3類:數字類型、日期和時間類型以及字符串(字符)類型。本節首先給出可用類型的一個概述,并且總結每個列類型的存儲需求,然后提供每個類中的類型性質的更詳細的描述。概述有意簡化,更…

LeetCode OJ - Convert Sorted List to Binary Search Tree

題目: Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST. 解題思路: 注意是讓構造平衡二叉搜索樹。 每次將鏈表從中間斷開,分成左右兩部分。左邊部分用來構造左子樹&#xff…

手把手教你如下在Linux下如何寫一個C語言代碼,編譯并運行

文章目錄手把手教你如下在Linux下如何寫一個C語言代碼,編譯并運行打開Ubuntu終端創建 helloworld.c編譯C文件手把手教你如下在Linux下如何寫一個C語言代碼,編譯并運行 打開Ubuntu終端 我這里的終端是Windows下的WSL,如果有疑問,…

郵件群發工具的編寫(二)數據的保存

數據的保存與讀取 人類是在不斷探索與改進中進步的 上一篇,郵件群發工具的編寫(一)郵件地址提取,我們講到了郵箱的提取。 那么這一篇,講一下提取完的郵箱信息的保存和讀取。 首先,我希望對上一篇郵箱提取類…

mysql 文件描述符_MySQL沒有發布臨時文件描述符

幾天前,我們遇到了MySQL安裝的一些嚴重問題:MySQL不斷打開臨時文件(正常行為)但這些文件從未發布過.結果是,最終磁盤空間耗盡,我們必須重新啟動服務并手動清理/ tmp.使用lsof,我們看到這樣的事情:mysqld 16866 mysql 5u REG 8,3 0 692 /tmp/ibyWJylQ (de…

c++ lambda函數_C++11 之 lambda函數的詳細使用

1. lambda 函數概述lambda 表達式是一種匿名函數,即沒有函數名的函數;該匿名函數是由數學中的λ演算而來的。通常情況下,lambda函數的語法定義為:[capture] (parameters) mutable ->return-type {statement}其中:[c…

zabbix監控 openstack 的實例的資源使用情況

領導提出的需求:在不給云主機安裝客戶端的情況下,監控云主機的 cpui 內存 網絡 io,并且能出圖。想了幾個方案:1、ceilometer取數據,存入mangodb,用zabbix來讀mangodb數據繪圖2 ceilometer 取數據 &#xff…

pytorch 正向與反向傳播的過程 獲取模型的梯度(gradient),并繪制梯度的直方圖

記錄一下怎樣pytorch框架下怎樣獲得模型的梯度 文章目錄引入所需要的庫一個簡單的函數模型梯度獲取先定義一個model如下定義兩個獲取梯度的函數定義一些過程與調用上述函數的方法可視化一下梯度的histogram引入所需要的庫 import os import torch import torch.nn as nn impor…

2012-9

響應式設計的典范 http://www.bostonglobe.com/ 網站測試頁面 http://www.webpagetest.org/ 編程算法 http://blog.sina.com.cn/s/articlelist_1647038822_1_1.html C Programmers Cookbook http://www.cppblog.com/mzty/category/7609.html Blade 是一個現代構建系統&#xff…

PV操作 (轉載)

PV操作與信號量的處理相關,P表示通過的意思,V表示釋放的意思。信號量是最早出現的用來解決進程同步與互斥問題的機制,包括一個稱為信號量的變量及對它進行的兩個原語操作。 信號量(semaphore)的數據結構為一個值和一個…

ubuntu升級python_Ubuntu 升級python3為更高版本【已實測】

2020-04-13 更新安裝步驟: 1. 先update一下 sudo apt update 2. 安裝依賴庫 sudo apt-get install zlib1g-dev libbz2-dev libssl-dev libncurses5-dev libsqlite3-dev libreadline-dev tk-dev libgdbm-dev libdb-dev libpcap-dev xz-utils libexpat1-dev liblzma-d…

mysql5.0 java連接_Java連接mysql5.0

網上的資料真爛,千篇一律的拷貝的,根本不能用,鄙視! 正題: 到MYSQL網站下載mysql-connector-java-5.0.4.zip文件,解壓; 解壓后有一個文件:mysql-connector-java-5.0.4-bin.jar 把這個…

Framework打包

2019獨角獸企業重金招聘Python工程師標準>>> iOS app需要在許多不同的CPU架構下運行: arm7: 在最老的支持iOS7的設備上使用 arm7s: 在iPhone5和5C上使用 arm64: 運行于iPhone5S的64位 ARM 處理器 上 i386: 32位模擬器上使用 x86_64: 64為模擬器上使用…

windows 10 下利用WSL的Linux環境實現vscode C/C++環境的配置

本文主要結合二個工具,介紹如何在windows搭建Linux開發環境: WSL(Windows Subsystem for Linux)VSCode(Visual Studio Code) 文章目錄WSL安裝VSCode安裝配置Linux下的C/C環境1. 打開WSL的控制臺2. 更新ubuntu軟件3. 安裝GCC和GDB4. 配置VSCode(1). 打開…

java類初始化順序

轉自:http://zangweiren.iteye.com/blog/208122 對于靜態變量、靜態初始化塊、變量、初始化塊、構造器,它們的初始化順序以此是(靜態變量、靜態初始化塊)>(變量、初始化塊)>構造器。我們也可以通過下…

Java 8 - Interface Default Method接口默認方法

Java 8 相比于Java 7 推出了幾大特色(features)(接口默認方法)default methods in interface, (接口靜態方法)static method in interface, 函數編程(functional programming), lamda expression, stream API.這里首先…

Windows 11下 WSL使用 jupyter notebook

這里寫目錄標題前言在WSL下的配置測試運行更優雅的啟動方法配置jupyter生成默認配置文件生成秘鑰修改配置文件nohup啟動前言 一直都使用jupyter notebook,不管做數據分析,還是調試代碼,還有寫文章都是。但是好像在WSL下又不好使。看了網上有…