gsi*_*011 31 c++ matlab gaussian blur filter
我的问题非常接近这个问题:如何在不使用任何内置高斯函数的情况下高斯模糊图像?
这个问题的答案非常好,但它没有给出一个实际计算真实高斯滤波器内核的例子.答案给出了一个任意内核,并展示了如何使用该内核应用过滤器,而不是如何计算真实内核本身.我试图从头开始在C++或Matlab中实现高斯模糊,所以我需要知道如何从头开始计算内核.
如果有人能够使用任何小的示例图像矩阵计算真正的高斯滤波器内核,我将不胜感激.
pet*_*hor 33
您可以从头开始创建高斯内核,如MATLAB文档中所述fspecial
.请阅读该页面算法部分中的高斯内核创建公式,并遵循以下代码.代码是用sigma = 1创建m-by-n矩阵.
m = 5; n = 5;
sigma = 1;
[h1, h2] = meshgrid(-(m-1)/2:(m-1)/2, -(n-1)/2:(n-1)/2);
hg = exp(- (h1.^2+h2.^2) / (2*sigma^2));
h = hg ./ sum(hg(:));
h =
0.0030 0.0133 0.0219 0.0133 0.0030
0.0133 0.0596 0.0983 0.0596 0.0133
0.0219 0.0983 0.1621 0.0983 0.0219
0.0133 0.0596 0.0983 0.0596 0.0133
0.0030 0.0133 0.0219 0.0133 0.0030
Run Code Online (Sandbox Code Playgroud)
请注意,这可以通过内置完成,fspecial
如下所示:
fspecial('gaussian', [m n], sigma)
ans =
0.0030 0.0133 0.0219 0.0133 0.0030
0.0133 0.0596 0.0983 0.0596 0.0133
0.0219 0.0983 0.1621 0.0983 0.0219
0.0133 0.0596 0.0983 0.0596 0.0133
0.0030 0.0133 0.0219 0.0133 0.0030
Run Code Online (Sandbox Code Playgroud)
我认为用你喜欢的任何语言实现它都很简单.
编辑:让我也添加h1
和h2
给定的情况的值,因为你可能不熟悉meshgrid
如果你用C++编码.
h1 =
-2 -1 0 1 2
-2 -1 0 1 2
-2 -1 0 1 2
-2 -1 0 1 2
-2 -1 0 1 2
h2 =
-2 -2 -2 -2 -2
-1 -1 -1 -1 -1
0 0 0 0 0
1 1 1 1 1
2 2 2 2 2
Run Code Online (Sandbox Code Playgroud)
thi*_*ton 28
这听起来很简单:
double sigma = 1;
int W = 5;
double kernel[W][W];
double mean = W/2;
double sum = 0.0; // For accumulating the kernel values
for (int x = 0; x < W; ++x)
for (int y = 0; y < W; ++y) {
kernel[x][y] = exp( -0.5 * (pow((x-mean)/sigma, 2.0) + pow((y-mean)/sigma,2.0)) )
/ (2 * M_PI * sigma * sigma);
// Accumulate the kernel values
sum += kernel[x][y];
}
// Normalize the kernel
for (int x = 0; x < W; ++x)
for (int y = 0; y < W; ++y)
kernel[x][y] /= sum;
Run Code Online (Sandbox Code Playgroud)
moo*_*eep 18
要实现高斯模糊,您只需使用高斯函数并为内核中的每个元素计算一个值.
通常,您希望为内核中的中心元素指定最大权重,并为内核边界处的元素指定接近零的值.这意味着内核应具有奇数高度(分别为宽度)以确保实际存在中心元素.
要计算实际的内核元素,您可以将高斯钟调整到内核网格(选择任意例如sigma = 1
和任意范围,例如-2*sigma ... 2*sigma
)并对其进行标准化,将元素总和为1.要实现此目的,如果要支持任意内核大小,可能需要将sigma调整为所需的内核大小.
这是一个C++示例:
#include <cmath>
#include <vector>
#include <iostream>
#include <iomanip>
double gaussian( double x, double mu, double sigma ) {
const double a = ( x - mu ) / sigma;
return std::exp( -0.5 * a * a );
}
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';
}
}
Run Code Online (Sandbox Code Playgroud)
输出是:
$ g++ test.cc && ./a.out
0.00134 0.00408 0.00794 0.00992 0.00794 0.00408 0.00134
0.00408 0.01238 0.02412 0.03012 0.02412 0.01238 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.01238 0.02412 0.03012 0.02412 0.01238 0.00408
0.00134 0.00408 0.00794 0.00992 0.00794 0.00408 0.00134
Run Code Online (Sandbox Code Playgroud)
作为简化,您不需要使用2d内核.更容易实现并且计算效率更高是使用两个正交的1d内核.由于这种类型的线性卷积(线性可分离性)的相关性,这是可能的.您可能还想查看相应维基百科文章的这一部分.
这在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]
Run Code Online (Sandbox Code Playgroud)
生成内核:
['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']
Run Code Online (Sandbox Code Playgroud)