### 一、引入
在对 NCHW 格式的图片数据进行 reshape 操作并存为 Image 后的可视化效果比较奇怪,但它明显和原图之间存在联系,因此有必要再了解一下图片的结构和 reshape 对其造成的影响。
已知原图:

经过代码中的 reshape 操作后:
(代码部分如有疑问,可以参考 http://luxuff.cn/archives/reshape和transpose的区别 第二节)
```python
from src.dataset import create_BRDNetDataset
from mindspore.ops import composite as C
import PIL.Image as Image
import os
from mindspore import context
if __name__ == '__main__':
device_id = int(os.getenv('DEVICE_ID', '6'))
context.set_context(mode=context.GRAPH_MODE, device_id=device_id, device_target="Ascend", save_graphs=False)
out_dir = "./outputs/"
dataset, _= create_BRDNetDataset(r'./Test/Kodak24/', 75, 3, 1, 1, 0, shuffle=False)
data_loader = dataset.create_dict_iterator()
for i, data in enumerate(data_loader):
img_test = data["image"]
img_test = C.clip_by_value(img_test, 0, 1)
img_out = data["label"]
img_out = C.clip_by_value(img_out , 0, 1)
img_test=img_test.asnumpy()
img_test=img_test.reshape((500,500,3))
img_test = Image.fromarray((img_test*255).astype('uint8'))
img_test.save(out_dir+'noise_'+str(i)+'_sigma75.png')
img_out=img_out.asnumpy()
img_out=img_out.reshape((500,500,3))
img_out = Image.fromarray((img_out*255).astype('uint8'))
img_out.save(out_dir+'label_'+str(i)+'_sigma75.png')
```
保存后的原图:

保存后的噪声图:

首先,保存后的图片每行内的区域内容几乎完全一样,完全有理由猜测经过插值组合后的图片就是原来的大图;
其次,这三行图片虽然都是灰度图,同一个帽子(比如第二个)的表现效果却不一样;而且越接近三原色(R、G、B)的颜色效果差异越明显,因此完全有理由猜测这三行数据只是某一通道的数据可视化效果。
至于到底是不是这样,还是上实验检测了看看。
### 二、Reshape可能的影响
依据我在 http://luxuff.cn/archives/reshape和transpose的区别 文章中总结出的绳子规律,可以将 CHW 格式的图片 reshape 成 HWC 格式的图片的过程用下图来表示:

图片左侧是我们最初拿到的 CHW 格式的图片数据(由 3 个通道的数据共同表示),假设按照图中正视方向,我们访问图片数据的时候肯定是从左上角(1,2,3,4,5,6...)那儿开始读取。
待转换成的 HWC 格式的数据如图中右侧所示(假设一开始只是空数组),假设按照图中所述正视方向,访问该数组时肯定是从图中坐标轴原点开始。
按照绳子规律分配原数据时,从左侧的 CHW 中依次取出数据,放置到 HWC 数组中,如同图中所示的(1,2,3,4,5,6...)分配到(1,2,3),(4,5,6)...
由于左侧的数据是 500x500 的,而右侧分配的“空位”是 500x3 的,因此左边的“一行数据”只能分配到右边的三分之一的空位,后续三分之二的空位将由左侧第二行、第三行的数据补上。我们可以认为相邻三行的像素数据极为相近,因此才使得同行不同列的那三块区域看起来几乎一模一样。但其实它们是由原图的第 i 行、i+1 行、i+2 行数据构成的。
而左侧的 R 通道数据“用完”后,也只能填完右侧 H/3 的数据。这就使得转换后的图片数据(三大行),每行其实都属于同一个通道的数据(R、G、B)。
这就是之前看到的那种效果。
### 三、反向计算
知道了 reshape 的流程之后,就相当于我们知道了转换后的数据分布。因此如果将转换后的数据调整回它应该在的位置,所显示的图片就一定会是正常的。
```python
from src.dataset import create_BRDNetDataset
from mindspore.ops import composite as C
import PIL.Image as Image
import os
from mindspore import context
import numpy as np
if __name__ == '__main__':
device_id = int(os.getenv('DEVICE_ID', '6'))
context.set_context(mode=context.GRAPH_MODE, device_id=device_id, device_target="Ascend", save_graphs=False)
out_dir = "./outputs/"
dataset, _= create_BRDNetDataset(r'./Test/Kodak24/', 75, 3, 1, 1, 0, shuffle=False)
data_loader = dataset.create_dict_iterator()
for i, data in enumerate(data_loader):
if i==6:
img_test = data["image"]
img_test = C.clip_by_value(img_test, 0, 1)
img_out = data["label"]
img_out = C.clip_by_value(img_out , 0, 1)
img_test=img_test.asnumpy()
img_test=img_test.reshape((500,500,3))
img_test = Image.fromarray((img_test*255).astype('uint8'))
img_test.save(out_dir+'noise_'+str(i)+'_sigma75.png')
img_out=img_out.asnumpy()
img_out2=img_out.reshape((500,500,3))
label_wrong = Image.fromarray((img_out2*255).astype('uint8'))
label_wrong.save(out_dir+'label_wrong_'+str(i)+'_sigma75.png')
label_right = np.ones((500, 500, 3))
index = 0
for k in range(500):
for z in range(500):
for t in range(3):
label_right[(index%250000)//500, (index%250000)%500, index//250000] = img_out2[k,z,t]
index+=1
label_right = Image.fromarray((label_right*255).astype('uint8'))
label_right.save(out_dir+'label_right_'+str(i)+'_sigma75.png')
```
我们已知转换后的 HWC 数组中在 WC 维度每读取 500 个数据都应该是原来的 W 维度的,每读取完 250000 (500x500)个数据后,就属于下一个通道的数据,因此如上述代码所示,我们新开了一个 500x500x3 的数组,用于存储调整后的数据。
调整后转存为 Image 得到的图片label_right_6_sigma75.png 显示出来就和原图一样了。


Reshape操作对NCHW格式的图片数据的影响