python多线程读图片

2023-11-01

用 threading 模块多线程读图片加速,flickr25k 和 nuswide 两个数据集的图片准备见 [1-4],图像预处理程序来自 [5]。

为了测试,写了一个叫 LazyImage 的类,和其多线程版本 LazyImage_MT,代码:

import time
import multiprocessing
import threading
import os
import os.path as osp
import numpy as np
from PIL import Image

#
# 普通顺序加载:LazyImage、ImageF25k、ImageNUS
#

class LazyImage:
    """mimics np.ndarray, but uses lazy loading"""

    def __init__(self, image_path, image_size=224):
        """image_size: int"""
        self.image_path = image_path
        self.image_size = image_size
        # used in resizing
        self.lower_half = image_size // 2
        self.upper_half = (image_size + 1) // 2

    def __getitem__(self, index):
        if isinstance(index, int):
            return self._load_image(index)
        elif isinstance(index, (np.ndarray, list, tuple)):
            if isinstance(index, np.ndarray):
                assert 1 == index.ndim, "* index should be vector"
            return np.vstack([np.expand_dims(
                self._load_image(i), 0) for i in index])

        raise NotImplemented

    def _load_image(self, full_index):
        """loads single image & resizes
        Input:
            - full_index: int, the sample ID
        """
        img = Image.open(self._get_image_path(full_index))
        xsize, ysize = img.size
        seldim = min(xsize, ysize)
        rate = float(self.image_size) / seldim
        img = img.resize((int(xsize * rate), int(ysize * rate)))
        nxsize, nysize = img.size
        cx, cy = nxsize / 2.0, nysize / 2.0
        box = (cx - self.lower_half, cy - self.lower_half, cx + self.upper_half, cy + self.upper_half)
        img = img.crop(box)
        img = img.convert("RGB")  # can deal with grey-scale images
        img = img.resize((224, 224))
        img = np.array(img, dtype=np.float32)
        return img  # [H, W, C]

    def _get_image_path(self, full_index):
        """get image path according to sample ID"""
        raise NotImplemented


class ImageF25k(LazyImage):
    def _get_image_path(self, full_index):
        # shift to 1-base
        return osp.join(self.image_path, "im{}.jpg".format(full_index + 1))


class ImageNUS(LazyImage):
    """depends on (github) iTomxy/data/nuswide/make.image.link.py"""
    def _get_image_path(self, full_index):
        # remain 0-base as is
        return osp.join(self.image_path, "{}.jpg".format(full_index))

#
# 多线程加载:LazyImage_MT、ImageF25k_MT、ImageNUS_MT
#

class LazyImage_MT:
    """multi-threading version"""

    def __init__(self, image_path, image_size=224, n_thread=None):
        """image_size: int"""
        self.image_path = image_path
        self.image_size = image_size
        # used in resizing
        self.lower_half = image_size // 2
        self.upper_half = (image_size + 1) // 2
        self._mutex_put = threading.Lock()
        self._buffer = []
        self.n_thread = n_thread if (n_thread is not None) else \
            max(1, multiprocessing.cpu_count() - 2)

    def __getitem__(self, index):
        if isinstance(index, int):
            return self._load_image(index)
        elif isinstance(index, (np.ndarray, list, tuple)):
            if isinstance(index, np.ndarray):
                assert 1 == index.ndim, "* index should be vector"
            if self.n_thread < 2:
                return np.vstack([np.expand_dims(self._load_image(i), 0) for i in index])

            self._buffer = []
            batch_size = (len(index) + self.n_thread - 1) // self.n_thread
            t_list = []
            for tid in range(self.n_thread):
                t = threading.Thread(target=self._load_image_mt, args=(
                    index, range(tid * batch_size, min((tid + 1) * batch_size, len(index)))))
                t_list.append(t)
                t.start()
            for t in t_list:
                t.join()
            del t_list
            assert len(self._buffer) == len(index)
            self._buffer = [t[1] for t in sorted(self._buffer, key=lambda _t: _t[0])]
            return np.vstack(self._buffer)

        raise NotImplemented

    def _load_image_mt(self, indices, seg_meta_indices):
        batch_images = [(mid, np.expand_dims(self._load_image(indices[mid]), 0))
            for mid in seg_meta_indices]
        self._mutex_put.acquire()
        self._buffer.extend(batch_images)
        self._mutex_put.release()

    def _load_image(self, full_index):
        """loads single image & resizes
        Input:
            - full_index: int, the sample ID
        """
        img = Image.open(self._get_image_path(full_index))
        xsize, ysize = img.size
        seldim = min(xsize, ysize)
        rate = float(self.image_size) / seldim
        img = img.resize((int(xsize * rate), int(ysize * rate)))
        nxsize, nysize = img.size
        cx, cy = nxsize / 2.0, nysize / 2.0
        box = (cx - self.lower_half, cy - self.lower_half, cx + self.upper_half, cy + self.upper_half)
        img = img.crop(box)
        img = img.convert("RGB")  # can deal with grey-scale images
        img = img.resize((224, 224))
        img = np.array(img, dtype=np.float32)
        return img  # [H, W, C]

    def _get_image_path(self, full_index):
        """get image path according to sample ID"""
        raise NotImplemented


