Performance 对图像应用线性滤波器(实现imfilter)而不影响速度和性能
基于,我熟悉imfilter函数的实现。但正如您所知,这类代码(使用顺序for循环)在matlab中非常慢,特别是对于高分辨率图像,并且在其他编程语言中效率更高。在matlab中,最好尽可能多地对代码进行矢量化。Performance 对图像应用线性滤波器(实现imfilter)而不影响速度和性能,performance,matlab,image-processing,time,Performance,Matlab,Image Processing,Time,基于,我熟悉imfilter函数的实现。但正如您所知,这类代码(使用顺序for循环)在matlab中非常慢,特别是对于高分辨率图像,并且在其他编程语言中效率更高。在matlab中,最好尽可能多地对代码进行矢量化。 有人能给我一个矢量化imfilter实现的方法吗? 注意:我知道我可以使用edit('imfilter')来研究开发人员用于实现imfilter函数的代码,但这对我来说相当困难。我不太懂这些代码。我对matlab相当陌生。 注意:我知道作为示例介绍的部分代码可以非常容易地矢量化,因此中
有人能给我一个矢量化imfilter实现的方法吗?
注意:我知道我可以使用edit('imfilter')来研究开发人员用于实现imfilter函数的代码,但这对我来说相当困难。我不太懂这些代码。我对matlab相当陌生。
注意:我知道作为示例介绍的部分代码可以非常容易地矢量化,因此中的示例填充部分可以更容易地实现。
但是我正在考虑一种方法来对代码的主要部分(应用过滤器的部分)进行矢量化。我指的是图片中显示的部分:
我不知道如何将这些部分矢量化?
哦,我忘了告诉你我已经写了公认的答案,如果我也不想使用conv2函数,有什么办法吗?两个内部循环可以通过-
orignalFlip=flipud(fliplr(orignal(i-1:i+1,j-1:j+1)));
temp=orignalFlip.*filter;
但是“conv2”有什么问题呢?看来这正是你需要的
但是,您不应该在matlab中执行4个嵌套循环。这两个内部循环可以通过-
orignalFlip=flipud(fliplr(orignal(i-1:i+1,j-1:j+1)));
temp=orignalFlip.*filter;
但是“conv2”有什么问题呢?看来这正是你需要的
但是,您不应该在matlab中执行4个嵌套循环。有一个函数只适合您。。。它被称为
im2col
。有关说明,请参阅。它允许您将图像的“块”转换为“列”-如果您正在寻找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);
>> 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-- ----
没有使用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) 最好用一个例子来解释'slided'
和'distinct'
之间的区别:
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);
>> 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'
选项返回非重叠块:'slided'
选项返回“适合的所有块”,即使有些块会重叠
3)
conv2
的实现可能是一些较低级别的速度代码-您可能知道.mex
文件,这些文件允许您编写自己的C代码,可以与Matlab链接,并给您带来很大的速度优势?很可能是这样的。他们在自己的网站上声称他们使用的是“简单的实现”——因此速度很可能只是一个快速实现的问题(而不是“高效的Matlab”)。有一个函数只适合你。。。它被称为im2col
。有关说明,请参阅。它允许您将图像的“块”转换为“列”-如果您正在寻找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);
>> 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-- ----
没有使用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) 最好用一个例子来解释'slided'
和'distinct'
之间的区别:
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);
>> 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'
选项返回非重叠块:'slided'
选项返回“适合的所有块”,即使有些块会重叠
3)
conv2
的实现可能是一些较低级别的速度代码-您可能知道.mex
文件,这些文件允许您编写自己的C代码,可以与Matlab链接,并给您带来很大的速度优势?很可能是这样的。他们在自己的网站上声称他们使用了“直接的实现”——因此速度很可能只是一个快速实现的问题(而不是“高效的Matlab”)。来自MathWorks的文章。另请参见MathWorks上的这篇文章。再看看这个。这是一个大学作业。我不应该使用内置函数