我遇到了问题。我有一个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);
也需要很长时间。 我有一些非常大的矩阵,两种解决方案都需要很长时间。 有没有更快的方法?
答案 0 :(得分:3)
+1给@Floris,以获得使用hist
的绝佳建议。它非常快。你可以做得更好一些。 hist
基于histc
,可以替代使用histc
。 nlfilter
是一个已编译的函数,即不是用Matlab编写的,这就是解决方案更快的原因。
这是一个小函数,它试图概括@Floris所做的事情(也就是该解决方案返回一个向量而不是所需的矩阵),并实现了你对im2col
和colfilt
的所作所为。它不要求输入具有特定维度,并使用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?...
以下是情节:
奇怪的是,当你运行这段代码时,mi
的分布并不平坦,而是倾向于较小的值。当您检查直方图时,您将看到这是因为您经常会有多个具有“max”值的bin。在这种情况下,您将获得具有最大数量的第一个bin。这显然会严重扭曲你的结果;要考虑的事情。更好的滤波器可能是中值滤波器 - 上下相邻像素数相等的滤波器。这有一个独特的解决方案(而mode
最多可以有四个值,九个像素 - 即四个分别有两个值的分区。)
要考虑的事情。
今天无法向您展示mex
示例(错误的计算机);但Mathworks网站(以及整个网络上)都有很多很好的例子,很容易理解。请参阅示例http://www.shawnlankton.com/2008/03/getting-started-with-mex-a-short-tutorial/