class ImageF25k_MT(LazyImage_MT):
    def _get_image_path(self, full_index):
        # shift to 1-base
        return osp.join(self.image_path, "im{}.jpg".format(full_index + 1))


class ImageNUS_MT(LazyImage_MT):
    """depends on (github) iTomxy/data/nuswide/make.image.link.py"""
    def _get_image_path(self, full_index):
        # remain 0-base as is
        return osp.join(self.image_path, "{}.jpg".format(full_index))

#
# 测试:速度、一致性
#

if "__main__" == __name__:
    batch_size = 128
    N_F25K = 25000
    N_NUS = 269648
    indices_f25k = np.arange(N_F25K)
    indices_nus = np.arange(N_NUS)

    print("-> flickr25k")
    tic = time.time()
    im_f25k = ImageF25k("data/flickr25k/mirflickr")
    for i in range(0, N_F25K, batch_size):
        _ = im_f25k[indices_f25k[i: i + batch_size]]
    print(time.time() - tic)  # 214.9833734035492
    # del im_f25k

    print("-> flickr25k multi-threading")
    tic = time.time()
    im_f25k_mt = ImageF25k_MT("data/flickr25k/mirflickr")
    for i in range(0, N_F25K, batch_size):
        _ = im_f25k_mt[indices_f25k[i: i + batch_size]]
    print(time.time() - tic)  # 56.653871297836304
    # del im_f25k_mt

    print("-> nuswide")
    tic = time.time()
    im_nus = ImageNUS("data/nuswide-tc21/images")
    for i in range(0, N_NUS, batch_size):
        _ = im_nus[indices_nus[i: i + batch_size]]
    print(time.time() - tic)  # 631.8568336963654
    # del im_nus

    print("-> nuswide multi-threading")
    tic = time.time()
    im_nus_mt = ImageNUS_MT("data/nuswide-tc21/images")
    for i in range(0, N_NUS, batch_size):
        _ = im_nus_mt[indices_nus[i: i + batch_size]]
    print(time.time() - tic)  # 207.77122569084167
    # del im_nus_mt

    print("-> consistency")
    for i in range(0, N_F25K, batch_size):
        i_s = im_f25k[indices_f25k[i: i + batch_size]]
        i_mt = im_f25k_mt[indices_f25k[i: i + batch_size]]
        print("f25k diff:", (i_s != i_mt).sum())  # 0
        i_s = im_nus[indices_nus[i: i + batch_size]]
        i_mt = im_nus_mt[indices_nus[i: i + batch_size]]
        print("nus diff:", (i_s != i_mt).sum())  # 0
        break
  • 输出
-> flickr25k
214.9833734035492
-> flickr25k multi-threading
56.653871297836304
-> nuswide
631.8568336963654
-> nuswide multi-threading
207.77122569084167
-> consistency
f25k diff: 0
nus diff: 0

References

  1. MIR-Flickr25K数据集预处理
  2. iTomxy/data/flickr25k
  3. NUS-WIDE数据集预处理
  4. iTomxy/data/nuswide
  5. DeXie0808/GCH/load_data.py
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python多线程读图片 的相关文章

