Python 比较抽取然后上采样二维数组的问题
Python issue comparing decimated then upsampled 2D arrays
我正在尝试研究随着我逐渐抽取照片而导致的图像质量下降。
为此,我设计了这个实验:
- 获取输入图像并在循环中在每次迭代中抽取 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: operands could not be broadcast together with shapes
(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
这是因为在具有相同数量元素的数组中,切片操作和缩放操作并不总是 return。
切片操作与 step
2(仅作为示例)一起使用时,如果原始数组有 2*n 个元素,则只会 return 一个两倍小的数组。否则,它将 return 元素数量的一半(向下舍入)加 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]
"Zooming" 那些乘以 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 个后续迭代)的倍数。
让我们看一下 "smooth" 案例,了解发生了什么。 temp1
是一个 400x400 / 10 = 40x40
数组。 400
正好除以 10
。同样 temp2
正好是 50x50
。当您上采样时,数组恢复为 400x400
,因为它们是维度的精确倍数。
现在让我们看看当您拥有 n = 6
时会发生什么。 temp1
是 400x400 / 6 + 1 = 67x67
数组。整数除法在这里适用,因为您实际上是每六个元素步进一次。 temp2
是一个 400x400 / 8 = 50x50
数组。对于temp2
,400
平均分为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)
这个问题有几个显而易见的解决方案:
- Select
n
的值,其中 n
和 n-2
使得 400
是两者的倍数。这可能会大大限制您的操作范围。虽然这是一个合法的解决方案,但我不推荐它。
scipy.ndimage.interpolation.zoom
将 float
作为缩放参数。不要只传入 n
和 n-2
,而是分别传入 400 / temp1.shape[0]
和 400 / temp2.shape[0]
。例如,如果 temp1
是 67x67
,这会将其放大 5.97014925373
而不是 6
,从而使上采样大小正好 400x400
.
我正在尝试研究随着我逐渐抽取照片而导致的图像质量下降。
为此,我设计了这个实验: - 获取输入图像并在循环中在每次迭代中抽取 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: operands could not be broadcast together with shapes (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
这是因为在具有相同数量元素的数组中,切片操作和缩放操作并不总是 return。
切片操作与 step
2(仅作为示例)一起使用时,如果原始数组有 2*n 个元素,则只会 return 一个两倍小的数组。否则,它将 return 元素数量的一半(向下舍入)加 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]
"Zooming" 那些乘以 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 个后续迭代)的倍数。
让我们看一下 "smooth" 案例,了解发生了什么。 temp1
是一个 400x400 / 10 = 40x40
数组。 400
正好除以 10
。同样 temp2
正好是 50x50
。当您上采样时,数组恢复为 400x400
,因为它们是维度的精确倍数。
现在让我们看看当您拥有 n = 6
时会发生什么。 temp1
是 400x400 / 6 + 1 = 67x67
数组。整数除法在这里适用,因为您实际上是每六个元素步进一次。 temp2
是一个 400x400 / 8 = 50x50
数组。对于temp2
,400
平均分为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)
这个问题有几个显而易见的解决方案:
- Select
n
的值,其中n
和n-2
使得400
是两者的倍数。这可能会大大限制您的操作范围。虽然这是一个合法的解决方案,但我不推荐它。 scipy.ndimage.interpolation.zoom
将float
作为缩放参数。不要只传入n
和n-2
,而是分别传入400 / temp1.shape[0]
和400 / temp2.shape[0]
。例如,如果temp1
是67x67
,这会将其放大5.97014925373
而不是6
,从而使上采样大小正好400x400
.