Python多进程加快图片读取速度、多进程下图片的有序读取(mp.Queue)

news2025/1/18 6:49:30

Python多进程加快图片读取速度(mp.Queue)

多进程,加快图片读取,多进程下图片的有序读取,Python,multiprocessing,multiprocessing.Queue,opencv-python

  • 文章结构

    • 快速使用,多进程读取图片(简化版)
    • 影响读取速度的瓶颈(CPU 与磁盘)
    • 多进程读取图片(完整版):有序读取、图片检查

1.快速使用,多进程读取图片(简化版)

黑色加粗的地方,是文件夹路径,请自行修改,图片为 jpg 格式,可以直接复制运行一下,体验一下磁盘占用率 100% 的感觉。

这里用到了 python3 自带的 multiprocessing.Queue 完成多进程的实现,如果你想先对 multiprocessing 有一定的了解,可以先看我的另一篇文章(还没写,有人催我就写)——multiprocessing 简单使用

import os
import multiprocessing as mp

import cv2
import numpy as np

'''
2018-07-05 Yonv1943 show file images, via multiprocessing
2018-09-04 use multiprocessing for loading images
2018-09-05 add simplify
'''


def img_load(queue, queue_idx__img_paths):
    while True:
        idx, img_path = queue_idx__img_paths.get()
        img = cv2.imread(img_path)  # Disk IO
        queue.put((img, idx, img_path))


def img_show(queue, window_name=''):  # img_show_simplify
    cv2.namedWindow(window_name, cv2.WINDOW_KEEPRATIO)
    while True:
        img, idx, img_path = queue.get()
        cv2.imshow(window_name, img)
        cv2.waitKey(1)


def run():
    src_path = 'F:/url_get_image/ftp.nnvl.noaa.gov_GER_2018'
    img_paths = [os.path.join(src_path, f) for f in os.listdir(src_path)]

    mp.set_start_method('spawn')

    queue_img = mp.Queue(8)
    queue_idx__img_path = mp.Queue(len(img_paths))
    [queue_idx__img_path.put(idx__img_path) for idx__img_path in enumerate(img_paths)]

    processes = list()
    processes.append(mp.Process(target=img_show, args=(queue_img,)), )
    processes.extend([mp.Process(target=img_load, args=(queue_img, queue_idx__img_path))
                      for _ in range(3)])

    [setattr(process, "daemon", True) for process in processes]
    [process.start() for process in processes]
    [process.join() for process in processes]


if __name__ == '__main__':
    run()

2.影响读取速度的瓶颈(CPU 与磁盘)

开启多个进程从磁盘读取文件,并由 CPU 解析图片格式,将图片转化为 numpy 的 ndarray 保存在内存里面

当备用内存中找不到我们要读取的图片时,进程开始从磁盘中读取,这个时候磁盘成为限制读取的瓶颈。

如果操作系统有类似于 Win10 的 Superfetch 服务,那么读取初期,要读取的文件其实已经在内存里面了,此时的系统瓶颈在 CPU 处,CPU 需要把对应的图片格式转化为 ndarray

看下面图中的 CPU 占用 与 磁盘占用,可以看到前期是 CPU 满载,后期是磁盘满载,

因为我没有把读取到内存的 ndarray 继续保存在内存里,所以内存占用没有上升。

3.多进程读取图片(完整版)

我放了一份完整版代码在 GitHub 上: DEMO_images_load_order_mp_cv2.py(GitHub 上的代码会时常修改,有时候因为文件改名,会导致链接会指向错误,到时候请联系我修改,当然你也可以直接看下面的代码)

完整版添加了:

  • 多进程下的有序读取:维护一个有序数组,按顺序读取图片
  • 图片类型检查:图片是否可以正确读取,检查图片是否完整
  • 图片后缀名检查:只读取匹配的文件类型,如 jpg
import os
import multiprocessing as mp

import cv2
import numpy as np

'''
2018-07-05 Yonv1943 show file images, via multiprocessing
2018-09-04 use multiprocessing for loading images
2018-09-05 add simplify
'''


