【问题标题】:Python issue comparing decimated then upsampled 2D arraysPython问题比较抽取然后上采样的二维数组
【发布时间】:2016-05-31 12:46:52
【问题描述】:

我正在尝试研究随着我逐渐减少照片质量而导致的图像质量下降。

为此,我设计了这个实验: - 获取输入图像,并在每次迭代中循环抽取 n 倍和 n-2 倍,获得新图像 A 和 B - 使用 sp.ndimage.interpolation.zoom 上采样到原始大小 A 和 B,缩放因子为 n 和 n-2 - 在每次迭代中计算上采样 A 和 B 之间的元素差异的元素的 mse - 检查每次迭代中 mse 的变化。

这是我的代码:

import numpy as np
import scipy as sp
import matplotlib.pyplot as plt
from skimage import io, feature, color, exposure

# import an image
tut=io.imread('http://www.two-views.com/images/Tut%20bone%20frag.jpg') 
tut=color.rgb2gray(io.imread('Tut.jpg'))  

# contrast stretching
p2, p98 = np.percentile(tut, (2, 98))
st_tut = exposure.rescale_intensity(tut, in_range=(p2, p98))

# decimate progressively, upsample, calculate mse
mse_tut = []

for n in range(6,50,2):
        temp1 = st_tut[::n,::n]
        temp2 = st_tut[::n-2,::n-2]
        tempz1 = sp.ndimage.interpolation.zoom(temp1, n, order=2)
        tempz2 = sp.ndimage.interpolation.zoom(temp2, n-2, order=2)
        mse_temp = ((tempz2 - tempz1) ** 2).mean(axis=None)
        mse_tut.append(mse_temp)

问题是我收到此错误消息:

---> 11 mse_temp = ((tempz2 - tempz1) ** 2).mean(axis=None)

ValueError:操作数无法与形状一起广播 (400,400) (402,402)

我不确定为什么会发生这种情况,因为当我在下面尝试时,一切运行顺利:

temp1 = st_tut[::10,::10]
temp2 = st_tut[::8,::8]

tempz1 = sp.ndimage.interpolation.zoom(temp1, 10, order=2)
tempz2 = sp.ndimage.interpolation.zoom(temp2, 8, order=2)

print temp1.shape, temp2.shape
print tempz1.shape, tempz2.shape

mse_temp = ((tempz2 - tempz1) ** 2).mean(axis=None)
print mse_temp

(40, 40) (50, 50)

(400, 400) (400, 400)

0.00981401032334

【问题讨论】:

  • st_tut.shape 是什么,n 的哪个迭代会崩溃?
  • st_tut.shape 是 400,400,当我在笔记本中工作时,我不确定它在哪个迭代中崩溃
  • 我敢打赌它是第一个。答案即将到来。
  • 是的。这是第一个。如果您对不精确多重上采样没问题,那么有一个简单的解决方法,而不必费劲。

标签: python for-loop multidimensional-array scipy zooming


【解决方案1】:

让我们看一下“顺利”的案例,以了解发生了什么。 temp1 是一个 400x400 / 10 = 40x40 数组。 400 正好除以 10。同样temp2 正好是50x50。上采样时,数组会恢复为 400x400,因为它们是维度的精确倍数。

现在让我们看看当您拥有n = 6 时会发生什么。 temp1400x400 / 6 + 1 = 67x67 数组。整数除法适用于此处,因为您实际上是每第六个元素步进一次。 temp2 是一个 400x400 / 8 = 50x50 数组。对于temp2400 均分为n-2。现在,当您进行上采样时,您会得到一个 66x66 * 6 = 402x402 数组和一个 400x400 数组。

您可以通过以下方式进行测试:

 >>> import numpy as np
 >>> x = np.ones((400, 400))
 >>> x.shape
 (400, 400)
 >>> x[::6, ::6].shape
 (67, 67)

对于这个问题有几个显而易见的解决方案:

  1. 选择n 的值,其中nn-2 使得400 是两者的倍数。这可能会显着限制您的操作范围。虽然是合法的解决方案,但我不推荐它。
  2. scipy.ndimage.interpolation.zoomfloat 作为缩放参数。不要只传入nn-2,而是分别传入400 / temp1.shape[0]400 / temp2.shape[0]。例如,如果temp167x67,这会将其放大5.97014925373 而不是6,从而使上采样大小恰好是400x400

【讨论】:

  • 我将不得不考虑我是否可以使用非整数上采样,因为我正在尝试通过抽取记录站来模拟物理系统。但很高兴知道这是一种选择,在许多类似情况下它可能是完美的。至于您的解决方案 1,如果我将输入图像填充为 2^n 大小(例如 512x512),那也不会太糟糕,正如我在对 Oliver 答案的评论中提到的那样。无论如何,谢谢你的好答案。我将很难在这两个答案之间做出选择。
  • 让我说几句来说服你:你使用的是抛物线样条插值。通过向400x400 图像添加几行和几列创建的“真实”未抽取图像的部分失真是微不足道的。我怀疑它不会妨碍您对物理系统进行准确建模。
【解决方案2】:

原因是切片操作,然后是缩放操作,并不总是返回具有相同数量元素的数组。

当与step 为 2(仅作为示例)一起使用时,切片操作只会返回一个比原始数组有 2*n 个元素的数组小两倍的数组。否则,它将返回元素数量的一半(向下舍入)加 1:

>>> [0,1,2,3][::2]  # 4-element array, will be reduced to 2
[0, 2]  
>>> [0,1,2,3,4][::2] # 5-element array, will be reduced to 3
[0, 2, 4]

将这些结果数组“缩放”2 倍,只会在第一种情况下为您提供具有相同数量元素的数组,但在第二种情况下不会。

因此,结果完全取决于输入数组的大小:在您的情况下,如果它是 n 和 (n-2) 的倍数,那么您会没事的。否则,你不是。

我可以用另一个例子来总结一下:

>>> import numpy as np
>>> 
>>> D = np.arange(10)
>>> for n in range(3,7,2):
...     print(D[::n].shape[0]*n, D[::n-2].shape[0]*(n-2))
... 
12 10
10 12
>>> 

将其与 D = np.arange(15) 的情况进行比较,例如,它是 3 和 1 以及 5 和 3 的倍数(本示例中使用的 2 个后续迭代)。

【讨论】:

  • 所以,只要我比较被 n1 和 n2 抽取的两个集合,它们都是输入数组大小的因子/除数,我就可以了。例如,我可以将原始图像填充为 512x512 的大小,然后使用 n 和 n/2:4、8、16、32、64、128 和 2、4、16、32、64。听起来对吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-24
  • 2015-02-10
  • 2023-02-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多