首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Matlab编码说明

Matlab编码说明
EN

Stack Overflow用户
提问于 2013-06-16 22:36:30
回答 2查看 994关注 0票数 0

我在互联网上找到了这段Matlab代码。它实际上是整个代码的一部分,可以在here中找到。有人能逐行解释一下发生了什么吗。我真的很绝望..。

代码语言:javascript
运行
复制
% ------------- % 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
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-06-17 01:05:38

此函数尝试返回高斯的梯度-当您将其与一组0个数据点进行卷积时,它将检测数据中的边缘,同时平滑均值水平没有突然变化的区域中的点。以下是N=15时的输出:

然而,如果你将N增加到20,一些疯狂的事情发生了,因为坦率地说,代码有buggy (以及丑陋)。你最终得到的不是一条漂亮的曲线,而是一条直线--一个糟糕的过滤器。这是因为尝试为alpha计算一个新值是非常可怕的。

Robert P.已经一步一步地描述了代码的作用。让我向您展示编写此函数的“正确方法”(您将看到我使用了Robert提到的一些技术,以及我将解释的其他一些技术)……

代码语言:javascript
运行
复制
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

当您使用N=150alpha = 3运行此函数时,曲线如下所示:

以下是一些需要解释的技术:

documentation当您在函数声明的正下方启动一个注释块(用%表示)时,当用户请求有关此函数的帮助时,将向用户显示该块中的所有内容(例如,通过突出显示另一个脚本中的函数名称并按F1键)。永远是个好主意

vectorization Matlab在“显式循环”方面做得很糟糕,而在“隐式循环”方面却做得很好。只要有可能,你就想一次对一大堆值进行“相同的计算”。在本例中,我计算了一个向量x )function. This returns an equally spaced array ofnvalues fromx1tox2` (包括x1,x2,nusing the)。现在,我可以用一条语句计算整个函数

Matlab by element matrix 实际上是为矩阵操作而设计的(这是"Matlab“中的"Mat”-它代表矩阵,而不是数学)。如果您有两个向量ab,并且希望将它们逐个元素相乘(因此结果是[a(1)8b(1) a(2)*b(2) ... a(n)*b(n)]),则可以使用.*运算符。

flexibility代替“硬连接”alpha的值,使其成为第二个参数,允许您重用相同的函数并更改滤镜的锐度。允许用户省略变量并提供默认值意味着当函数只有一个参数时编写的程序仍然可以使用该变量。当存在名为true的变量('var')时,exist('alpha', 'var')调用将返回'alpha'。在函数前面添加~会使结果无效--这与其他语言中的If Not类似。

票数 7
EN

Stack Overflow用户

发布于 2013-06-16 23:23:07

我完全同意弗洛里斯的观点,但我会给你一些关于发生了什么的线索。根据您的问题,我假设您以前从未使用过MATLAB,因此我强烈建议您尝试在线提供的许多教程中的一些。

代码语言:javascript
运行
复制
function filter=gaussfilt(N)

它定义了函数gaussfilt、输入变量N和输出变量filter的名称。M文件必须另存为gaussfilt.m

filter是MATLAB中众多内置函数之一,因此不是一个好的变量名。我建议您使用诸如gauss_filter之类的名称,或者基本上使用任何其他名称。在您的例子中,这可能并不重要,因为您没有使用filter函数,但是,使用这样的名称是一个坏习惯。这也适用于sizelengthmax等名称。

代码语言:javascript
运行
复制
alpha=N;
first=-(1-N/2)*exp(-(1-N/2)^2/alpha);
count=0;

这些行的作用仅仅是给变量名赋值。exp()是自然指数。count用于跟踪您的while循环循环次数。

代码语言:javascript
运行
复制
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

只要满足下面的条件,就会计算whileend之间的所有内容。条件应该是不言而喻的。

代码语言:javascript
运行
复制
first < .1*(-(1530/4000*N-N/2)*exp(-(1530/4000*N-N/2)^2/alpha))

count会递增,这样您就可以跟踪循环执行了多少次。但是,它从未使用过,因此在此上下文中是不必要的。但是,我建议您保留计数器,并在您的while循环中包含另一个条件,即如果出现count > 1e6或其他较大的数字,则应停止运行。这样,您将避免在另一个条件不满足的情况下永远运行的循环。

代码语言:javascript
运行
复制
for n=1:N
     filter(n)=-(n-N/2)*exp(-(n-N/2)^2/alpha);   % d/dt of a gaussian
end

for n = 1:N是一个循环,它将运行N时间,其中n第一次将为1,第二次为2,依此类推。filter(n) = ..将该值分配给filter变量中的nth位置,从而创建一个长度为N的向量。这是创建向量的糟糕方法。您应该始终为向量分配内存,以避免向量在循环中增长。一个“增长”的向量是非常非常慢的。因此,在开始循环之前,您应该执行以下操作:

代码语言:javascript
运行
复制
filter = zeros(1,N);

它创建了一个零向量。这可能有点太多了,但是给filter赋值的更好方法是使用arrayfun

代码语言:javascript
运行
复制
filter = arrayfun(@(n) (-(n-N/2) * exp(-(n-N/2)^2 / alpha)), 1:N);

请查看this answer中的第6点,以了解原因。

最后一行:

代码语言:javascript
运行
复制
filter=filter/sum(abs(filter));

您可以将filter值除以这些值的总和,从而创建一个新的filter,其和等于1。这是您将从函数中获得的输出。

使用该函数时,必须编写类似以下内容的代码:

代码语言:javascript
运行
复制
filter_vector = gaussfilt(N) % where N is an integer

最后一句话,使用空格!它更容易阅读!

再一次,我推荐一些MATLAB教程。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17134389

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档