【问题标题】:How to rotate a 3D array without rounding, by using Python?如何使用 Python 旋转 3D 数组而不进行舍入?
【发布时间】:2019-11-02 05:49:28
【问题描述】:

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

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

【问题讨论】:

  • 旋转 90 度?你能举个改造前后的例子吗?
  • @user7784503 没有 90 度是容易的。问题是之间的角度。我已更新问题以显示结果
  • 我认为关键是你的插值方法,你想找到一个使用最近邻插值而不是样条/三次等的实现。对吗?
  • 你可能想看看codereview.stackexchange.com/questions/41688/…(嗯,那是2D,但你可以扩展这个想法)
  • @brechmos 是的,没错

标签: python


【解决方案1】:

您正在处理的问题本质上是一个抽样问题。对于您正在处理的数据,您的分辨率太低。解决此问题的一种可能性是增加您正在使用的图像的分辨率,在您旋转时强制颜色值(即边缘不混合颜色),并创建旋转后必须满足的尺寸/形状模板。

编辑:为清楚起见,分辨率太低的不是数据,而是存储数据的图像应该具有足够高的分辨率。关于多维采样的维基百科页面非常适合这个主题:https://en.wikipedia.org/wiki/Multidimensional_sampling

【讨论】:

  • 图像是模拟的结果。这就是分辨率低且无法获得更好分辨率的原因。我确实需要按照您的解释去做,但我不知道该怎么做。
  • 在不知道你是怎么做的情况下,我不能确切地说该怎么做,但我认为这个问题有很好的答案:stackoverflow.com/questions/48121916/numpy-resize-rescale-image
【解决方案2】:

认为我会接近它的方式,除了有人知道执行此操作的实际包之外,从索引开始并旋转它们,然后,鉴于它们可能是浮点数,将它们四舍五入.这可能不是最好的,但我认为它应该可以工作。

此示例的大部分内容是加载我发现用作示例的 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)

认为总体思路可行。您将不得不考虑要围绕什么轴旋转。

【讨论】:

  • Hmmm... 想一想,您可能不得不考虑旋转超出0..data.shape 范围的索引。因此,可能需要在rotate_nn 方法中的rotatenp.round 之后添加np.clip()。我看看能不能把它清理干净。
  • ValueError:具有多个元素的数组的真值不明确。使用 a.any() 或 a.all()。我似乎用上面的代码得到了这个错误
  • 是你使用你的数据时出错,还是上面的示例数据?
  • 是的,当我使用我的数据时。它是一个只有整数的 60,60,25 数组
  • 嗯...我建议您检查 d1 并将其与 d1r(d2/d3 相同)进行比较,并确保旋转没有做奇怪的事情。 (可能是axes 参数?)。如果不使用实际数据就不确定。
猜你喜欢
  • 1970-01-01
  • 2013-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-03
相关资源
最近更新 更多