基于这个代码和这个我熟悉实现 imfilter 函数的代码。但是如你所知,这些代码(使用顺序 for 循环)在 matlab 中会非常慢,特别是对于高分辨率图像,它们在其他编程语言中效率更高. 在 matlab 中,最好尽可能对代码进行矢量化。
谁能建议我一种矢量化 imfilter 实现的方法?
注意:我知道我可以使用 edit('imfilter') 来研究开发人员用于实现 imfilter 功能的代码,但这对我来说很难。我不懂很多代码。我对matlab很陌生。
笔记:这段代码可以更容易地实现。
但我正在考虑对代码的主要部分进行矢量化(应用过滤器的一部分)。我的意思是图片中显示的部分:
我不知道如何矢量化这些部分?
哦,我忘了告诉我我已经写了这个问题的公认答案。如果我也不想使用 conv2 功能,有什么办法吗?
2 回答
有一个专为您准备的功能......它被称为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 代码,但无法连接到许可证服务器。如果您遇到问题,请告诉我!
为您编辑一些进一步的说明
n-2
1) 为什么用and重塑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;
并在填充图像上运行过滤器。
'sliding'
2)和之间的区别'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 代码的文件,这些 C 代码可以与 Matlab 链接并为您提供很大的速度优势?这很可能是这样的。他们确实在他们的网站上声称他们使用“直接实现” - 所以速度很可能只是以快速方式实现的问题(而不是“高效的 Matlab”)。
两个内部循环可以通过-
orignalFlip=flipud(fliplr(orignal(i-1:i+1,j-1:j+1)));
temp=orignalFlip.*filter;
但是“conv2”有什么问题?看来这正是你需要的......
但是,您不应该在 matlab 中执行 4 个嵌套循环。