2014-11-22 20 views
1

我目前正在做一个案例研究,改善性能的可分离滤波器与方形滤波器。我理解时间复杂性差异背后的数学,但是我遇到了真实世界实现的问题。图像滤波可分矩阵速度MATLAB

所以基本上我所要做的就是写一个循环鉴于它实现了我的过滤图像功能:

function imOut = FilterImage(imIn, kernel, boundFill, outputSize) 


VkernelOffset = floor(size(kernel,1)/2); 
HkernelOffset = floor(size(kernel,2)/2); 


imIn = padarray(imIn, [VkernelOffset HkernelOffset], boundFill); 


imInPadded = padarray(imIn, [VkernelOffset HkernelOffset], boundFill); 


imOut = zeros(size(imIn)); 


kernelVector = reshape(kernel,1, []); 
kernelVector3D = repmat(kernelVector, 1, 1, size(imIn,3)); 


for row = 1:size(imIn,1) 
    Vwindow = row + size(kernel,1)-1; 
    for column = 1:size(imIn,2) 
     Hwindow = column + size(kernel,2)-1; 

     imInWindowVector = reshape(... 
      imInPadded(row:Vwindow, column:Hwindow, :),1,[],size(imIn,3)); 

     imOut(row,column, :) = sum((imInWindowVector.*kernelVector3D),2); 
    end 
end 


ouputSize = lower(outputSize); 


if strcmp(outputSize, 'same') 
imOut = imOut((1+VkernelOffset):(size(imOut,1)-VkernelOffset), ... 
    (1+HkernelOffset):(size(imOut,2)-HkernelOffset), :); 
elseif strcmp(outputSize, 'valid') 
    imOut = imOut((1+VkernelOffset*2):(size(imOut,1)-VkernelOffset*2), ... 
     (1+HkernelOffset*2):(size(imOut,2)-HkernelOffset*2), :); 
end 
end 

我又写了脚本执行一个740x976灰度图像并记录在以下两个命令集他们的处理时间:

for n = 1:25 
    dim(n) = 6*n + 1; 
    h=fspecial('gaussian',dim(n), 4); 
    tic; 
    Im = FilterImage(I,h,0,'full'); 
    tM(n) = toc; 

    h1 = fspecial('gaussian', [dim(n) 1], 4); 
    h2 = fspecial('gaussian', [1 dim(n)], 4); 
    tic; 
    It = FilterImage(I,h1,0,'full'); 
    Is = FilterImage(It,h2,0,'full'); 
    tS(n) = toc; 
end 

密谋需要我得到以下结果相应时间后:Output Plot

我的问题是,为什么可分离方法的速度慢到49x49大小的内核矩阵,并且只显示55x55以上的内核大小提高了速度,我的图像过滤器代码有问题?

p.s.图像滤镜代码是为3D图像设计的,以考虑颜色深度,但是对于速度测试,我使用的是使用im2double转换为灰度图像的灰度图像。

PS2从而下面提到,比较我进行了使用MATLAB的本地CONV2功能,并在那里为你所期望的结果,也是令人难以置信的速度相同的过程... same exact measure, this time using conv2 instead of FilterImage

感谢

+1

它是我的,因为Matlab的优化...或不。 – 2014-11-22 20:31:47

+1

您可以使用分析器更详细地检查代码的时间。查看“55x55”后出现的区别。 – 2014-11-22 20:37:43

+0

因此,剖析器显示,大多数时间饥饿的功能主要是重塑和总和。出于某种原因,在使用Profiler时,可分离的方法在内核尺寸大于67x67之后才变得更快:/ mind mind boggles ...感谢您的建议,尽管:) – 2014-11-22 22:17:18

回答

0

这似乎是一个优化错误。
我会使用函数conv2来代替。
让我们写一个示例代码:

mOutputImage = conv2((vFilterCoeff.' * vFilterCoeff), mInputImage); 
mOutputImageSep = conv2(vFilterCoeff, vFilterCoeff.', mInputImage); 

尝试那些在一个循环,vFilterCoeff(行向量!!!)的长度越来越大。

更新我们现在有什么结果。

+0

在发布之前,我尝试了类似于此的内容,实现完全相同时间脚本,但与conv2而不是我的FilterImage。结果如你所料。分离出来的滤波器在每一个点上的表现都优于方形滤波器,而且开始时有一个很小的差别,这使得我相信这个问题在我自己的FilterImage函数中是有的,这导致我在这里发布..我会发布conv2的时间比较结果。 – 2014-11-23 10:41:10