PIL、cv2、numpy,和pytorch(torch)之间的转换

一、单通道图片(灰度图)的读取和转换

1、OpenCV ——(BGR):

        因为大多数显示或处理图像的函数都期望图像是BGR格式(即Blue-Green-Red),而不是灰度格式。

        在OpenCV imread函数图片读取出来默认为3通道,当你读取单通道(灰度图)图像时,通道数会自动扩展为三通道。Opecv会将单通道的图复制3次转化为三通道, 因此三个通道的颜色值是相同的。

如果你不想让OpenCV这样做,即想要保持读取的图像为单通道,可以使用以下方法:cv2.IMREAD_UNCHANGED标志。保持图像的原通道数不变。如果图像本来是单通道的,那么读取后它仍然是单通道的。如果图像本来有多个通道,那读取后会是多通道。

cv2.IMREAD_GRAYSCALE 标志。指定读取单通道图像(灰度图),最后的结果是单通道

import cv2
 
# 读取图像,保持原通道数
image = cv2.imread('image.jpg', cv2.IMREAD_UNCHANGED)

# 读取单通道图像(灰度图)
img_gray = cv2.imread('img.png', cv2.IMREAD_GRAYSCALE)


# 单通道(灰度图)转换到RGB
img_rgb = cv2.cvtColor(img_gray, cv2.COLOR_GRAY2RGB)

# opencv 默认读取的是 BGR 三通道, 从BGR转换为RGB
image_bgr = cv2.imread('image.jpg')
img_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)


# 图片保存
output_file = 'imageRGB.png'
cv2.imwrite(output_file, img_rgb)


