cv2.imread 和PIL中的image.open图片显示区别 格式互相转换

本文详细对比了plt.imread、PIL.Image.open和cv2.imread读取图像的颜色顺序差异,展示了OpenCV与PIL库间图像格式转换的方法,并提供了判断图像数据是否为OpenCV格式的技巧。

显示区别

plt.imread和PIL.Image.open读入的都是RGB顺序,而opencv中cv2.imread读入的是BGR通道顺序 。cv2.imread会显示图片更蓝一些。

以下代码为opencv imread和PIL库中image.open读入图像颜色顺序的比较

import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt

import cv2
import numpy as np
from PIL import Image

path="/Users/waldenz/Documents/Work/doc/TestImages/c1.jpeg"
img1 = cv2.imread(path, 3)
img2 = Image.open(path)
img2 = np.asarray(img2)
plt.subplot(121)
plt.imshow(img1)
plt.subplot(122)
plt.imshow(img2)
# plt.figure()
plt.show()

左侧为原图,右侧为代码运行结果图。

                  

                 

格式互相转换 

以上面牛头梗的狗狗图片作为原图,展示两种格式间的转换

def PILImageToCV():
    # PIL Image转换成OpenCV格式
    path = "/Users/waldenz/Documents/Work/doc/TestImages/t3.png"
    img = Image.open(path)
    plt.subplot(121)
    plt.imshow(img)

    img = cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)
    plt.subplot(122)
    plt.imshow(img)
    plt.show()


def CVImageToPIL():
    # OpenCV图片转换为PIL image
    path = "/Users/waldenz/Documents/Work/doc/TestImages/t3.png"
    img = cv2.imread(path)
    # cv2.imshow("OpenCV",img)
    plt.subplot(121)
    plt.imshow(img)

    img2 = Image.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
    plt.subplot(122)
    plt.imshow(img2)
    plt.show()

第一组为PIL Image和转换后的opencv格式; 第二组为opencv读取的原图在matplotlib中的展示,和转换为PIL Image后的展示

               

 

判断图像数据是否是OpenCV格式

即判断image是否为numpy的ndarray数据类型

isinstance(img, np.ndarray)

 

