我正在嘗試生成一個熱圖,其中像素值由兩個獨立的2D高斯分佈控制。讓它們分別是Kernel1(muX1,muY1,sigmaX1,sigmaY1)和Kernel2(muX2,muY2,sigmaX2,sigmaY2)。更具體地說,每個內核的長度是其標準偏差的三倍。第一個內核有sigmaX1 = sigmaY1,第二個內核有sigmaX2 < sigmaY2。兩個核的協方差矩陣都是對角線(X和Y是獨立的)。 Kernel1通常完全在Kernel2內部。如何高效地計算Python中兩個高斯分佈的熱圖?
我嘗試了以下兩種方法,結果都不令人滿意。有人可以給我一些建議嗎?
Approach1:
遍歷地圖上的所有像素值對(I,J),並通過I(I,J)= P(I,J計算的給定I(I,J)的值| Kernel1,Kernel2)= 1-(1-P(i,j | Kernel1))*(1-P(i,j | Kernel2))。然後我得到了以下結果,這在平滑性方面很好。但是在我的電腦上運行需要10秒,這太慢了。
代碼:
def genDensityBox(self, height, width, muY1, muX1, muY2, muX2, sigmaK1, sigmaY2, sigmaX2):
densityBox = np.zeros((height, width))
for y in range(height):
for x in range(width):
densityBox[y, x] += 1. - (1. - multivariateNormal(y, x, muY1, muX1, sigmaK1, sigmaK1)) * (1. - multivariateNormal(y, x, muY2, muX2, sigmaY2, sigmaX2))
return densityBox
def multivariateNormal(y, x, muY, muX, sigmaY, sigmaX):
return norm.pdf(y, loc=muY, scale=sigmaY) * norm.pdf(x, loc=muX, scale=sigmaX)
Approach2:
產生對應於兩個內核分別兩個圖像,然後使用某些α值一起混合它們。每個圖像通過取兩個一維高斯濾波器的外積來生成。然後我得到了如下結果,這非常粗糙。但是這種方法的優點是由於在兩個向量之間使用外部產品,所以速度非常快。
由於第一個很慢,第二個是粗糙的,我試圖找到一個新的方法,同時實現良好的平滑度和低時間複雜性。有人能給我一些幫助嗎?
謝謝!
對於第二種方法中,2D高斯地圖可以很容易地提到here產生:
def gkern(self, sigmaY, sigmaX, yKernelLen, xKernelLen, nsigma=3):
"""Returns a 2D Gaussian kernel array."""
yInterval = (2*nsigma+1.)/(yKernelLen)
yRow = np.linspace(-nsigma-yInterval/2.,nsigma+yInterval/2.,yKernelLen + 1)
kernelY = np.diff(st.norm.cdf(yRow, 0, sigmaY))
xInterval = (2*nsigma+1.)/(xKernelLen)
xRow = np.linspace(-nsigma-xInterval/2.,nsigma+xInterval/2.,xKernelLen + 1)
kernelX = np.diff(st.norm.cdf(xRow, 0, sigmaX))
kernelRaw = np.sqrt(np.outer(kernelY, kernelX))
kernel = kernelRaw/(kernelRaw.sum())
return kernel