# 显示图像
cv2.imshow('Image', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

2、PIL ——(RGB):

默认模式下PIL会自动检测图像模式,如果是灰度图则为'L'模式,灰度图读出的结果就是单通道

from PIL import Image
 
# 打开图像(默认模式下PIL会自动检测图像模式,如果是灰度图则为'L'模式)
img_gray = Image.open('your_image.png')


# 转换为RGB图像
# 注意:对于灰度图,直接使用.convert()转为"RGB"模式并不会增加色彩信息,每个像素的R=G=B=灰度值
img_rgb = img_gray.convert('RGB')
 
 
# 保存转换后的图像
output_file = 'converted_image.png'
img_rgb.save(output_file)


# 显示图像
img_rgb.show(title='Converted to RGB')

二、图像转换

在图像处理和深度学习中,经常需要在PIL(Python Imaging Library)、OpenCV(cv2)、NumPy和PyTorch之间进行图像数据的转换。

OpenCV: 读取的图片格式直接是numpy,uint8的ndarry数据,形状为HxWxC,颜色通道(C)是 BRG, 如果要使用正常的图片,先使用通道转换方法转化成RGB通道。保存时数据形式是uint8的ndarray数组。

matplotlib: uint8的ndarray数据,形状为HxWxC,颜色通道(C)是RGB。不怎么用

PIL: 可以np.array(image)或者np.asarray(image)转换成numpy数组:uint8的ndarray数据,形状为HxWxC,颜色通道(C)是RGB。可以Image.fromarray(image)将uint8格式numpy数组类型转化为pillow类型。

Pythorch: ToTensor()归一化到[0, 1]的torch数据,通道顺序nchw(只是单张图片的话是chw),颜色通道RGB,查看图片方法及ToPILImage。注意一点:经过transforms.ToTensor()得到的结果就是0-1.0的,而且通道转成(c,h,w)了

总结:除了pytorch得到的是nchw图片,其余方法得到的都是hwc图片;除了cv2得到的c是bgr图片,其余方法得到的c都是rgb图片;

注意,OpenCV和PIL读取图片成numpy array的范围是[0,255]是uint8,而转成tensor的范围就是[0,1.0], 是float

把图片转成成torch的tensor数据,一般采用函数:torchvision.transforms。注意一点是:opencv或者PIL储存图片的格式和torch的储存方式不一样,opencv或者PIL储存图片格式是(H,W,C),而torch储存的格式是(C,H,W)。

1. PIL和numpy之间的转换

import numpy as np
from PIL import Image

image_path = "img.jpg"
image_PIL = Image.open(image_path)

# 从PIL转换到numpy
numpy_array = np.array(image_PIL)

# 从numpy转换到PIL
image_PIL = Image.fromarray(numpy_array)

2. cv2和numpy之间的转换

import cv2
import numpy as np

image_path = "img.jpg"
image_opencv = cv2.imread(image_path)

# 从cv2到numpy的转换
numpy_array = np.array(image_opencv)

# 从numpy到cv2的转换。
image_opencv = cv2.cvtColor(numpy_array)

#注意:如果 opencv_image 是RGB图像,要进行颜色空间转换, 先转换为 BGR 再进行后续操作
opencv_image = cv2.cvtColor(numpy_array, cv2.COLOR_RGB2BGR)

3.numpy和pytorch之间的转换

import torch
import numpy as np

H, W, C = 512, 512, 3
# NumPy数组
numpy_array = np.array([H, W, C])

# 从numpy到torch的转换
torch_tensor = torch.from_numpy(numpy_array)
# 或者
torch_tensor = torch.Tensor(numpy_array)

# 从torch到numpy的转换
numpy_array = torch_tensor.numpy()

4、opencv、PIL 和 tensor之间互相转换

img 的范围是[0, 255]

tensor 当做训练数据时候的范围是[0, 1.0]

如果只是tesnor 张量,则没有限制

(1)、使用transforms内部函数 ToTensor()、ToPILImage() 进行转换
import cv2
from PIL import Image
import torchvision
import torch
import torchvision.transforms as transforms

"--------------------------读取img-------------------------------"
image_path = "/home/ytusdc/Data/Data_Split/Data_seg/ori.jpg"
# 使用 OpenCV 读取
img = cv2.imread(image_path)   # 读取到的是 BGR
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # 转换为 RGB
print(img.shape)

# 使用 PIL 读取
img = Image.open(image_path)   # 读取到的是 RGB, img
# 以上img数组格式为 均为(H,W,C)

"--------------------------图片转 tensor---------------------------"
# ToTensor() 函数实现归一化到[0, 1.0]范围和通道转换(H,W,C)-> (C,H,W)
img_tensor = transforms.ToTensor()(img)  # tensor数据格式是torch(C,H,W)
print(img_tensor.size())

"--------------------------tensor 转图片----------------------------"
# tensor 转换前都先要到cpu
input_tensor = img_tensor.clone().detach().to(torch.device('cpu'))  # 到cpu

# tensor 转PIL
# ToPILImage() 函数实现了反归一化到[0, 255],和通道变换 (C,H,W)->(H,W,C),直接转换成 PIL格式
PIL_img = transforms.ToPILImage()(input_tensor)
PIL_img.save("pil.jpg")

# tensor 直接转图片,并且保存
# utils.save_image() 函数内部实现了反归一化,和通道变换 (C,H,W)->(H,W,C),因此直接可以保存成图片
torchvision.utils.save_image(input_tensor, "out_cv.jpg")

(2)、自己进行归一化和通道变换

下面实现了 numpy 和 tensor 之间的转换,并且实现了归一化、反归一化、通道变换,当变换到numpy后,可以自己再根据需求变换到opecv或者PIL图片格式

import torch
from PIL import Image
import numpy as np
import torchvision.transforms as transforms

# 图像转换为PyTorch张量,转换过程进行了通道变换和归一化,这两个过程可选
def numpy_to_tensor(img):
    img_numpy = np.array(img)  # 从img转换为NumPy数组
    img_numpy = img_numpy.transpose((2, 0, 1))     # (可选)通道变换 (H, W, C) -> (C, H, W)
    tensor = torch.from_numpy(img_numpy).float()   # 将图像从numpy数组转换为PyTorch张量
    tensor = tensor.to(torch.float32) / 255.0      # (可选)在0-1范围内标准化图像
    return tensor

# PyTorch张量转换为numpy
def tensor_to_numpy(tensor):
    # 将张量转换为numpy数组, 如果张量在GPU上,请先使用.cpu()将其移动到CPU。
    image_array = tensor.detach().cpu().clone().numpy()
    # image_array = tensor.detach().cpu().numpy()
    # (可选)如果图像是在0-1之间标准化的,则需要先反标准化(乘以255)
    image_array = (image_array * 255).astype(np.uint8)
    image_array = np.clip(image_array, 0, 255).astype(np.uint8)  # 区间 0-255 截断
    # (可选)如果张量进行了通道变换则要变换回来 (C, H, W) -> (H, W, C)
    image_array = image_array.transpose((1, 2, 0))
    return image_array

image = Image.open('path_to_your_image.jpg')
tensor_image = numpy_to_tensor(image)  # 转换为张量
numpy_image = tensor_to_numpy(tensor_image)  # 转换回 numpy

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用以下代码将 PyTorch 中的 Tensor 转换NumPy 数组: ``` import numpy as np import torch tensor = torch.randn((3, 4)) # 创建一个大小为 3x4 的张量 numpy_array = tensor.numpy() # 将张量转换NumPy 数组 ``` 要将 NumPy 数组转换PyTorch 中的 Tensor,可以使用以下代码: ``` import numpy as np import torch numpy_array = np.random.rand(3, 4) # 创建一个大小为 3x4 的 NumPy 数组 tensor = torch.from_numpy(numpy_array) # 将 NumPy 数组转换为张量 ``` 要将 PyTorch 中的 Tensor 转换为 OpenCV 中的图像,可以使用以下代码: ``` import cv2 import torch tensor = torch.randn((3, 256, 256)) # 创建一个大小为 3x256x256 的张量 image = tensor.permute(1, 2, 0).numpy() # 将张量转换NumPy 数组,并将通道顺序从 CxHxW 转换为 HxWxC cv2.imshow("Image", image) # 显示图像 cv2.waitKey() # 等待关闭窗口 ``` 要将 OpenCV 中的图像转换PyTorch 中的 Tensor,可以使用以下代码: ``` import cv2 import torch image = cv2.imread("image.png") # 读取图像文件 tensor = torch.from_numpy(image.transpose((2, 0, 1))) # 将图像转换为张量,并将通道顺序从 HxWxC 转换为 CxHxW ``` 要将 PyTorch 中的 Tensor 转换Pillow 中的图像,可以使用以下代码: ``` from PIL import Image import torch tensor = torch.randn((3, 256, 256)) # 创建一个大小为 3x256x256 的张量 image = tensor.permute(1, 2, 0).numpy() # 将张量转换NumPy 数组,并将通道顺序从 CxHxW 转换为 HxWxC pil_image = Image.fromarray((image * 255).astype('uint8')) # 将 NumPy 数组转换PIL 图像 pil_image.show() # 显示图像 ``` 要将 Pillow 中的图像转换PyTorch 中的 Tensor,可以使用以下代码: ``` from PIL import Image import numpy as np import torch pil_image = Image.open("image.png") # 打开图像文件 numpy_array = np.array(pil_image) / 255.0 # 将 PIL 图像转换NumPy 数组,并将像素值转换为 0 到 1 之间的浮点数 tensor = torch.from_numpy(numpy_array.transpose((2, 0, 1))) # 将 NumPy 数组转换为张量,并将通道顺序从 HxWxC 转换为 CxHxW ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值