<think>我们讨论的是在PyTorch中如何实现PIL.ImageOpenCV(cv2)图像格式的相互转换。虽然PyTorch主要处理张量,但在数据预处理阶段,我们经常需要在这两种常见的图像表示之间转换。以下是详细的转换方法: ### 1. PIL.ImageOpenCV (cv2) 格式 **步骤**: 1.PIL.Image转换为NumPy数组(注意:PIL图像是RGB格式,而OpenCV默认使用BGR格式2. 转换颜色空间:RGB → BGR 3. 可选:如果图像有透明度通道(RGBA),需要额外处理 **代码示例**: ```python import cv2 from PIL import Image import numpy as np # 读取PIL图像 pil_image = Image.open("image.jpg") # RGB格式 # 转换为NumPy数组 np_image = np.array(pil_image) # 此时是RGB格式 # 转换通道顺序:RGB → BGR cv2_image = cv2.cvtColor(np_image, cv2.COLOR_RGB2BGR) # 现在cv2_image可以被OpenCV函数处理 cv2.imshow("OpenCV Window", cv2_image) cv2.waitKey(0) ``` ### 2. OpenCV (cv2) 格式PIL.Image **步骤**: 1. 转换OpenCV图像的通道顺序:BGR → RGB 2. 将NumPy数组转换PIL.Image **代码示例**: ```python import cv2 from PIL import Image import numpy as np # 读取OpenCV图像 (BGR格式) cv2_image = cv2.imread("image.jpg") # BGR格式 # 转换通道顺序:BGR → RGB rgb_image = cv2.cvtColor(cv2_image, cv2.COLOR_BGR2RGB) # 转换PIL.Image pil_image = Image.fromarray(rgb_image) # 现在可以使用PIL处理图像 pil_image.show() ``` ### 3. 注意事项 - **通道顺序**:这是转换中最关键的差异,PIL使用RGB,OpenCV使用BGR。 - **数据类型**:PIL图像转换为NumPy数组后,数据类型通常是`uint8`(0-255)。OpenCV同样使用`uint8`。 - **透明度处理**:如果图像有alpha通道(RGBA),在转换时需要使用`COLOR_RGBA2BGRA`或`COLOR_BGRA2RGBA`等。 - **灰度图像**:对于单通道图像(灰度图),无需转换通道顺序,但要注意维度: ```python # 灰度PILOpenCV pil_gray = Image.open("gray.jpg").convert('L') cv2_gray = np.array(pil_gray) # 直接转换,无需颜色空间转换 # 灰度OpenCVPIL cv2_gray = cv2.imread("gray.jpg", cv2.IMREAD_GRAYSCALE) pil_gray = Image.fromarray(cv2_gray) ``` ### 4. 在PyTorch数据管道中的整合 在PyTorch的`Dataset`中,可以这样使用: ```python from torch.utils.data import Dataset import cv2 from PIL import Image class MyDataset(Dataset): def __init__(self, file_list, transform=None): self.file_list = file_list self.transform = transform def __getitem__(self, index): img_path = self.file_list[index] # 使用OpenCV读取 cv2_img = cv2.imread(img_path) # 转换为RGB rgb_img = cv2.cvtColor(cv2_img, cv2.COLOR_BGR2RGB) # 或者使用PIL读取(二选一) # pil_img = Image.open(img_path).convert('RGB') # 应用transform(通常包含ToTensorNormalize) if self.transform: # 注意:如果上面用的是OpenCV读取,这里传入的是rgb_img(numpy数组),而transform通常设计为处理PIL图像 # 因此,如果transform包含ToTensor,则可以直接传入numpy数组(因为ToTensor也接受numpy数组) transformed = self.transform(rgb_img) return transformed # 定义transform(假设使用OpenCV读取,然后转换) transform = transforms.Compose([ transforms.ToPILImage(), # 将numpy数组或张量转换PIL图像(如果是numpy数组,则要求格式为HWC,uint8) transforms.Resize((256, 256)), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) ``` **注意**:在transform中,如果第一个操作是`ToPILImage()`,那么传入的应该是numpy数组(HWC格式,uint8)。如果跳过`ToPILImage()`,则可以使用`transforms.ToTensor()`直接处理numpy数组(它会自动将HWC转为CHW,并将值缩放到[0,1])。因此,上面的transform也可以改为: ```python transform = transforms.Compose([ transforms.ToTensor(), # 直接处理numpy数组(要求HWC,uint8),输出CHW,[0,1] transforms.Resize((256, 256)), # 注意:ToTensor之后,图像变为张量,Resize操作需要能处理张量(新版本PyTorch的Resize支持CHW张量) transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) ``` ### 5. 常见问题解决 - **颜色失真**:如果转换后颜色异常,请检查通道顺序转换是否正确(BGR ↔ RGB)[^2]。 - **值域错误**:如果转换过程中遇到值域错误(如之前的问题),请检查图像数据是否在预期范围内(如uint8为0-255,float为0-1或-1到1等)。 ### 总结转换关系 ```mermaid graph LR A[PIL.Image] -->|numpy.array| B[NumPy Array<br>RGB] B -->|Image.fromarray| A C[OpenCV Image<br>BGR] -->|cv2.cvtColor<br>COLOR_BGR2RGB| B B -->|cv2.cvtColor<br>COLOR_RGB2BGR| C ``` §§相关问题§§ 1. 如何解决OpenCV读取图像后颜色异常的问题? 2. 在PyTorch中如何正确处理带有透明通道的图像? 3. 如何将PyTorch张量转换PIL.ImageOpenCV格式? </think> ### PyTorch 中 PIL.ImageOpenCV (cv2) 图片格式互相转换指南 #### 一、核心转换原理 1. **数据结构差异**: - `PIL.Image`:RGB 通道顺序 (H×W×C) - `OpenCV (cv2)`:BGR 通道顺序 (H×W×C) - 转换关键:**通道顺序调整** **数据类型转换** 2. **转换流程图**: ```mermaid graph LR A[PIL.Image<br>RGB格式] -->|1.转NumPy数组| B[NumPy数组<br>RGB格式] B -->|2.通道交换| C[NumPy数组<br>BGR格式] C --> D[cv2图像对象] D -->|1.通道交换| B B -->|2.PIL.Image| A ``` #### 二、具体转换方法 ##### 1. PIL.ImageOpenCV (cv2) ```python from PIL import Image import cv2 import numpy as np # 读取PIL图像 pil_img = Image.open("input.jpg") # RGB格式 # 转换步骤: # 1. PIL转NumPy数组 (自动转换为RGB顺序) np_img = np.array(pil_img) # 得到H×W×C的RGB数组 # 2. 转换通道顺序: RGB → BGR cv2_img = cv2.cvtColor(np_img, cv2.COLOR_RGB2BGR) # 关键步骤[^2] # 3. 使用OpenCV处理 cv2.imwrite("output_cv2.jpg", cv2_img) ``` ##### 2. OpenCV (cv2) → PIL.Image ```python import cv2 from PIL import Image import numpy as np # 读取OpenCV图像 cv2_img = cv2.imread("input.jpg") # BGR格式 # 转换步骤: # 1. 转换通道顺序: BGR → RGB rgb_img = cv2.cvtColor(cv2_img, cv2.COLOR_BGR2RGB) # 关键步骤[^1] # 2. NumPy数组转PIL.Image pil_img = Image.fromarray(rgb_img) # 得到PIL对象 # 3. 使用PIL处理 pil_img.save("output_pil.jpg") ``` #### 三、特殊场景处理 1. **灰度图像转换**: ```python # PILOpenCV灰度图 pil_gray = pil_img.convert('L') cv2_gray = np.array(pil_gray) # 无需通道转换 # OpenCVPIL灰度图 cv2_gray = cv2.imread("gray.jpg", cv2.IMREAD_GRAYSCALE) pil_gray = Image.fromarray(cv2_gray) ``` 2. **带Alpha通道的图像**: ```python # RGBA转BGRA rgba_array = np.array(pil_img_rgba) bgra_array = cv2.cvtColor(rgba_array, cv2.COLOR_RGBA2BGRA) # BGRA转RGBA bgra_array = cv2.imread("input.png", cv2.IMREAD_UNCHANGED) rgba_array = cv2.cvtColor(bgra_array, cv2.COLOR_BGRA2RGBA) ``` #### 四、PyTorch 数据管道集成 ```python import torchvision.transforms as T from torch.utils.data import Dataset class CustomDataset(Dataset): def __init__(self, image_paths): self.paths = image_paths self.cv2_to_pil = T.Compose([ T.ToPILImage() # 自动处理BGR→RGB转换 ]) self.transform = T.Compose([ T.Resize(256), T.ToTensor(), T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) def __getitem__(self, idx): # 用OpenCV读取 cv2_img = cv2.imread(self.paths[idx]) # 转换PIL格式 (自动BGR→RGB) pil_img = self.cv2_to_pil(cv2_img) # 应用变换 return self.transform(pil_img) ``` #### 五、常见问题解决 1. **颜色失真问题**: - 现象:转换后图像颜色异常 - 原因:未正确处理 RGB/BGR 转换 - 方案:必须使用 `cv2.cvtColor` 显式转换 2. **值域范围错误**: ```python # 确保值域在0-255 (uint8) cv2_img = np.clip(cv2_img, 0, 255).astype(np.uint8) pil_img = pil_img.convert('RGB') # 确保无alpha通道 ``` #### 六、性能优化建议 1. **批量转换加速**: ```python # 使用OpenCV批量处理 bgr_batch = np.stack([cv2.cvtColor(np.array(pil), cv2.COLOR_RGB2BGR) for pil in pil_images]) ``` 2. **内存优化**: ```python # 避免中间副本 cv2_img = np.asarray(pil_img)[..., ::-1].copy() # RGB→BGR ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值