def img_load(queue, queue_idx__img_paths):
    while True:
        idx, img_path = queue_idx__img_paths.get()
        img = cv2.imread(img_path)  # Disk IO
        queue.put((img, idx, img_path))


def img_show(queue, window_name=''):  # check images and keep order
    cv2.namedWindow(window_name, cv2.WINDOW_KEEPRATIO)

    import bisect
    idx_previous = -1
    idxs = list()
    queue_gets = list()
    while True:
        queue_get = queue.get()
        idx = queue_get[1]
        insert = bisect.bisect(idxs, idx)  # keep order
        idxs.insert(insert, idx)
        queue_gets.insert(insert, queue_get)

        # print(idx_previous, idxs)
        while idxs and idxs[0] == idx_previous + 1:
            idx_previous = idxs.pop(0)
            img, idx, img_path = queue_gets.pop(0)
            if not isinstance(img, np.ndarray):  # check images
                os.remove(img_path)
                print("| Remove no image:", idx, img_path)
            elif not (img[-4:, -4:] - 128).any():  # download incomplete
                os.remove(img_path)
                print("| Remove incomplete image:", idx, img_path)
            else:
                try:
                    cv2.imshow(window_name, img)
                    cv2.waitKey(1)
                except error as e:
                    print("|Error:", e, idx, img_path)



def run():
    src_path = 'F:/url_get_image/ftp.nnvl.noaa.gov_GER_2018'
    img_paths = [os.path.join(src_path, f) for f in os.listdir(src_path) if f[-4:] == '.jpg']
    print("|Directory perpare to load:", src_path)
    print("|Number of images:", len(img_paths), img_paths[0])

    mp.set_start_method('spawn')

    queue_img = mp.Queue(8)
    queue_idx__img_path = mp.Queue(len(img_paths))
    [queue_idx__img_path.put(idx__img_path) for idx__img_path in enumerate(img_paths)]

    processes = list()
    processes.append(mp.Process(target=img_show, args=(queue_img,)), )
    processes.extend([mp.Process(target=img_load, args=(queue_img, queue_idx__img_path))
                      for _ in range(3)])

    [setattr(process, "daemon", True) for process in processes]
    [process.start() for process in processes]
    [process.join() for process in processes]


if __name__ == '__main__':
    run()

4.多进程下的有序读取:(重点)

因为将读取的任务列表分发给各个 CPU 的时候,因为 CPU 读取耗费的时间不同,而导致图片顺序被小幅度打乱,所以需要将图片排序。

用于输出图片的 CPU_0 负责排序,如果上一张输出图片 01,那么下一张输出的图片是 02,如果接收到其他 CPU 传来的图片 04、图片 05,那么就先不输出,暂时存入有序列表;
接收到图片 02 后,才输出图片,等到缺少下一张图片的时候,再从 CPU 处接收新的图片。

4.1 图片类型检查:

读取大量图片的时候,需要进行类型检查,以避免程序因错误而中断,这里进行了两个检查

  1. 检查图片是否正确读取(使用 Python 的内建函数 ininstance(object, object))
  2. 检查图片是否下载完整(未完整下载的图片,图片下方 RGB 值为固定值)
  3. 捕获未知的错误

其实对于无法打开的图片,比较好的处理方式并不是删除,而是移动,把出错的图片移动到其他文件夹。使用 shutil.rmtree() 替代 os.remove()

if not isinstance(img, np.ndarray):  # check images
    os.remove(img_path)
    print("| Remove no image:", idx, img_path)
elif not (img[-4:, -4:] - 128).any():  # download incomplete
    os.remove(img_path)
    print("| Remove incomplete image:", idx, img_path)
else:
    try:
        cv2.imshow(window_name, img)
        cv2.waitKey(1)
    except error as e:
        print("|Error:", e, idx, img_path)

4.2 图片后缀名检查:

检查后缀名可以避开文件夹里面的其他文件,读取的图片格式应该随实际情况修改, 我读取的是’jpg’,以免被过滤掉,opencv-python 的 cv2.imread() 支持 jpg,jpeg,png,bmp 等格式的读取