随机推荐

  • idea简便导入jar包的方法

    idea简便导入jar包的方法 Step1 2021 12 18 15 21 19 复制准备好的jar包 Step 2 2021 12 18 15 21 20 在需要该jar包的项目中创建一个文件夹 一般习惯文件夹的名字为lib Step
  • case when 多个条件 以及case when 权重排序

    1 case when 多个条件 语法 SELECT nickname user name CASE WHEN user rank 5 THEN 经销商 WHEN user rank 6 THEN 代理商 WHEN user rank 7
  • 【计算机视觉这一年】万字长文盘点近百篇代表论文、应用和市场

    新智元导读 The M Tank发布了一份对计算机视觉领域最近一年进展的报告 A Year in Computer Vision 详述了四大部分的内容 包括 分类 定位 目标检测 目标追踪 分割 超分辨率 自动上色 风格迁移 动作识别 3D
  • 头哥作业:统计字母数量

    统计字母数量 输入格式 输出格式 示例 1 任务描述 读取附件是一篇英文短文 请编写程序统计这篇短文前 n 行中每一个英文字母出现的次数 结果按次数降序排列 次数相同时 按字母表顺序输出 若 n 值大于短文行数 输出整篇文章中每一个英文字母
  • windows安装JDK、maven 和 IDEA

    一 JDK安装 Java程序必须运行在JVM之上 或者说java exe就是JVM 所以 使用Java的第一件事情是安装JDK 1 获取安装包 官方网址 https www oracle com java technologies down
  • 距离公式详解

    在做分类时常常需要估算不同样本之间的相似性度量 SimilarityMeasurement 这时通常采用的方法就是计算样本间的 距离 Distance 采用什么样的方法计算距离是很讲究 甚至关系到分类的正确与否 本文的目的就是对常用的相似性
  • 一种通过篡改特定代码数据修复嵌入式产品BUG的方法

    一 前言 在嵌入式产品开发中 难以避免地会因为各种原因导致最后出货的产品存在各种各样的BUG 通常会给产品进行固件升级来解决问题 记得之前在公司维护一款BLE产品的时候 由于前期平台预研不足 OTA参数设置不当 导致少数产品出现不能OTA的
  • Wetab 标签页:内置多种免费实用优雅小组件的浏览器主页和起始页

    Wetab 是什么 Wetab 是一款基于浏览器的新标签页产品 主张辅助用户打造一个兼具效率与美观的主页 nbsp Wetab 的核心特色便是内置了多种实用 优雅的小组件 今天这篇 主要按照分类详细介绍 nbsp Wetab 中的各个小组件
  • c++中的sort函数的头文件及详细用法

    头文件为 include
  • centos7 mysql server_centos7 mysqlserver 安装过程

    官网下载安装mysql server wget http dev mysql com get mysql community release el7 5 noarch rpm rpm ivh mysql community release
  • ​通过VS Code远程访问局域网Linux

    来源 配置vscode远程到Linux环境下 z417 博客园 首先 VS Code安装插件remote SSH 其次 修改C Users xxx ssh config Host JetsonNano HostName 192 168 13
  • Flutter快速入门学习(二)

    目录 Dart介绍 一些Dart的重要概念 Dart语法学习 变量 内建类型 Number String Boolean List Set Map Symbol 函数 参数类型 可选参数 必选参数 函数作为另一个函数的参数 匿名函数 运算符
  • vue使用computed计算属性,监听初始化路由,页面高度

    vue中computed计算属性 页面高度自适应问题 div div
  • 王者S19服务器维护时间表,王者荣耀s19buff刷新时间一览 红蓝BUFF刷新间隔是多久...

    王者荣耀S19赛季加大了打野位对战局的影响 因此熟悉红蓝BUFF的刷新时间非常重要 无论是反BUFF还是拿自家BUFF都应该清楚刷新时间点 今日光耀菌就为大家带来了红蓝BUFF的刷新时间表 快来了解一番吧 王者荣耀s19赛季红蓝BUFF刷新
  • javaScript-----数组使用字符串作为下标

    原文地址 http blog csdn net chenssy article details 7366160 首先Array是从Object那里继承下 它具备Object所有的功能和特性 下面是Object的情况 html view pl
  • TypeScript void 无返回值

    void 表示没有任何类型 当一个函数没有返回值时 通常会返回 void 有值则会返回指定值类型 void 类型 没有返回值 function showMsg void console log 显示消息 不能返回数据 会报错 return
  • Android开发从入门到精通 章节一 : 环境+IDE

    Android开发从入门到精通 章节一 环境 IDE 接下来带领大家踏入Android编程的世界 跟着我的文章一起迈入移动端开发的世界 Android官网 https developer android google cn index ht
  • qt 嵌入web页面_Qt与Web混合开发(一)--简单使用

    目录 放个目录方便预览 目录是从博客复制过来的 点击会跳转到博客 前言 Qt与Web混合开发 系列文章 主要讨论Qt与Web混合开发相关技术 这类技术存在适用场景 例如 Qt项目使用Web大量现成的组件 方案做功能扩展 Qt项目中性能无关
  • 创建型设计模式

    为什么说支持懒加载的双重检测不比饿汉式更优 单例模式 一个类只允许创建一个对象 或实例 即单例模式 为什么使用单例 处理资源访问冲突 表示全局唯一类 从业务概念上 有些数据在系统种只应该保存一份 就比较适合设计为单例类 实现一个单例 构造函
  • python多线程读图片

    用 threading 模块多线程读图片加速 flickr25k 和 nuswide 两个数据集的图片准备见 1 4 图像预处理程序来自 5 为了测试 写了一个叫 LazyImage 的类 和其多线程版本 LazyImage MT 代码 i