如何使用Python旋转3D数组而不进行舍入?

如何使用Python旋转3D数组而不进行舍入?,python,Python,我有一个3D numpy阵列,我想以我想要的角度旋转它。我尝试过使用scipy.ndimage.rotate函数,它可以完成这项工作。但是,它在旋转时会进行很多舍入。这给我带来了一个问题,因为我的3D数组表示一个对象,每个像素中的数字表示像素填充的材质(存储在不同的文件中)。因此,我需要一种在不进行近似或舍入的情况下旋转阵列的方法,并且使对象模糊不是问题 以下是我使用的函数得到的结果: 您正在处理的问题本质上是一个采样问题。对于正在处理的数据,您的分辨率太低。解决此问题的一种可能方法是提高正在

我有一个3D numpy阵列,我想以我想要的角度旋转它。我尝试过使用scipy.ndimage.rotate函数,它可以完成这项工作。但是,它在旋转时会进行很多舍入。这给我带来了一个问题,因为我的3D数组表示一个对象,每个像素中的数字表示像素填充的材质(存储在不同的文件中)。因此,我需要一种在不进行近似或舍入的情况下旋转阵列的方法,并且使对象模糊不是问题

以下是我使用的函数得到的结果:


您正在处理的问题本质上是一个采样问题。对于正在处理的数据,您的分辨率太低。解决此问题的一种可能方法是提高正在处理的图像的分辨率,在旋转时强制执行颜色值(即边缘没有混合颜色),并创建旋转后必须满足的大小/形状模板


编辑:为了清晰起见,不是数据的分辨率太低,而是存储数据的图像的分辨率应该足够高。关于多维抽样的维基百科页面很适合这个主题:

I我认为,在知道实际数据包的情况下,我的处理方法是从索引开始,旋转它们,然后,考虑到它们可能是浮点,将它们四舍五入。这可能不是最好的,但我认为它应该有效

本例的大部分内容是加载我发现用作示例的3D数据集

import matplotlib.pyplot as plt
import os
import numpy as np
from scipy.ndimage import rotate

def load_example_data():
    # Found data as an example
    from urllib.request import urlopen
    import tarfile
    opener = urlopen( 'http://graphics.stanford.edu/data/voldata/MRbrain.tar.gz')
    tar_file = tarfile.open('MRbrain.tar.gz')
    try:
        os.mkdir('mri_data')
    except:
        pass
    tar_file.extractall('mri_data')
    tar_file.close()

    import numpy as np
    data = np.array([np.fromfile(os.path.join('mri_data', 'MRbrain.%i' % i),
                                            dtype='>u2') for i in range(1, 110)])
    data.shape = (109, 256, 256)

    return data

def rotate_nn(data, angle, axes):
    """
    Rotate a `data` based on rotating coordinates.
    """

    # Create grid of indices
    shape = data.shape
    d1, d2, d3 = np.mgrid[0:shape[0], 0:shape[1], 0:shape[2]]

    # Rotate the indices
    d1r = rotate(d1, angle=angle, axes=axes)
    d2r = rotate(d2, angle=angle, axes=axes)
    d3r = rotate(d3, angle=angle, axes=axes)

    # Round to integer indices
    d1r = np.round(d1r)
    d2r = np.round(d2r)
    d3r = np.round(d3r)

    d1r = np.clip(d1r, 0, shape[0])
    d2r = np.clip(d2r, 0, shape[1])
    d3r = np.clip(d3r, 0, shape[2])

    return data[d1r, d2r, d3r]


data = load_example_data()

# Rotate the coordinates indices
angle = 5
axes = (0, 1)

data_r = rotate_nn(data, angle, axes)

我认为总的想法会奏效。你必须考虑轴绕着什么旋转。 旋转90度?你能举一个转换前后的例子吗?@user7784503没有90度是很容易的。问题在于两者之间的角度。我更新了问题以显示结果我认为关键在于你的插值方法,你想找到一个使用最近邻插值而不是样条曲线/三次曲线等的实现。对吗?你可能想看看(嗯,那是2D,但你可以扩展这个想法)@布雷希莫斯:是的,这是正确的。图像是模拟的结果。这就是为什么分辨率很低,不可能获得更好的分辨率。我确实需要做你解释的事情,我想,但我不知道怎么做。不知道你是怎么做的,我不能确切地说怎么做,但这个问题有很好的答案,我想:嗯。。。想想看,你可能需要考虑从<代码> 0…..数据>形状> <代码>范围内旋转的索引。因此,可能需要在
rotate
方法中的
np.round
np.round
之后添加
np.clip()
。我来看看是否能解决这个问题。ValueError:包含多个元素的数组的真值不明确。使用a.any()或a.all()。我似乎从上面的代码中得到了这个错误,是您使用数据时的错误,还是上面的示例数据?是的,是我使用数据时的错误。它是一个只有整数的60,60,25数组。。。我建议您检查d1,并将其与d1r(d2/d3相同)进行比较,确保旋转没有发生异常。(可能是
参数?)。如果不使用实际数据,则不确定。