PIL批量对图片进行转换(RGB-->Gray)

Image模块中主要有八种模式,分别为1,L,P,RGB,RGBA,CMYK,YCbCr,I,

以往很多博客都是对一张图片做转换,本文简单的读取文件夹中的图片,做颜色通道的转换,可以改改做其他的尝试。

from os.path import splitext
import glob
from PIL import Image
 
def get_file(filename):
    files = glob.glob(filename)
    return files
 
def convert_file(files, type):
    for jpg in files:
        im = Image.open(jpg)
        im = im.convert('L')
        pg = splitext(jpg)[0]+"." + type
        im.save(pg)
 

if __name__ == "__main__":
    filename = "/Users/***/2/*.[j][p][g]"
    files = get_file(filename)
    convert_file(files, "jpg")




<think>我们讨论的是在PyTorch中如何实现PIL.Image和OpenCV(cv2)图像格式的相互转换。虽然PyTorch主要处理张量,但在数据预处理阶段,我们经常需要在这两种常见的图像表示之间转换。以下是详细的转换方法: ### 1. PIL.Image 转 OpenCV (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 # 灰度PIL转OpenCV pil_gray = Image.open("gray.jpg").convert('L') cv2_gray = np.array(pil_gray) # 直接转换,无需颜色空间转换 # 灰度OpenCV转PIL 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(通常包含ToTensor和Normalize) 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.Image或OpenCV格式? </think> ### PyTorch 中 PIL.Image 与 OpenCV (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.Image → OpenCV (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 # PIL转OpenCV灰度图 pil_gray = pil_img.convert('L') cv2_gray = np.array(pil_gray) # 无需通道转换 # OpenCV转PIL灰度图 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、付费专栏及课程。

余额充值