Python画像の読み取り方法と書き込み方法の比較

  視覚関連のニューラルネットワークモデルをトレーニングする場合、画像の読み取りと書き込みが常に使用されます。matplotlib、cv2、PILなどの多くのメソッドがあります。以下では、トレーニング速度を向上させるための最速の方法を選択するために、読み取りと書き込みのいくつかの方法を比較します。

実験標準

  トレーニングに使用されるフレームワークはPytorchであるため、読み取りの実験基準は次のとおりです。

  1. 1920x1080の解像度で5枚の写真(1枚はpng形式、4枚はjpg形式)を読み取り、配列に保存します。

  2.読み取った配列をCxHxWの寸法順序のPytorchテンソルに変換し、ビデオメモリに保存します(トレーニングにはGPUを使用します)。3つのチャネルの順序はRGBです。

  3.上記の操作で各メソッドが費やした時間を記録します。png形式の画像サイズはjpg形式の約10倍で、品質にわずかな違いがあるため、データセットは通常pngに保存されないため、2つの形式の読み取り時間の違いは比較されません。

  書かれた実験基準は次のとおりです。

  1.5つの1920x1080画像に対応するPytorchテンソルを、対応する方法で使用できるデータタイプの配列に変換します。

  2.5枚の写真をjpg形式で保存します。

  3.画像を保存するために各メソッドで費やされた時間を記録します。

実験状況

cv2

  GPUのため、cv2には画像を読み取る2つの方法があります。

  1.最初にすべての画像をnumpy配列として読み取り、次にそれらをGPUに格納されているpytorchテンソルに変換します。

  2. GPUに保存されているpytorchテンソルを初期化し、各画像をこのテンソルに直接コピーします。

  最初の方法の実験コードは次のとおりです。

import os, torch
import cv2 as cv 
import numpy as np 
from time import time 
 
read_path = 'D:test'
write_path = 'D:test\\write\\'
 
# cv2读取 1
start_t = time()
imgs = np.zeros([5, 1080, 1920, 3])
for img, i in zip(os.listdir(read_path), range(5)): 
  img = cv.imread(filename=os.path.join(read_path, img))
  imgs[i] = img   
imgs = torch.tensor(imgs).to('cuda')[...,[2,1,0]].permute([0,3,1,2])/255 
print('cv2 读取时间1:', time() - start_t) 
# cv2保存
start_t = time()
imgs = (imgs.permute([0,2,3,1])[...,[2,1,0]]*255).cpu().numpy()
for i in range(imgs.shape[0]): 
  cv.imwrite(write_path + str(i) + '.jpg', imgs[i])
print('cv2 保存时间:', time() - start_t) 

  実験結果:

cv2 读取时间1: 0.39693760871887207
cv2 保存时间: 0.3560612201690674

  2番目の方法の実験コードは次のとおりです。

import os, torch
import cv2 as cv 
import numpy as np 
from time import time 
 
read_path = 'D:test'
write_path = 'D:test\\write\\'
 
 
# cv2读取 2
start_t = time()
imgs = torch.zeros([5, 1080, 1920, 3], device='cuda')
for img, i in zip(os.listdir(read_path), range(5)): 
  img = torch.tensor(cv.imread(filename=os.path.join(read_path, img)), device='cuda')
  imgs[i] = img   
imgs = imgs[...,[2,1,0]].permute([0,3,1,2])/255 
print('cv2 读取时间2:', time() - start_t) 
# cv2保存
start_t = time()
imgs = (imgs.permute([0,2,3,1])[...,[2,1,0]]*255).cpu().numpy()
for i in range(imgs.shape[0]): 
  cv.imwrite(write_path + str(i) + '.jpg', imgs[i])
print('cv2 保存时间:', time() - start_t) 

  実験結果:

cv2 读取时间2: 0.23636841773986816
cv2 保存时间: 0.3066873550415039

matplotlib

  同じ2つの読み取り方法、最初のコードは次のとおりです。

import os, torch 
import numpy as np
import matplotlib.pyplot as plt 
from time import time 
 
read_path = 'D:test'
write_path = 'D:test\\write\\'
 
