HWC格式(Torch)

人工智能小白,不对之处,希望各位大佬不吝赐教^_^

目录

前言 

 正文

1.关于HWC维度的理解

2.为什么pytorch中transforms.ToTorch要把(H,W,C)的矩阵转为(C,H,W)? [2]

3.如何进行格式的转换?

3.1 opencv python 把图(cv2下)BGR转RGB,且HWC转CHW【3】.

3.2 Torch将HWC格式转为CHW

附录

推荐文章


前言 

最近在做一个图像分类的任务,其中涉及到对于数据集的处理,利用到了均值和标准差。但是其中的均值和标准差是一个数组,如下所示。

# 各通道的均值
CIFAR100_TRAIN_MEAN = (0.5070751592371323, 0.48654887331495095, 0.4409178433670343)
# 各通道的标准差
CIFAR100_TRAIN_STD = (0.2673342858792401, 0.2564384629170883, 0.27615047132568404)

查阅资料发现,其中每个数值代表一个通道的均值和标准差,因此我猜测是RGB通道对应的数值。后来,通过研读整个项目代码,发现了一个令我困扰的地方。

# 数据增强
    transform_train = transforms.Compose([
        # transforms.ToPILImage(),
        # Crop the given PIL Image at a random location.
        # 32*32,padding=4,图像上下左右像素均填充一个像素
        transforms.RandomCrop(32, padding=4),
        # 随机水平翻转,默认值是0.5
        transforms.RandomHorizontalFlip(),
        # (-degrees,+degrees)
        transforms.RandomRotation(15),
        
        # 数据的格式转换和标准化 HWC => CHW。
        # 把图片转换为张量,同时进行归一化操作,把每个通道 0~255 的值归一化为0~1
        transforms.ToTensor(),
        transforms.Normalize(mean, std)  # 图像张量的归一化
    ])

由于我之前对于张量tensor以及torch不太熟悉,查阅资料补充了对上述代码的理解。

 正文

下面将依次介绍HWC格式的理解以及torch图像格式的转换,我认为这是一个循序渐进的过程。

1.关于HWC维度的理解

我们首先需要明确的是各个参数的含义,HWC可以看作是一幅图像的shape,H表示图像的高度(height),W表示图像的宽度(Width),而C表示一幅图像的通道数(Channel)

举个小栗子

hwc=[5,5,3] 的含义是什么呢?

大家可以思考一下,以图像为例,那么高宽都是5,3就是其中的通道数。因此我们也可以理解为3个 5*5 大小的特征图。 

2.为什么pytorch中transforms.ToTorch要把(H,W,C)的矩阵转为(C,H,W)? 

此问题的回答来源于知乎[2].

  • 因为pytorch很多函数都是设计成假设你的输入是 (c,h,w)的格式,当然你如果不嫌麻烦的话可以每次要用这些函数的时候转成chw格式,但我想这会比你输入的时候就转成chw要麻烦很多。
  • 至于为什么pytorch选择设计成chw而不是hwc(毕竟传统的读图片的函数opencv的cv2.imread或者sklearn的imread都是读成hwc的格式的)这点确实比较令初学者困惑。个人感觉是因为pytorch做矩阵加减乘除以及卷积等运算是需要调用cuda和cudnn的函数的,而这些接口都设成成chw格式了,故而pytorch为了方便起见也设计成chw格式了。
  • 那新问题就来了,cuda和cudnn为什么设计成chw格式呢?我想这是由于涉及到图片操作的都是和卷积相关的,而内部做卷积运算的加速设计成chw在操作上会比hwc处理起来更容易,更快。题主如果想进一步了解可以google一下cudnn的卷积实现。

3.如何进行格式的转换?

3.1 opencv python 把图(cv2下)BGR转RGB,且HWC转CHW【3】.

img = cv2.imread("test.jpg")
img_ = img[:,:,::-1].transpose((2,0,1))
  • 在opencv里,图格式HWC,其余都是CHW,故使用方法transpose((2,0,1)),transpose(2,0,1)就是读入第三维的数C作为第一维的值,读入第一维的数H作为第二维,读入第二维的数作为第三维W,如果再高维,就再按照输入的读取顺序来读【4】。
  • img[:,:,::-1]对应H、W、C,彩图是3通道,即C是3层。opencv里对应BGR,故通过C通道的 ::-1 就是把BGR转为RGB,其中[::-1] 代表顺序相反操作。

3.2 Torch将HWC格式转为CHW

from PIL import Image
from torchvision.transforms import ToTensor

img = Image.open('image_path')
#产生的PIL_image格式数据的取值范围是[0,255]
#形状(shape)是[h, w, c]
#像素顺序是RGB

tensor = ToTensor()(PIL_img)

# 或者
np_data = np.asarray(PIL_img)
tensor = ToTensor()(np_data)

ToTensor()接收PIL格式的数据,或者是直接从PIL转来的np.ndarray格式数据,只要保证进来的数据取值范围是[0, 255], 形状是[h, w, c],像素顺序是RGB,它就会帮你做下面的事情[5]

  • 取值范围[0, 255] / 255.0 => [0, 1.0], 数据格式从int8变成了float32
  • 形状(shape)转为[c, h, w]
  • 像素顺序依旧是RGB

附录

  1. Pytorch数据前后处理整理 
  2. 为什么pytorch中transforms.ToTorch要把(H,W,C)的矩阵转为(C,H,W)?
  3. opencv python 把图(cv2下)BGR转RGB,且HWC转CHW
  4. Python numpy.transpose 详解
  5. PIL skimage opencv torch各种图像格式的转换


 推荐文章

  1. 700套个人简历模板(考研保研工作)
  2. 人工智能2019年秋季学期期末复习知识点整理
  3. Fisher线性分类器的设计与实现,感知器算法的设计实现

以上就是我理解的内容啦,欢迎大家关注【小果果学长】微信公众号,获取更多资料和源码,希望大家点赞收藏加关注,如有不对的地方,非常开心和您交流。

你可能感兴趣的:(人工智能,数字图像处理,python,torch,图像处理)