我在互联网上找到了这个Matlab代码.它实际上是整个代码的一部分,可以在这里找到.有人可以逐行解释发生了什么.我真的很绝望......
% ------------- % This is code to make the edge detecting filter % ----%
function filter=gaussfilt(N)
% calculate alpha so the filter fills all N points
alpha=N;
first=-(1-N/2)*exp(-(1-N/2)^2/alpha);
count=0;
while first<.1*(-(1530/4000*N-N/2)*exp(-(1530/4000*N-N/2)^2/alpha))
count=count+1;
alpha=N*500*count;
first=-(1-N/2)*exp(-(1-N/2)^2/alpha);
end
for n=1:N
filter(n)=-(n-N/2)*exp(-(n-N/2)^2/alpha); % d/dt of a gaussian
end
filter=filter/sum(abs(filter)); % normalization
return
Run Code Online (Sandbox Code Playgroud)
此函数尝试返回高斯的梯度 - 当您使用集合数据点进行卷积时,它将检测数据中的边缘,同时平滑平均水平没有突然变化的区域中的点.这是N = 15时的输出:

但是,如果你将N增加到20,就会发生一些疯狂的事情,因为代码是坦率的错误(以及丑陋).而不是一条漂亮的曲线,你最终会得到一条直线 - 一个糟糕的过滤器.这是因为计算新值的尝试alpha是可怕的.
Robert P.已经提供了对代码正在做什么的逐步描述.让我向您展示编写此函数的"正确方法"(您将看到我使用Robert提到的一些技术,以及其他一些我会解释)...
function myFilter = gaussfilt2(N, alpha)
% myFilter = gaussfilt(N, alpha)
% returns an N point normalized array of filter coefficients
% corresponding to the gradient of a Gaussian over the interval [-1 1]
% with a standard deviation of 1/alpha
% in other words, the higher alpha, the sharper the filter
% default value for alpha is 3
if ~exist('alpha', 'var')
alpha = 3;
end
x = linspace( -1, 1, N); % create a vector of N values between -1 and 1 inclusive
sigma = 1.0 / alpha; % convert from alpha to sigma as used in Gaussian formula
% compute first derivative, but leave constants out
% we will normalize later by summing over the coefficients
myFilter = -x .* exp( -(x.^2)/(2*sigma.^2)); % using .* for element-by-element operation
% normalize:
myFilter = myFilter / sum( abs( myFilter ) ); % absolute sum of coefficients is now one
Run Code Online (Sandbox Code Playgroud)
使用N=150和运行此函数时alpha = 3,曲线如下所示:

一些需要解释的技术:
当您%在函数声明的正下方启动注释块(用于指示)时,该文档中的所有内容将在用户请求此功能的帮助时显示给用户(例如,通过在另一个脚本中突出显示函数名称并按F1).总是一个好主意
矢量化 Matlab在做"显式循环"时非常糟糕,并且非常擅长"隐式循环".只要有可能,您希望一次对一大堆值进行"相同的计算".在这种情况下,我计算向量x using thelinspace(x1,x2,n)function. This returns an equally spaced array ofn values fromx1 tox2`包含.现在我可以使用单个语句计算整个函数
元素乘法元素 Matlab真正用于矩阵操作(即"Matlab"中的"Mat" - 它代表矩阵,而不是数学).如果你有两个矢量a和b,并希望将它们相乘元素的元素(所以结果[a(1)8b(1) a(2)*b(2) ... a(n)*b(n)]),可以使用.*运营商.
灵活性而不是"硬连线"alpha的值,使其成为第二个参数,允许您重复使用相同的功能并更改过滤器的清晰度.允许用户省略变量并提供默认值意味着当函数只有一个参数时,程序仍然可以使用它.当具有名称的变量()存在时,exist('alpha', 'var')调用返回.添加函数前面会否定结果 - 就像在其他一些语言中一样.true'var''alpha'~If Not
我完全赞同Floris,但我会告诉你一些关于发生了什么的线索.根据您的问题,我假设您以前从未使用过MATLAB,因此我强烈建议您尝试一些在线提供的教程.
function filter=gaussfilt(N)
Run Code Online (Sandbox Code Playgroud)
这定义了函数的名称gaussfilt,输入变量N和输出变量filter.您的m文件必须另存为gaussfilt.m.
filter是MATLAB中许多内置函数之一,因此不是一个好的变量名.我建议你使用一个名字gauss_filter,或者基本上任何东西.在你的情况下,这可能并不重要,因为你没有使用这个filter功能,但是,使用这些名称是一个坏习惯.这正好与名称,如size,length,max等过.
alpha=N;
first=-(1-N/2)*exp(-(1-N/2)^2/alpha);
count=0;
Run Code Online (Sandbox Code Playgroud)
这些行只是为变量名赋值.exp()是自然的指数.count用于跟踪while循环循环的次数.
while first<.1*(-(1530/4000*N-N/2)*exp(-(1530/4000*N-N/2)^2/alpha))
count=count+1;
alpha=N*500*count;
first=-(1-N/2)*exp(-(1-N/2)^2/alpha);
end
Run Code Online (Sandbox Code Playgroud)
只要满足以下条件while,end就会计算出之间和之间的所有内容.条件应该是自我解释的.
first < .1*(-(1530/4000*N-N/2)*exp(-(1530/4000*N-N/2)^2/alpha))
Run Code Online (Sandbox Code Playgroud)
count增加,以便您可以跟踪循环执行的次数.但是,它从未使用过,因此在这种情况下是不必要的.但是我会建议你保留计数器,并在你的while循环中包含另一个条件,即它应该停止运行count > 1e6,或者其他一些大数字.这样,您将避免在不满足其他条件的情况下永久运行循环.
for n=1:N
filter(n)=-(n-N/2)*exp(-(n-N/2)^2/alpha); % d/dt of a gaussian
end
Run Code Online (Sandbox Code Playgroud)
for n = 1:N是一个循环,它将运行N时间,第一次,第二次等n将值分配给变量中的第th个位置,从而创建一个长度为N的向量.这是创建向量的坏方法.您应该始终为向量分配内存,以避免在循环内生成向量."增长"矢量非常慢.因此,在开始循环之前,您应该执行以下操作:12filter(n) = ..nfilter
filter = zeros(1,N);
Run Code Online (Sandbox Code Playgroud)
这会创建一个零向量.这可能有点过多,但更好的分配值的方法filter是使用arrayfun:
filter = arrayfun(@(n) (-(n-N/2) * exp(-(n-N/2)^2 / alpha)), 1:N);
Run Code Online (Sandbox Code Playgroud)
查看第6点,在这个答案中了解原因.
最后一行:
filter=filter/sum(abs(filter));
Run Code Online (Sandbox Code Playgroud)
那么你将你的filter值除以值的总和,从而创建filter一个总和等于的新值1.这是您将从函数中获得的输出.
使用该功能时,必须编写如下内容:
filter_vector = gaussfilt(N) % where N is an integer
Run Code Online (Sandbox Code Playgroud)
作为最后一句话,请使用空格!它更容易阅读!
再次,我推荐一些MATLAB教程......