[英]Python - Find x and y values of a 2D gaussian given a value for the function
我有一個二維高斯 function f(x,y)
。 我知道x₀
的峰值g₀
出現時的值y₀
和 y₀。 但是后來我想找到f(xₑ, yₑ) = g₀ / e¹
處的xₑ
和yₑ
值。 我知道有多種解決方案,但至少有一個就足夠了。
到目前為止我有
def f(x, y, g0,x0,y0,sigma_x,sigma_y,offset):
return offset + g0* np.exp(-(((x-x0)**(2)/(2*sigma_x**(2))) + ((y-y0)**(2)/(2*sigma_y**(2)))))
所有作為參數的變量都是已知的,因為它們是從曲線擬合中提取的。
我知道在x
中取導數並設置f() = 0
並在y
中類似地給出(x,y)
的可解線性系統,但這似乎是手動實現的過大殺傷力,必須有一些庫或工具在那里那可以做我想達到的目標嗎?
有無數種可能性(或者在關於g0
的值的特殊情況下可能有 1 種微不足道或沒有)。 可以使用直接方法在常數時間內分析計算解。 無需近似或迭代方法即可找到給定 function 的根。它只是純數學。
高斯 kernel 具有有趣的對稱性。 其中之一是當峰值轉換為(0,0)
時旋轉的不變性。 另一個是二維高斯曲面的一維截面是高斯曲線。
讓我們暫時忽略offset
:它並沒有真正改變問題(它只是一個 Z 軸平移)並為分辨率添加了額外的無用術語。
問題的幾何解是一個橢圓,所以解(xe, ye)
遵循圓錐表達式: (xe-x0)² / a² + (ye-y0)² / b² = 1
。 如果sigma_x = sigma_y
,則解決方案更簡單:這是一個表達式為(xe-x0)² + (ye-y0)² = r
。 請注意, a
、 b
和r
取決於搜索值和 kernel 參數(例如sigma_x
)。 更改sigma_x
和sigma_y
就像拉伸空間一樣,因此解決方案類似。 改變x0
和y0
就像平移空間,所以解決方案也是如此。
事實上,我們可以解決x0=0
、 y0=0
、 sigma_x=1
和sigma_y=1
的更簡單情況的問題。 然后我們可以應用平移,然后使用變換矩陣進行線性變換。 一個基本的乘法 4x4 矩陣可以做到這一點。 解決更簡單的情況要容易得多,因為要考慮的參數更少。 實際上, g0
和offset
也可以部分舍棄f
,因為它在表達式的兩邊,只需要求解線性方程offset + g0 * h(xe,ye) = g0 / e
so h(x,y) = 1 / e - offset / g0
其中h(xe, ye) = exp(-(xe² + ye²)/2)
。 假設我們暫時忘記平移和線性變換,問題可以很容易地解決:
h(xe, ye) = 1 / e - offset / g0
exp(-(xe² + ye²)/2) = 1 / e - offset / g0
-(xe² + ye²)/2 = ln(1 / e - offset / g0)
xe² + ye² = -2 * ln(1 / e - offset / g0)
而已! 我們得到了我們的圓表達式,其中半徑r
是-2*ln(1 / e - offset / g0)
! 請注意,表達式中的ln
基本上是自然對數。
現在我們可以嘗試找到 4x4 矩陣系數,或者實際上嘗試直接求解完整的表達式,這終於沒有那么困難了。
offset + g0 * exp(-((x-x0)²/(2*sigma_x²) + (y-y0)²/(2*sigma_y²))) = g0 / e
exp(-((x-x0)²/(2*sigma_x²) + (y-y0)²/(2*sigma_y²))) = 1 / e - offset / g0
-((x-x0)²/(2*sigma_x²) + (y-y0)²/(2*sigma_y²)) = ln(1 / e - offset / g0)
((x-x0)²/sigma_x² + (y-y0)²/sigma_y²)/2 = -ln(1 / e - offset / g0)
(x-x0)²/sigma_x² + (y-y0)²/sigma_y² = -2 * ln(1 / e - offset / g0)
而已! 我們得到了圓錐表達式,其中r = -2 * ln(1 / e - offset / g0)
是常數, a = sigma_x
和b = sigma_y
是上述表達式中的未知參數。 可以使用a = sigma_x/sqrt(r)
和b = sigma_y/sqrt(r)
對其進行歸一化,因此右側為 1,與上面的表達式完全吻合,但這只是一些數學細節。
您可以輕松找到橢圓的一個點,因為您知道橢圓的中心(x0, y0)
並且在直線y=y0
和上述二次曲線的交點處至少有 1 個點。 讓我們找到它:
(x-x0)²/sigma_x² + (y0-y0)²/sigma_y² = -2 * ln(1 / e - offset / g0)
(x-x0)²/sigma_x² = -2 * ln(1 / e - offset / g0)
(x-x0)² = -2 * ln(1 / e - offset / g0) * sigma_x²
x = sqrt(-2 * ln(1 / e - offset / g0) * sigma_x²) + x0
請注意,有兩種解決方案 ( -sqrt(...) + x0
),但您只需要其中一種。 我希望我在計算中沒有犯任何錯誤(至少細節應該足以輕松找到它)並且解決方案在您的情況下不是一個復雜的數字。 這個解決方案的好處是計算速度非常非常快。
最終的解決方案是:
(xe, ye) = (sqrt(-2*ln(1/e-offset/g0)*sigma_x²)+x0, y0)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.