Comparación de los métodos de escritura y lectura de imágenes de Python

  Al entrenar modelos de redes neuronales relacionados con la visión, siempre se utilizan la lectura y escritura de imágenes. Hay muchos métodos, como matplotlib, cv2, PIL, etc. A continuación, se comparan varias formas de leer y escribir, para seleccionar la forma más rápida de mejorar la velocidad de entrenamiento.

Estándar experimental

  Debido a que el marco utilizado para el entrenamiento es Pytorch, los estándares experimentales para la lectura son los siguientes:

  1. Lea 5 imágenes (una en formato png y cuatro en formato jpg) con una resolución de 1920x1080 y guárdelas en una matriz.

  2. Convierta la matriz de lectura en un tensor de Pytorch cuyo orden de dimensión sea CxHxW y guárdelo en la memoria de video (yo uso GPU para entrenamiento) El orden de los tres canales es RGB.

  3. Registre el tiempo empleado por cada método en las operaciones anteriores. Debido a que el tamaño de la imagen en el formato png es casi 10 veces mayor que el del formato jpg con una ligera diferencia en la calidad, el conjunto de datos generalmente no se guarda en png, por lo que no se compara la diferencia en el tiempo de lectura entre los dos formatos.

  Los estándares experimentales escritos son los siguientes:

  1. Convierta el tensor de Pytorch correspondiente a las 5 imágenes de 1920 x 1080 en una matriz de tipos de datos que se pueden utilizar con el método correspondiente.

  2. Guarde cinco imágenes en formato jpg.

  3. Registre el tiempo consumido por cada método para guardar la imagen.

Situación experimental

cv2

  Debido a la GPU, cv2 tiene dos formas de leer imágenes:

  1. Primero lea todas las imágenes como una matriz numérica y luego conviértalas en un tensor de pytorch almacenado en la GPU.

  2. Inicialice un tensor de pytorch guardado en la GPU y luego copie cada imagen directamente en este tensor.

  El código de experimento de la primera forma es el siguiente:

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) 

  Resultados experimentales:

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

  El código de experimento de la segunda forma es el siguiente:

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) 

  Resultados experimentales:

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

matplotlib

  Los mismos dos métodos de lectura, el primer código es el siguiente:

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) 

  Resultados experimentales:

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

  La segunda forma de experimentar el código:

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) 

  Resultados experimentales:

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

  Cabe señalar que el valor de la matriz obtenida por matplotlib leyendo la imagen en formato png es un número de punto flotante en el rango de $ [0, 1] $, mientras que la imagen en formato jpg es un número entero en el rango de $ [0, 255] $. Por lo tanto, si el formato de imagen en el conjunto de datos es inconsistente, tenga cuidado de convertirlo al mismo antes de leer, de lo contrario, el procesamiento previo del conjunto de datos será problemático.

PIL

  La lectura y escritura de PIL no puede usar directamente el tensor de pytorch o la matriz numpy. Primero debe convertirse al tipo de imagen, por lo que es muy problemático. La complejidad del tiempo definitivamente está en desventaja, por lo que no experimentaré.

antorcha

  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))    # 规范化的范围

Supongo que te gusta

Origin blog.csdn.net/qq_37189298/article/details/109699749
Recomendado
Clasificación