基于this code和this one我熟悉实现imfilter函数。但是你知道这些代码(使用顺序for循环)在matlab中会非常慢,特别是对于高分辨率图像并且它们在其他编程语言中更有效。在matlab中,最好尽可能地对代码进行矢量化
任何人都可以建议我一种矢量化imfilter实现的方法吗?
注意:我知道我可以使用edit('imfilter')来研究开发人员用来实现imfilter函数的代码,但这对我来说很难。我不太了解这些代码。我是matlab的新手
注意:我知道作为示例引入的代码的某些部分可以非常容易地进行矢量化,因此可以更容易地实现this code中的示例填充部分。
但我正在考虑将代码的主要部分(应用过滤器的一部分)进行矢量化。我指的是图片中显示的部分:
我不知道如何对这些部件进行矢量化?
哦,我忘了告诉我已经为this question.编写了接受的答案。如果我也不想使用conv2函数,有什么办法吗?
答案 0 :(得分:3)
只有你的功能...它被称为im2col
。有关说明,请参阅http://www.mathworks.com/help/images/ref/im2col.html。它允许您将图像的“块”转换为“列” - 如果您要查找3x3块进行过滤,则每列将长度为9个元素。之后,过滤操作可以非常简单。这是一个例子:
n = 20; m = 30
myImg = rand(n, m)*255;
myImCol = im2col(myImg, [3 3], 'sliding');
myFilter = [1 2 1 2 4 2 1 2 1]';
myFilter = myFilter / sum(myFilter(:)); % to normalize
filteredImage = reshape( myImCol' * myFilter, n-2, m-2);
没有使用conv2
,也没有使用任何显式循环。然而,这确实产生了一个比图像大得多的中间矩阵(在这种情况下,几乎是9倍)。这本身就是一个问题。
免责声明:我通常在发布前测试Matlab代码,但无法连接到许可证服务器。如果你遇到问题,请告诉我!
编辑为您做进一步的澄清
1)为什么要重塑n-2
和m-2
?好吧 - im2col函数只返回它可以创建的块的“完整”列。当我创建3x3块时,我可以制作的第一个以(2,2)为中心,最后一个在(end-1,end-1)上。因此,结果比原始图像略小 - 它就像“填充”一样。事实上,这与使用conv2
时发生的情况完全相反 - 在这种情况下,事情会得到扩展。如果您想避免这种情况,可以先使用
paddedIm = zeros(n+2, m+2);
paddedIm(2:end-1, 2:end-1) = myImg;
并在填充图像上运行过滤器。
2)'sliding'
和'distinct'
之间的区别最好用一个例子来解释:
>> M = magic(4)
M =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
>> im2col(M,[2 2], 'distinct')
ans =
16 9 3 6
5 4 10 15
2 7 13 12
11 14 8 1
xx-- --xx ---- ----
xx-- --xx ---- ----
---- ---- xx-- --xx
---- ---- xx-- --xx
>> im2col(M,[2 2], 'sliding')
ans =
16 5 9 2 11 7 3 10 6
5 9 4 11 7 14 10 6 15
2 11 7 3 10 6 13 8 12
11 7 14 10 6 15 8 12 1
xx-- ---- ---- -xx-
xx-- xx-- ---- -xx- ... etc ...
---- xx-- xx-- ----
---- ---- xx-- ----
如您所见,'distinct'
选项返回非重叠块:'sliding'
选项返回“所有适合的块”,即使有些块会重叠。
3)conv2
的实现可能是一些较低级别的速度代码 - 您可能知道.mex
文件,它们允许您编写自己的C代码,可以与Matlab链接并为您提供一个很大的速度优势?这可能就是这样的。他们在他们的网站上声称他们使用“直接实现” - 因此速度很可能只是快速实施(而不是“高效的Matlab”)。
答案 1 :(得分:1)
两个内部循环可以通过 -
进行矢量化orignalFlip=flipud(fliplr(orignal(i-1:i+1,j-1:j+1)));
temp=orignalFlip.*filter;
但是' conv2' ?似乎正是你需要的......
但是,你不应该在matlab中做4个嵌套循环。