NumPy拆分图像为16×16子块后如何正确合并还原为原图
图像16x16分块拼接问题解决
问题核心
所有拼接异常、旋转翻转、转张量报错的根源是分块遍历顺序和拼接时的轴变换逻辑不匹配,后续加的旋转、翻转操作属于补丁式修复,没有解决轴顺序的根本问题,还会引入负步长导致PyTorch张量转换失败。
正确实现
numpy存储图像的维度顺序是(垂直方向y, 水平方向x, 通道c),切片im[y:y+16, x:x+16]本身逻辑正确,只需要对齐循环顺序和transpose的轴参数即可,以下是两种可直接运行的方案:
方案1:保留原有分块逻辑,仅修正拼接轴顺序
原有分块代码不需要改动:
import numpy as np import torch block = [] for x in range(0, 224, 16): for y in range(0, 224, 16): block.append(im[y:y+16, x:x+16]) np_block = np.array(block)
该循环是先固定列块位置x,遍历所有行块位置y,因此np_blockreshape为5维后维度含义为(列块数14, 行块数14, 块内y16, 块内x16, 通道3),拼接时调整轴顺序即可,不需要任何旋转翻转操作:
# 轴顺序调整为(行块索引, 块内y坐标, 列块索引, 块内x坐标, 通道) reshaped_img = np_block.reshape(14,14,16,16,3).transpose(1,2,0,3,4).reshape(224,224,3) # 直接转张量无报错,图像完全匹配原图 tensor_img = torch.from_numpy(reshaped_img)
方案2:调整分块遍历顺序为行优先(更符合常规编码直觉)
把外层循环改为遍历行块y,内层遍历列块x,切片保持原有正确顺序:
block = [] # 外层遍历垂直方向的块 for y in range(0, 224, 16): # 内层遍历水平方向的块 for x in range(0, 224, 16): block.append(im[y:y+16, x:x+16]) np_block = np.array(block)
此时reshape后的5维维度含义为(行块数14, 列块数14, 块内y16, 块内x16, 通道3),拼接代码如下:
reshaped_img = np_block.reshape(14,14,16,16,3).transpose(0,2,1,3,4).reshape(224,224,3) tensor_img = torch.from_numpy(reshaped_img)
踩坑说明
- 你之前使用的
transpose(0,3,1,2,4)轴参数完全错误,才会导致拼接后图像旋转翻转,后续加np.rot90、np.flip属于错误逻辑上的补丁:这类操作默认返回原数组的视图,步长为负,PyTorch不支持负步长numpy数组转张量,就算加.copy()也会因为底层轴逻辑错误导致视觉效果异常。 - 你尝试把切片改为
im[x:x+16, y:y+16]是错误修改:直接交换了块内的x、y坐标,会导致块内像素位置错乱,自然无法正确衔接。
内容的提问来源于stack exchange,提问作者Craving_gold
相关产品推荐
相关产品推荐