src_path = 'F:\\url_get_image\\ftp.nnvl.noaa.gov_GER_2018'  # better in winOS
img_paths = [os.path.join(src_path, f) for f in os.listdir(src_path) if f[-4:] == '.jpg']

我读取的图片是从美国国家海洋和大气管理局下载的,在我的另外一篇文章( 使用卷积网络移除卫星图片中的云层 )中,我也需要使用多进程加快磁盘图片文件的读取,因为我顺便把多进程读取图片的代码发到网络上,方便大家交流。

参考资料:

17.2. multiprocessing - Process-based parallelism - Python 3.7.0 documentation

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/755263.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

冯诺依曼体系结构以及回答操作系统(是什么,为什么,怎么办)问题

目录 一、硬件冯诺依曼体系结构 二、软件2.1 计算机的层状结构2.2 操作系统的概念2.3 操作系统是什么?2.4 为什么要有操作系统?2.5 操作系统是怎么管理底层的软硬件资源的呢? 一、硬件 冯诺依曼体系结构 我们常见的计算机,如笔记…

HTML+CSS+JavaScript:九九乘法表

一、需求如图 二、思路及代码 1、JavaScript代码 稍微刷过一点算法题的小伙伴就很容易想到这题需要利用双层for循环来实现&#xff0c;思路也是比较简单的&#xff0c;我在这里就直接放代码了 不添加CSS渲染的代码如下 <!DOCTYPE html> <html lang"en"&…

JVM学习笔记(三)垃圾回收

相关文章&#xff1a; JVM中的新生代和老年代&#xff08;Eden空间、两个Survior空间&#xff09;_jvm eden_样young的博客-CSDN博客JAVA命令行工具&#xff08;一&#xff09;--JAVA - 简书JAVA命令行工具&#xff08;二&#xff09;-jps - 简书JAVA命令行工具&#xff08;三&…

AttributeError: module ‘torch.nn‘ has no attribute ‘module‘

import torch import torch.nn as nnclass LinearModel(nn.Module):def _init_(self,ndim):super(LinearModel,self)._init_()self.ndimndimself.weightnn.Parameter(torch.randn(ndim,1))#定义权重self.biasnn.Parameter(torch.randn(1)) #定义偏置def forward(self,x):# y …

【离散数学实验报告】最小生成树的生成

实验四&#xff1a;最小生成树 一、实验目的&#xff1a; 理解最小生成树的画法。提高学生编写实验报告&#xff0c;总结实验结果的能力&#xff0c;培养学生的逻辑思维能力和算法设计思想。能够独立完成简单的算法设计和分析&#xff0c;进一步用他们来解决实际问题&#xf…

谁能成为首个RedCap规模商用的厂商?

RedCap在“降本、小尺寸、低功耗”的呼声中逐渐成为后5G时代的宠儿&#xff0c;随着相关技术的成熟&#xff0c;RedCap如何进一步商用成为行业关注的焦点。RedCap的发展&#xff0c;离不开运营商、芯片厂商、终端厂商、模组厂商等产业关键节点的通力合作。那RedCap离正式商用还…

关于hessian2的一些疑点(0CTF来分析)

目录 前言&#xff1a;csdn很久不用了&#xff0c;打算最近拾起来&#xff0c;主要是监督自己。 非常可疑的点 另一种方法通过JNDI注入来 构造完整的链子 这里&#xff0c;希望佬们解答解答&#xff0c;非常感谢&#xff01;&#xff01;&#xff01; 前言&#xff1a;csdn很…

【C++】开源:cpp-tbox百宝箱组件库

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍cpp-tbox百宝箱组件库。 无专精则不能成&#xff0c;无涉猎则不能通。。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;…

ingress之503问题

ingress之503问题 背景&#xff1a; 部署好应用服务(nsyai-test名称空间下)后&#xff0c;通过ingress做七层反代&#xff0c;浏览器访问域名一直出现503的错误&#xff0c;其中30086端口为ingress-controller控制器nodeport型service端口 问题&#xff1a; 网上查看发现是不…

【http-server】http-server的安装、前端使用http-server启动本地dist文件服务:

