1

基于这个代码这个我熟悉实现 imfilter 函数的代码。但是如你所知,这些代码(使用顺序 for 循环)在 matlab 中会非常慢,特别是对于高分辨率图像,它们在其他编程语言中效率更高. 在 matlab 中,最好尽可能对代码进行矢量化。
谁能建议我一种矢量化 imfilter 实现的方法?
注意:我知道我可以使用 edit('imfilter') 来研究开发人员用于实现 imfilter 功能的代码,但这对我来说很难。我不懂很多代码。我对matlab很陌生。
笔记:这段代码可以更容易地实现。
但我正在考虑对代码的主要部分进行矢量化(应用过滤器的一部分)。我的意思是图片中显示的部分:
在此处输入图像描述
在此处输入图像描述
我不知道如何矢量化这些部分?
哦,我忘了告诉我我已经写了这个问题的公认答案。如果我也不想使用 conv2 功能,有什么办法吗?

4

2 回答 2

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 代码,但无法连接到许可证服务器。如果您遇到问题,请告诉我!

为您编辑一些进一步的说明

n-21) 为什么用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”)。

于 2013-06-27T23:00:51.587 回答
1

两个内部循环可以通过-

orignalFlip=flipud(fliplr(orignal(i-1:i+1,j-1:j+1)));
temp=orignalFlip.*filter;

但是“conv2”有什么问题?看来这正是你需要的......

但是,您不应该在 matlab 中执行 4 个嵌套循环。

于 2013-06-27T22:35:49.440 回答