2014-09-04 160 views
2

我有一个2D numpy数组,代表来自已经被binned 3x3的CCD的单色图像(也就是说,数组中的每个值表示物理CCD上的9个像素(3x3))。重新调整numpy数组

我想重新调整它以匹配原始CCD布局(所以我可以轻松地将它与来自同一CCD的非分档图像叠加)。

我看到Resampling a numpy array representing an image,但这似乎并没有做我想要的。

假设我有一个数组G:

import numpy as np 
import scipy.ndimage 

g = np.array([[0, 1, 2], 
       [3, 4, 5], 
       [6, 7, 8]]) 

当我尝试的2倍,以它的规模:

o = scipy.ndimage.zoom(g, 2, order=0) 

我得到正是我所期待的 - 每个值现在是2×2相同值:

array([[0, 0, 1, 1, 2, 2], 
     [0, 0, 1, 1, 2, 2], 
     [3, 3, 4, 4, 5, 5], 
     [3, 3, 4, 4, 5, 5], 
     [6, 6, 7, 7, 8, 8], 
     [6, 6, 7, 7, 8, 8]]) 

但是,当我尝试了3倍缩放,我得到这个:

o = scipy.ndimage.zoom(g, 3, order=0) 

给我:

array([[0, 0, 1, 1, 1, 1, 2, 2, 2], 
     [0, 0, 1, 1, 1, 1, 2, 2, 2], 
     [3, 3, 4, 4, 4, 4, 5, 5, 5], 
     [3, 3, 4, 4, 4, 4, 5, 5, 5], 
     [3, 3, 4, 4, 4, 4, 5, 5, 5], 
     [3, 3, 4, 4, 4, 4, 5, 5, 5], 
     [6, 6, 7, 7, 7, 7, 8, 8, 8], 
     [6, 6, 7, 7, 7, 7, 8, 8, 8], 
     [6, 6, 7, 7, 7, 7, 8, 8, 8]]) 

我想原来的数组中的每个值成为一组3×3的值......这不是我所得到的。

我该怎么办? (为什么我得到这个结果直观?)

+1

为什么-1?这是一个坏问题吗?太多标签?作为一个SO新手,我会很感激一些关于我做错了什么的反馈。 – 2014-09-05 01:06:48

+0

我的猜测是,有人看到了这个,知道答案,并假定你没有阅读过zoom的文档,因此把你当作帮助吸血鬼。就我个人而言,我可以理解为什么在阅读'zoom'文档后仍然可能会感到困惑,但我想你可以更好地解释一下?我不知道。 – abarnert 2014-09-05 22:11:12

+0

似乎是http://stackoverflow.com/questions/7525214/how-to-scale-a-numpy-array?rq=1 – 2015-03-30 17:38:41

回答

3

您可以使用np.kron

In [16]: g 
Out[16]: 
array([[0, 1, 2], 
     [3, 4, 5], 
     [6, 7, 8]]) 

In [17]: np.kron(g, np.ones((3,3), dtype=int)) 
Out[17]: 
array([[0, 0, 0, 1, 1, 1, 2, 2, 2], 
     [0, 0, 0, 1, 1, 1, 2, 2, 2], 
     [0, 0, 0, 1, 1, 1, 2, 2, 2], 
     [3, 3, 3, 4, 4, 4, 5, 5, 5], 
     [3, 3, 3, 4, 4, 4, 5, 5, 5], 
     [3, 3, 3, 4, 4, 4, 5, 5, 5], 
     [6, 6, 6, 7, 7, 7, 8, 8, 8], 
     [6, 6, 6, 7, 7, 7, 8, 8, 8], 
     [6, 6, 6, 7, 7, 7, 8, 8, 8]]) 

zoom(g, 3, order=0)输出是有点出人意料。考虑第一行:[0, 0, 1, 1, 1, 1, 2, 2, 2]。为什么有四个1

order=0变焦(实际上)计算np.linspace(0, 2, 9),它看起来像

In [80]: np.linspace(0, 2, 9) 
Out[80]: array([ 0. , 0.25, 0.5 , 0.75, 1. , 1.25, 1.5 , 1.75, 2. ]) 

,然后舍入值。如果你使用np.round(),您可以:

In [71]: np.round(np.linspace(0, 2, 9)).astype(int) 
Out[71]: array([0, 0, 0, 1, 1, 1, 2, 2, 2]) 

注意np.round(0.5)0,但np.round(1.5)2np.round()使用"round half to even" tie-breaking rule。显然,在zoom代码进行舍入使用"round half down" rule:便将0.501.51,如下面的

In [81]: [int(round(x)) for x in np.linspace(0, 2, 9)] 
Out[81]: [0, 0, 1, 1, 1, 1, 2, 2, 2] 

,这就是为什么有四个1在里面。

+0

的副本我知道我不应该发布“感谢”评论,但感谢您添加解释为什么缩放()不符合我的预期。现在它是有道理的。如果可以的话,我会再给你一个+1 ... – 2014-09-05 15:12:06

2

为什么我会得到这个不直观的结果?

因为zoom是样条插值函数。换句话说,它从该中点1到该中点0绘制一个三次样条,并且它们之间的值将得到该样条的值在适当的位置。

如果您想要最近的,线性或二次插值而不是立方,可以使用order=0order=1order=2参数。但是如果你根本不需要插值 - 你不要使用插值函数。这就像问为什么使用[int(i*2.3) for i in range(10)]来获得从0到20的偶数给你一些奇数。从0到20的偶数并不是一个函数,所以它不会这样做,但它完全符合您的要求。


我该怎么办呢?

再一次,如果你想要非插值缩放,不要使用插值函数。最简单的方法可能是使用np.kron,对Kroenecker-用np.ones((scale, scale))乘以你的数组。

+0

嗯。如果“nearest = order = 0”(根据http://stackoverflow.com/questions/13242382/resampling-a-numpy-array-representing-an-image),那么结果仍然看起来不直观。但我已经得到了我的答案。 – 2014-09-05 00:51:10

+0

@ nerdfever.com:是的,最接近的是订单= 0。原始数组中的最接近的值与展开数组中的第三个值是第二个,而不是第一个。我将更详细地解释这一点,但我只注意到沃伦韦克塞已经做得很好。太糟糕了,我已经提出了他的原始答案,因为他编辑的版本值得另一个。 :) – abarnert 2014-09-05 17:37:35

+0

@abanert:真的吗?我想你一定是对的,否则他们不会那样做,但是从一维角度看,我们有[n1 n2 n3]映射到[m1 m2 m3 m4 m5 m6 m7 m8 m8 m9]。我会假设(也许错误)n1映射到m2和n2映射到m5。如果是这样,那么m3比n2更接近n1,并且应该得到n1的值。不知怎的,除非你在两个维度上都称“最接近”。但我认为“最接近”的意思是“最接近”,而不是“加权后最接近”。 [也许我认为是错误的。]即使在2维空间中,m3与m2的相邻值并不与任何其他映射值相邻。 – 2014-09-05 19:49:51