Matlab快速邻居操作

时间:2013-06-01 09:27:42

标签: matlab filter

我遇到了问题。我有一个Matrix A ,其整数值介于0到5之间。 比如:

x=randi(5,10,10)

现在我想调用一个大小为3x3的过滤器,它给出了最常见的值

我尝试了两种解决方案:

fun = @(z) mode(z(:));
y1 = nlfilter(x,[3 3],fun);

需要很长时间......

y2 = colfilt(x,[3 3],'sliding',@mode);

也需要很长时间。 我有一些非常大的矩阵,两种解决方案都需要很长时间。 有没有更快的方法?

2 个答案:

答案 0 :(得分:3)

+1给@Floris,以获得使用hist的绝佳建议。它非常快。你可以做得更好一些。 hist基于histc,可以替代使用histcnlfilter是一个已编译的函数,即不是用Matlab编写的,这就是解决方案更快的原因。

这是一个小函数,它试图概括@Floris所做的事情(也就是该解决方案返回一个向量而不是所需的矩阵),并实现了你对im2colcolfilt的所作所为。它不要求输入具有特定维度,并使用im2col来有效地重新排列数据。实际上,前三行和对colfit的调用几乎与function a=intmodefilt(a,nhood) [ma,na] = size(a); aa(ma+nhood(1)-1,na+nhood(2)-1) = 0; aa(floor((nhood(1)-1)/2)+(1:ma),floor((nhood(2)-1)/2)+(1:na)) = a; [~,a(:)] = max(histc(im2col(aa,nhood,'sliding'),min(a(:))-1:max(a(:)))); a = a-1; 在您的情况下的调用相同。

x = randi(5,10,10);
y3 = intmodefilt(x,[3 3]);

用法:

colfilt

对于大型阵列,这比我机器上的hist快75倍。用histc替换a将导致两倍的加速。当然没有输入检查,因此函数假定1:IMAX是全部整数等。

最后,请注意randi(IMAX,N,N)会返回0:IMAX范围内的值,而非{{1}},因为您似乎已声明。

答案 1 :(得分:2)

一个建议是重塑数组,使每个3x3块成为列向量。如果您的初始数组维度可以被3整除,这很简单。如果他们不这样做,你需要更努力地工作。你需要重复这九次,从不同的偏移开始到矩阵 - 我将把它留作练习。

以下是一些显示基本概念的代码(仅使用FreeMat中可用的函数 - 我家里的机器上没有Matlab ...):

N = 100;
A = randi(0,5*ones(3*N,3*N));
B = reshape(permute(reshape(A,[3 N 3 N]),[1 3 2 4]), [ 9 N*N]);
hh = hist(B, 0:5); % histogram of each 3x3 block: bin with largest value is the mode
[mm mi] = max(hh); % mi will contain bin with largest value
figure; hist(B(:),0:5); title 'histogram of B'; % flat, as expected
figure; hist(mi-1, 0:5); title 'histogram of mi' % not flat?...

以下是情节: enter image description here enter image description here

奇怪的是,当你运行这段代码时,mi的分布并不平坦,而是倾向于较小的值。当您检查直方图时,您将看到这是因为您经常会有多个具有“max”值的bin。在这种情况下,您将获得具有最大数量的第一个bin。这显然会严重扭曲你的结果;要考虑的事情。更好的滤波器可能是中值滤波器 - 上下相邻像素数相等的滤波器。这有一个独特的解决方案(而mode最多可以有四个值,九个像素 - 即四个分别有两个值的分区。)

要考虑的事情。

今天无法向您展示mex示例(错误的计算机);但Mathworks网站(以及整个网络上)都有很多很好的例子,很容易理解。请参阅示例http://www.shawnlankton.com/2008/03/getting-started-with-mex-a-short-tutorial/