文章目录 一、http-server 简介:二、安装node.js:[https://nodejs.org/en](https://nodejs.org/en)三、安装http-server:[https://www.npmjs.com/package/http-server](https://www.npmjs.com/package/http-server)四、开启服务&#xff1a;五、http-server参数&#xff1a;【1…

OpenMMLab MMTracking目标跟踪官方文档学习(一)

介绍 MMTracking 是PyTorch的开源视频感知工具箱。它是OpenMMLab项目的一部分。 它支持 4 个视频任务&#xff1a; 视频对象检测 (VID) 单目标跟踪 (SOT) 多目标跟踪 (MOT) 视频实例分割 (VIS) 主要特点 第一个统一视频感知平台 我们是第一个统一多功能视频感知任务的开源工…

自建DNSlog服务器

DNSlog简介 在某些情况下&#xff0c;无法利用漏洞获得回显。但是&#xff0c;如果目标可以发送DNS请求&#xff0c;则可以通过DNS log方式将想获得的数据外带出来。 DNS log常用于以下情况&#xff1a; SQL盲注无回显的命令执行无回显的SSRF 网上公开提供dnslog服务有很多…

windows 搭建ssh服务

1、官网下载安装包&#xff1a;mls-software.com 2、点击安装&#xff08;一直默认即可&#xff09; 3、配置 opensshServer 4、成功登录

云数据库MySQL相关帮助

1.为什么创建数据库后在数据库列表中不显示&#xff1f; 因为列表读取的是information_schema&#xff0c;刚创建的数据库是空库&#xff0c;没有数据写入&#xff0c;不会写入缓存表&#xff0c;所以不会显示&#xff0c;但不影响正常使用&#xff0c;可以直接对新建的数据库进…

2.数据结构面试题--消失的数字

面试题:消失的数字 数组nums包含从0到n的所有整数,但是其中缺了一个,请编写代码找出那个缺失的整数,你有办法O(N)时间内完成吗? 方法1.排序:依次查找 如果下一个数不是上一个数1,那么上一个数字1就是消失的数字 冒泡排序的话时间复杂度是O(n^2) qsort排序的话是O(NlogN) 需…

Python爬虫——urllib_get请求的quote方法和urlencode方法

quote方法&#xff1a; 将字符转换为对应Unicode编码 import urllib.request import urllib.parse# 获取 https://www.baidu.com/s?wd周杰伦 网页源码 url "https://www.baidu.com/s?wd" headers {User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKi…

stm32 报错 dev_target_not_halted

烧录stm32H743&#xff0c;在cubeprogrammer里面点击connect&#xff0c;报错dev_target_not_halted 解决方法&#xff1a;先把H743的boot0引脚接到高电平上&#xff0c;然后少上电&#xff0c;此时会停止内核的运行&#xff0c;再点击connect即可 H743管脚&#xff1a; 在芯…

windows系统 安装 InfluxDB

一、InfluxDB下载 InfluxDB的windows&#xff08;64-bit&#xff09;下载地址为&#xff1a;https://dl.influxdata.com/influxdb/releases/influxdb-1.7.7_windows_amd64.zip 二、安装 influxDB是不需要安装的&#xff0c;只需要将压缩文件解压到相应的目录即可&#xff1b;…

STM32CubeMX+Eclipse+gcc+Jlink 实现STM32开发环境搭建

本节记录通过STM32CubeMXEclipsegccJlink 进行STM32环境搭建的过程&#xff1b; 文章目录 一、环境确认二、Eclipse建立工程三、指定编译路径四、选择gcc路径五、选择make路径六、 选择Device 参考&#xff1a; https://blog.csdn.net/qq_35787848/article/details/124395509 h…

OPPO手机便签怎么上传录音文件?

相信很多网友对OPPO这个手机品牌并不陌生&#xff0c;因为它凭借时尚轻薄的外观设计、流畅简约的系统、清晰的拍照摄影以及高中低不同的价位选择&#xff0c;赢得了不少年轻消费者的青睐。不过在使用OPPO手机的过程中&#xff0c;也有不少用户表示自己遇到了各种各样的问题&…