为了实现gaussian blur你干脆把gaussian function和计算每个在你的核心要素之一值。
通常情况下,您希望将最大权重分配给内核中的中心元素,并将内核边界上的元素的值设置为接近零。 这意味着内核应该有一个奇数的高度(resp.width)来确保实际上有一个中心元素。
要计算实际内核元素,您可以将高斯钟放大到内核网格(选择一个任意的例如sigma = 1
和任意范围,例如-2*sigma ... 2*sigma
)并将其归一化,即s.t.元素总和为1。 为了达到这个目的,如果你想支持任意内核大小,你可能需要将sigma调整为所需的内核大小。
下面是一个C++例子:
#include <cmath>
#include <vector>
#include <iostream>
#include <iomanip>
double gaussian (double x, double mu, double sigma) {
return std::exp(-(((x-mu)/(sigma))*((x-mu)/(sigma)))/2.0);
}
typedef std::vector<double> kernel_row;
typedef std::vector<kernel_row> kernel_type;
kernel_type produce2dGaussianKernel (int kernelRadius) {
double sigma = kernelRadius/2.;
kernel_type kernel2d(2*kernelRadius+1, kernel_row(2*kernelRadius+1));
double sum = 0;
// compute values
for (int row = 0; row < kernel2d.size(); row++)
for (int col = 0; col < kernel2d[row].size(); col++) {
double x = gaussian(row, kernelRadius, sigma)
* gaussian(col, kernelRadius, sigma);
kernel2d[row][col] = x;
sum += x;
}
// normalize
for (int row = 0; row < kernel2d.size(); row++)
for (int col = 0; col < kernel2d[row].size(); col++)
kernel2d[row][col] /= sum;
return kernel2d;
}
int main() {
kernel_type kernel2d = produce2dGaussianKernel(3);
std::cout << std::setprecision(5) << std::fixed;
for (int row = 0; row < kernel2d.size(); row++) {
for (int col = 0; col < kernel2d[row].size(); col++)
std::cout << kernel2d[row][col] << ' ';
std::cout << '\n';
}
}
输出是:
$ g++ test.cc && ./a.out
0.00134 0.00408 0.00794 0.00992 0.00794 0.00408 0.00134
0.00408 0..02412 0.03012 0.02412 0..00408
0.00794 0.02412 0.04698 0.05867 0.04698 0.02412 0.00794
0.00992 0.03012 0.05867 0.07327 0.05867 0.03012 0.00992
0.00794 0.02412 0.04698 0.05867 0.04698 0.02412 0.00794
0.00408 0..02412 0.03012 0.02412 0..00408
0.00134 0.00408 0.00794 0.00992 0.00794 0.00408 0.00134
当你不需要使用2D内核的简化。更容易实现,而且计算效率更高的是使用两个正交的1d内核。由于这种类型的线性卷积(线性可分性)的相关性,这是可能的。 您可能还想看到相应维基百科文章的this section。
这里是用Python一样(希望有人可能会发现它很有用):
from math import exp
def gaussian(x, mu, sigma):
return exp(-(((x-mu)/(sigma))**2)/2.0)
#kernel_height, kernel_width = 7, 7
kernel_radius = 3 # for an 7x7 filter
sigma = kernel_radius/2. # for [-2*sigma, 2*sigma]
# compute the actual kernel elements
hkernel = [gaussian(x, kernel_radius, sigma) for x in range(2*kernel_radius+1)]
vkernel = [x for x in hkernel]
kernel2d = [[xh*xv for xh in hkernel] for xv in vkernel]
# normalize the kernel elements
kernelsum = sum([sum(row) for row in kernel2d])
kernel2d = [[x/kernelsum for x in row] for row in kernel2d]
for line in kernel2d:
print ["%.3f" % x for x in line]
产生内核:使用PIL图像库在Python
['0.001', '0.004', '0.008', '0.010', '0.008', '0.004', '0.001']
['0.004', '0.012', '0.024', '0.030', '0.024', '0.012', '0.004']
['0.008', '0.024', '0.047', '0.059', '0.047', '0.024', '0.008']
['0.010', '0.030', '0.059', '0.073', '0.059', '0.030', '0.010']
['0.008', '0.024', '0.047', '0.059', '0.047', '0.024', '0.008']
['0.004', '0.012', '0.024', '0.030', '0.024', '0.012', '0.004']
['0.001', '0.004', '0.008', '0.010', '0.008', '0.004', '0.001']
你读过这一点:http://en.wikipedia.org/wiki/Gaussian_function? –
甚至是这样:http://en.wikipedia.org/wiki/Gaussian_blur – Bart
是的,我花了很多时间去理解这些。我需要的是一步一步的例子。在我了解它之后,我可能会将示例添加到高斯模糊页面。 – gsingh2011