如何计算高斯加权圆Window?
How to calculate Gaussian-weighted Circular Window?
我有一个矩阵,每个字段都填充了值。大小是例如15x15(225) 现在我想根据矩阵的中心场计算每个场的权重。对于更大的距离,像素值的计算权重将降低。这应该看起来像围绕中心 Field 的圆圈。这里有一个例子图片:
小矩形是中心区域。权重应该是高斯加权循环 window,sigma 为 1.5。我怎么能完成这个?我的想法是……像这样,每个权重都填充到一个具有相同大小的矩阵中,以便之后进行计算。
expf = 1.f/(2.f * 1.5 * 1.5);
[...]
W[k] = (i*i + j*j) * expf;
其中 i 和 j 是距中心像素的距离(例如第一次迭代 i = -7, j = -7
)
对我来说这个解决方案似乎很好,但我得到的值总是很小例如:
W[0]: 3.48362e-10
W[1]: 6.26123e-09
W[2]: 7.21553e-08
W[3]: 5.3316e-07
W[4]: 2.52596e-06
W[5]: 7.67319e-06
W[6]: 1.49453e-05
[...]
W[40]: 0.000523195
W[41]: 0.000110432
W[42]: 1.49453e-05
W[43]: 1.29687e-06
W[44]: 7.21553e-08
W[45]: 5.3316e-07
W[46]: 9.58266e-06
W[47]: 0.000110432
W[48]: 0.000815988
[...]
W[85]: 0.055638
W[86]: 0.0117436
W[87]: 0.00158933
W[88]: 0.000137913
[...]
W[149]: 7.67319e-06
W[150]: 2.52596e-06
W[151]: 4.53999e-05
W[152]: 0.000523195
W[153]: 0.00386592
难道是权重计算错误?
PDF of a multivariate normal distribution是
2 π -k / 2 |Σ|-0.5exp(-0.5 ((x - μ ) |Σ|-1 ((x - μ))
对于你的情况,这转化为
double weight(int i, int j, double var) {
return 1 / (2 * M_PI) * std::exp(-0.5 * (i * i + j * j) / var / var);
}
其中i
和j
以0和0为中心,var
是方差。
注:
这是 PDF。如果您希望值在中心为 1,请使用 weight(i, j, var) / weight(0, 0, var)
。否则,你确实会得到小数字。
衰减由 var
指定 - 较低的值将显示较大的衰减。
以下代码打印
$ g++ --std=c++11 gs.cpp && ./a.out
1
0.884706
1
4.78512e-06
例如
#include <cmath>
#include <iostream>
double weight(int i, int j, double var) {
return 1 / (2 * M_PI) * std::exp(-0.5 * (i * i + j * j) / var / var);
}
int main() {
{
const double f = weight(0, 0, 20);
std::cout << weight(0, 0, 20) / f << std::endl;
std::cout << weight(-7, -7, 20) / f << std::endl;
}
{
const double f = weight(0, 0, 2);
std::cout << weight(0, 0, 2) / f << std::endl;
std::cout << weight(-7, -7, 2) / f << std::endl;
}
}
我有一个矩阵,每个字段都填充了值。大小是例如15x15(225) 现在我想根据矩阵的中心场计算每个场的权重。对于更大的距离,像素值的计算权重将降低。这应该看起来像围绕中心 Field 的圆圈。这里有一个例子图片:
小矩形是中心区域。权重应该是高斯加权循环 window,sigma 为 1.5。我怎么能完成这个?我的想法是……像这样,每个权重都填充到一个具有相同大小的矩阵中,以便之后进行计算。
expf = 1.f/(2.f * 1.5 * 1.5);
[...]
W[k] = (i*i + j*j) * expf;
其中 i 和 j 是距中心像素的距离(例如第一次迭代 i = -7, j = -7
)
对我来说这个解决方案似乎很好,但我得到的值总是很小例如:
W[0]: 3.48362e-10
W[1]: 6.26123e-09
W[2]: 7.21553e-08
W[3]: 5.3316e-07
W[4]: 2.52596e-06
W[5]: 7.67319e-06
W[6]: 1.49453e-05
[...]
W[40]: 0.000523195
W[41]: 0.000110432
W[42]: 1.49453e-05
W[43]: 1.29687e-06
W[44]: 7.21553e-08
W[45]: 5.3316e-07
W[46]: 9.58266e-06
W[47]: 0.000110432
W[48]: 0.000815988
[...]
W[85]: 0.055638
W[86]: 0.0117436
W[87]: 0.00158933
W[88]: 0.000137913
[...]
W[149]: 7.67319e-06
W[150]: 2.52596e-06
W[151]: 4.53999e-05
W[152]: 0.000523195
W[153]: 0.00386592
难道是权重计算错误?
PDF of a multivariate normal distribution是
2 π -k / 2 |Σ|-0.5exp(-0.5 ((x - μ ) |Σ|-1 ((x - μ))
对于你的情况,这转化为
double weight(int i, int j, double var) {
return 1 / (2 * M_PI) * std::exp(-0.5 * (i * i + j * j) / var / var);
}
其中i
和j
以0和0为中心,var
是方差。
注:
这是 PDF。如果您希望值在中心为 1,请使用
weight(i, j, var) / weight(0, 0, var)
。否则,你确实会得到小数字。衰减由
var
指定 - 较低的值将显示较大的衰减。
以下代码打印
$ g++ --std=c++11 gs.cpp && ./a.out
1
0.884706
1
4.78512e-06
例如
#include <cmath>
#include <iostream>
double weight(int i, int j, double var) {
return 1 / (2 * M_PI) * std::exp(-0.5 * (i * i + j * j) / var / var);
}
int main() {
{
const double f = weight(0, 0, 20);
std::cout << weight(0, 0, 20) / f << std::endl;
std::cout << weight(-7, -7, 20) / f << std::endl;
}
{
const double f = weight(0, 0, 2);
std::cout << weight(0, 0, 2) / f << std::endl;
std::cout << weight(-7, -7, 2) / f << std::endl;
}
}