# matplotlib 读取 1
start_t = time()
imgs = np.zeros([5, 1080, 1920, 3])
for img, i in zip(os.listdir(read_path), range(5)): 
  img = plt.imread(os.path.join(read_path, img)) 
  imgs[i] = img    
imgs = torch.tensor(imgs).to('cuda').permute([0,3,1,2])/255  
print('matplotlib 读取时间1:', time() - start_t) 
# matplotlib 保存
start_t = time()
imgs = (imgs.permute([0,2,3,1])).cpu().numpy()
for i in range(imgs.shape[0]):  
  plt.imsave(write_path + str(i) + '.jpg', imgs[i])
print('matplotlib 保存时间:', time() - start_t) 

  実験結果:

matplotlib 读取时间1: 0.45380306243896484
matplotlib 保存时间: 0.768944263458252

  コードを実験する2番目の方法:

import os, torch 
import numpy as np
import matplotlib.pyplot as plt 
from time import time 
 
read_path = 'D:test'
write_path = 'D:test\\write\\'
 
# matplotlib 读取 2
start_t = time()
imgs = torch.zeros([5, 1080, 1920, 3], device='cuda')
for img, i in zip(os.listdir(read_path), range(5)): 
  img = torch.tensor(plt.imread(os.path.join(read_path, img)), device='cuda')
  imgs[i] = img    
imgs = imgs.permute([0,3,1,2])/255  
print('matplotlib 读取时间2:', time() - start_t) 
# matplotlib 保存
start_t = time()
imgs = (imgs.permute([0,2,3,1])).cpu().numpy()
for i in range(imgs.shape[0]):  
  plt.imsave(write_path + str(i) + '.jpg', imgs[i])
print('matplotlib 保存时间:', time() - start_t) 

  実験結果:

matplotlib 读取时间2: 0.2044532299041748
matplotlib 保存时间: 0.4737534523010254

  matplotlibがpng形式の画像を読み取ることによって得られる配列の値は$ [0、1] $の範囲の浮動小数点数であり、jpg形式の画像は$ [0、255] $の範囲の整数であることに注意してください。したがって、データセット内の画像形式に一貫性がない場合は、読み取る前に同じ形式に変換するように注意してください。変換しないと、データセットの前処理が面倒になります。

PIL

  PILの読み取りと書き込みでは、pytorchテンソルやnumpy配列を直接使用することはできません。最初に画像タイプに変換する必要があるため、非常に面倒です。時間の複雑さは間違いなく不利なので、実験はしません。

トーチビジョン

  torchvision提供了直接从pytorch张量保存图片的功能,和上面读取最快的matplotlib的方法结合,代码如下:

import os, torch  
import matplotlib.pyplot as plt 
from time import time 
from torchvision import utils 

read_path = 'D:test'
write_path = 'D:test\\write\\'
 
# matplotlib 读取 2
start_t = time()
imgs = torch.zeros([5, 1080, 1920, 3], device='cuda')
for img, i in zip(os.listdir(read_path), range(5)): 
  img = torch.tensor(plt.imread(os.path.join(read_path, img)), device='cuda')
  imgs[i] = img    
imgs = imgs.permute([0,3,1,2])/255  
print('matplotlib 读取时间2:', time() - start_t) 
# torchvision 保存
start_t = time() 
for i in range(imgs.shape[0]):   
  utils.save_image(imgs[i], write_path + str(i) + '.jpg')
print('torchvision 保存时间:', time() - start_t) 

  实验结果:

matplotlib 读取时间2: 0.15358829498291016
torchvision 保存时间: 0.14760661125183105

  可以看出这两个是最快的读写方法。另外,要让图片的读写尽量不影响训练进程,我们还可以让这两个过程与训练并行。另外,utils.save_image可以将多张图片拼接成一张来保存,具体使用方法如下:

utils.save_image(tensor = imgs,     # 要保存的多张图片张量 shape = [n, C, H, W]
                 fp = 'test.jpg',   # 保存路径
                 nrow = 5,          # 多图拼接时,每行所占的图片数
                 padding = 1,       # 多图拼接时,每张图之间的间距
                 normalize = True,  # 是否进行规范化,通常输出图像用tanh,所以要用规范化 
                 range = (-1,1))    # 规范化的范围

おすすめ

転載: blog.csdn.net/qq_37189298/article/details/109699749