有效地生成"转移" python中的高斯内核

时间:2015-03-09 18:28:54

标签: python numpy scipy

我有一个(非常大)数量的数据点,每个数据点由x和y坐标和sigma不确定性组成(sigma在x和y方向都相同;所有三个变量都是浮点数)。对于每个数据点,我想在标准网格上生成一个二维数组,其概率是实际值在该位置。

例如,如果x = 5.0,y = 5.0,sigma = 1.0,在(0,0) - >(9,9)网格上,我希望生成:

   [ 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ],
   [ 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ],
   [ 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ],
   [ 0.  ,  0.  ,  0.  ,  0.  ,  0.01,  0.02,  0.01,  0.  ,  0.  ,  0.  ],
   [ 0.  ,  0.  ,  0.  ,  0.01,  0.06,  0.1 ,  0.06,  0.01,  0.  ,  0.  ],
   [ 0.  ,  0.  ,  0.  ,  0.02,  0.1 ,  0.16,  0.1 ,  0.02,  0.  ,  0.  ],
   [ 0.  ,  0.  ,  0.  ,  0.01,  0.06,  0.1 ,  0.06,  0.01,  0.  ,  0.  ],
   [ 0.  ,  0.  ,  0.  ,  0.  ,  0.01,  0.02,  0.01,  0.  ,  0.  ,  0.  ],
   [ 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ],
   [ 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ]]

上面是通过创建一个带有零的numpy数组生成的,[5,5] = 1,然后将ndimage.filters.gaussian_filter与sigma一起应用1.我感觉我可以处理通过分布在附近的整数值上得到非整数x和y,得到一个很好的近似值。

然而,由于scipy必须考虑所有值,而不仅仅是位置中的1 [5,5],即使它们都是0,但感觉极度过度杀戮是非常难以理解的。对于64x64网格需要300us,但是,我仍然想知道是否没有更有效的方法来获得具有任意x,y和sigma的高斯内核的X * Y numpy数组。

2 个答案:

答案 0 :(得分:6)

一种相当快速的方法是注意高斯是可分的,因此您可以计算xy的1D高斯,然后获取外部产品:

import numpy as np
import matplotlib.pyplot as plt

x0, y0, sigma = 5.5, 4.2, 1.4

x, y = np.arange(9), np.arange(9)

gx = np.exp(-(x-x0)**2/(2*sigma**2))
gy = np.exp(-(y-y0)**2/(2*sigma**2))
g = np.outer(gx, gy)
g /= np.sum(g)  # normalize, if you want that

plt.imshow(g, interpolation="nearest", origin="lower")
plt.show()

enter image description here

答案 1 :(得分:2)

@ tom10的外部产品答案可能是这个特殊情况的最佳选择。如果您想在两个(或更多)维度中使用任意函数制作核心,您可能需要查看import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import java.util.concurrent.Semaphore; public class Proof { private Semaphore mutex = new Semaphore(0, true); private boolean remember = false; private Activity context; public Proof(Activity context) { this.context = context; } private boolean showDialogMismoArchivo() { context.runOnUiThread(new Runnable() { public void run() { String[] item = {"Apply all"}; AlertDialog ad = new AlertDialog.Builder(context) .setTitle("¿Reemplazar?") .setMultiChoiceItems(item, null, new DialogInterface.OnMultiChoiceClickListener() { @Override public void onClick(DialogInterface dialog, int indexSelected, boolean isChecked) { if (isChecked) remember = true; else remember = false; } }) .setPositiveButton("Ok", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { mutex.release(); } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { mutex.release(); } }) .create(); ad.show(); } }); try { mutex.acquire(); } catch (InterruptedException e) { e.printStackTrace(); } return remember; } } np.indices

例如:

np.meshgrid

哪个收益率:

def gaussian(x, mu=0, sigma=1):
    n = np.prod(sigma)*np.sqrt(2*np.pi)**len(x)
    return np.exp(-0.5*(((x-mu)/sigma)**2).sum(0))/n

gaussian(np.indices((10,10)), mu=5, sigma=1)

为了获得更大的灵活性,您可以使用array([[ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ], [ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ], [ 0. , 0. , 0. , 0. , 0.001, 0.002, 0.001, 0. , 0. , 0. ], [ 0. , 0. , 0. , 0.003, 0.013, 0.022, 0.013, 0.003, 0. , 0. ], [ 0. , 0. , 0.001, 0.013, 0.059, 0.097, 0.059, 0.013, 0.001, 0. ], [ 0. , 0. , 0.002, 0.022, 0.097, 0.159, 0.097, 0.022, 0.002, 0. ], [ 0. , 0. , 0.001, 0.013, 0.059, 0.097, 0.059, 0.013, 0.001, 0. ], [ 0. , 0. , 0. , 0.003, 0.013, 0.022, 0.013, 0.003, 0. , 0. ], [ 0. , 0. , 0. , 0. , 0.001, 0.002, 0.001, 0. , 0. , 0. ], [ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ]]) 来控制域名的范围和范围:

np.meshgrid

为此,kern = gaussian(np.meshgrid(np.linspace(-10, 5), np.linspace(-2, 2))) 将为kern.shape,因为(50, 50)50的默认长度,np.linspace定义了meshgrid和数组的x轴传递给它。执行此操作的等效方法是y

gaussian kernel