如何在保留Numpy数组维度的同时无裁剪旋转3D立方体?
解决scipy.ndimage.rotate旋转立方体时的裁剪与维度保留问题
我用解析方程在3D NumPy数组中创建立方体,代码如下(注:原代码存在语法错误,已修正range的终止值):
import numpy as np A = np.zeros((150, 150, 150)) # 存储立方体的数组 r = 15 # 立方体边长 c = (39, 36, 119) # 立方体中心坐标 # 修正原代码的语法错误:range终止值补充r for x in range(c[0] - r, c[0] + r): for y in range(c[1] - r, c[1] + r): for z in range(c[2] - r, c[2] + r): deb = r - max(abs(c[0] - x), abs(c[1] - y), abs(c[2] - z)) # 立方体判定方程 if deb >= 0: A[x, y, z] = 1
这段代码生成与坐标轴对齐的立方体。随后使用scipy.ndimage.rotate旋转立方体:
import scipy.ndimage A = scipy.ndimage.rotate(A, np.random.randint(0, 90), reshape=False, axes=(0, 1))
遇到的问题:
- 设置
reshape=False时,数组维度保留,但旋转后的立方体可能被边缘裁剪 - 设置
reshape=True时,立方体完整无裁剪,但数组形状会改变
需要沿用scipy.ndimage.rotate方法,同时实现保留原数组维度和立方体无裁剪的效果。
解决方案思路
核心是先获取完整旋转后的立方体,再将其居中放置到原尺寸的数组中,既保留原维度,又避免裁剪。具体步骤:
- 用
reshape=True执行旋转,得到完整的旋转后数组(无裁剪) - 计算原数组与旋转后数组的尺寸差,确定居中偏移量
- 创建原尺寸的空数组,将旋转后的立方体居中填充进去
代码实现
import numpy as np import scipy.ndimage # 1. 创建立方体(修正原代码语法错误) A = np.zeros((150, 150, 150)) r = 15 c = (39, 36, 119) for x in range(c[0] - r, c[0] + r): for y in range(c[1] - r, c[1] + r): for z in range(c[2] - r, c[2] + r): deb = r - max(abs(c[0] - x), abs(c[1] - y), abs(c[2] - z)) if deb >= 0: A[x, y, z] = 1 # 2. 执行完整旋转(reshape=True) rotate_angle = np.random.randint(0, 90) A_rotated_full = scipy.ndimage.rotate(A, rotate_angle, reshape=True, axes=(0, 1)) # 3. 将完整旋转后的立方体居中放入原尺寸数组 original_shape = A.shape rotated_shape = A_rotated_full.shape # 计算各维度的偏移量,确保立方体居中 offset_x = (original_shape[0] - rotated_shape[0]) // 2 offset_y = (original_shape[1] - rotated_shape[1]) // 2 offset_z = (original_shape[2] - rotated_shape[2]) // 2 # 本次旋转未涉及z轴,此处offset_z为0 # 创建原尺寸的空数组 A_final = np.zeros(original_shape) # 确定填充区域的边界,避免索引越界 x_slice = slice(max(0, offset_x), min(original_shape[0], offset_x + rotated_shape[0])) y_slice = slice(max(0, offset_y), min(original_shape[1], offset_y + rotated_shape[1])) z_slice = slice(max(0, offset_z), min(original_shape[2], offset_z + rotated_shape[2])) # 对应旋转后数组的切片 rot_x_slice = slice(max(0, -offset_x), min(rotated_shape[0], original_shape[0] - offset_x)) rot_y_slice = slice(max(0, -offset_y), min(rotated_shape[1], original_shape[1] - offset_y)) rot_z_slice = slice(max(0, -offset_z), min(rotated_shape[2], original_shape[2] - offset_z)) # 填充立方体 A_final[x_slice, y_slice, z_slice] = A_rotated_full[rot_x_slice, rot_y_slice, rot_z_slice]
补充说明
- 若旋转涉及其他坐标轴(如(0,2)或(1,2)),只需调整对应的偏移量计算即可
- 此方法的前提是原数组尺寸足够大,能容纳旋转后的立方体。如果原数组本身过小,即使居中也会裁剪,此时需要先对原数组进行padding,旋转后再裁剪回原尺寸
内容的提问来源于stack exchange,提问作者hnambui
相关产品推荐
相关产品推荐

