【问题标题】:Approximating Gaussian Blur Using Extended Box Blur使用扩展框模糊逼近高斯模糊
【发布时间】:2014-06-22 18:48:28
【问题描述】:

问题如下,如何使用 Box Blur / Extended Box Blur 逼近具有给定 STD 的高斯模糊滤波器。

更具体地说,我知道这是 Photoshop 应用其高斯模糊的方式。

首先,一篇关于“Extended Box Blur 的文章可以看这里-Theoretical Foundations of Gaussian Convolution by Extended Box Filtering

我遇到的问题是文章中的图 2。
解释这一点的最佳方法是使用示例。

假设我们需要逼近 STD 为 15.4 -> Var = 237.16 的高斯模糊。
为了获得良好的近似值,我们将使用 6 次 Box Blur 迭代来做到这一点。

现在,我如何选择 Box Blur 的长度(我们将以可分离的方式进行,即在 1D 中工作)?
我应该选择不同的长度吗(看来我必须)?
目标与 GB 的模糊级别相匹配(即其 STD / VAR)。

谢谢。

附言
我正在使用 MATLAB,所以代码很简单 :-)。

【问题讨论】:

  • 这些实际上是多个问题。如果您可以在问题中包含一个(几乎)有效的代码示例,这可能会有很大帮助。
  • @DennisJaheruddin,我想我解决了固定长度框模糊问题。稍后我会分享 MATLAB 代码。

标签: matlab optimization image-processing photoshop mathematical-optimization


【解决方案1】:

这是我这篇文章的 MATLAB 实现:

```

function [ vBoxBlurKernel ] = GenerateBoxBlurKernel( boxBlurVar, numIterations )
% ----------------------------------------------------------------------------------------------- %
% [ boxBlurKernel ] = GenerateBoxBlurKernel( boxBlurVar, numIterations )
%   Approximates 1D Gaussian Kernel by iterative convolutions of "Extended Box Filter".
% Input:
%   - boxBlurVar        -   BoxFilter Varaiance.
%                           The variance of the output Box Filter.
%                           Scalar, Floating Point (0, inf).
%   - numIterations     -   Number of Iterations.
%                           The number of convolution iterations in order
%                           to produce the output Box Filter.
%                           Scalar, Floating Point [1, inf), Integer.
% Output:
%   - vBoxBlurKernel    -   Output Box Filter.
%                           The Box Filter with 'boxBlurVar' Variance.
%                           Vector, Floating Point, (0, 1).
% Remarks:
%   1.  The output Box Filter has a variance of '' as if it is treated as
%       Discrete Probability Function.
%   2.  References: "Theoretical Foundations of Gaussian Convolution by Extended Box Filtering"
%   3.  Prefixes:
%       -   'm' - Matrix.
%       -   'v' - Vector.
% TODO:
%   1.  F
%   Release Notes:
%   -   1.0.001     07/05/2014  xxxx xxxxxx
%       *   Accurate calculation of the "Extended Box Filter" length as in
%           the reference.
%   -   1.0.000     06/05/2014  xxxx xxxxxx
%       *   First release version.
% ----------------------------------------------------------------------------------------------- %

boxBlurLength = sqrt(((12 * boxBlurVar) / numIterations) + 1);
boxBlurRadius = (boxBlurLength - 1) / 2;

% 'boxBlurRadiusInt' -> 'l' in the reference
boxBlurRadiusInt    = floor(boxBlurRadius);
% boxBlurRadiusFrac   = boxBlurRadius - boxBlurRadiusInt;

% The length of the "Integer" part of the filter.
% 'boxBlurLengthInt' -> 'L' in the reference
boxBlurLengthInt = 2 * boxBlurRadiusInt + 1;

a1 = ((2 * boxBlurRadiusInt) + 1);
a2 = (boxBlurRadiusInt * (boxBlurRadiusInt + 1)) - ((3 * boxBlurVar) / numIterations);
a3 = (6 * ((boxBlurVar / numIterations) - ((boxBlurRadiusInt + 1) ^ 2)));

alpha = a1 * (a2 / a3);
ww = alpha / ((2 * boxBlurRadiusInt) + 1 + (2 * alpha));

% The length of the "Extended Box Filter".
% 'boxBlurLength' -> '\Gamma' in the reference.
boxBlurLength = (2 * (alpha + boxBlurRadiusInt)) + 1;

% The "Single Box Filter" with Varaince - boxBlurVar / numIterations
% It is normalized by definition.
vSingleBoxBlurKernel = [ww, (ones(1, boxBlurLengthInt) / boxBlurLength), ww];
% vBoxBlurKernel = vBoxBlurKernel / sum(vBoxBlurKernel);

vBoxBlurKernel = vSingleBoxBlurKernel;

% singleBoxKernelVar = sum(([-(boxBlurRadiusInt + 1):(boxBlurRadiusInt + 1)] .^ 2) .* boxBlurKernel)
% boxKernelVar = numIterations * singleBoxKernelVar


for iIter = 2:numIterations
    vBoxBlurKernel = conv2(vBoxBlurKernel, vSingleBoxBlurKernel, 'full');
end


end

这里有一个演示来试试:

% Box Blur Demo

gaussianKernelStd = 9.6;
gaussianKernelVar = gaussianKernelStd * gaussianKernelStd;
gaussianKernelRadius = ceil(6 * gaussianKernelStd);
gaussianKernel = exp(-([-gaussianKernelRadius:gaussianKernelRadius] .^ 2) / (2 * gaussianKernelVar));
gaussianKernel = gaussianKernel / sum(gaussianKernel);

boxBlurKernel = GenerateBoxBlurKernel(gaussianKernelVar, 6);
boxBlurKernelRadius = (length(boxBlurKernel) - 1) / 2;

figure();
plot([-gaussianKernelRadius:gaussianKernelRadius], gaussianKernel, [-boxBlurKernelRadius:boxBlurKernelRadius], boxBlurKernel);

sum(([-boxBlurKernelRadius:boxBlurKernelRadius] .^ 2) .* boxBlurKernel)
sum(([-gaussianKernelRadius:gaussianKernelRadius] .^ 2) .* gaussianKernel)

棘手的部分是“扩展盒过滤器”的有效长度的计算。
这不是使用常规“Box Filter”的方差计算长度的长度。

文章很棒,这个方法也很棒。

【讨论】:

  • 如何用二维高斯核实现。例如,我有一个生成二维高斯的代码: Ksigma=fspecial('gaussian',round(2*sigma)*2 + 1,sigma); % 核心。你能用 boxfilter 来近似我的 Ksigma 内核吗?谢谢
  • 高斯滤波器是可分离的。使用该属性通过 2 个 1D 高斯滤波器实现它。
  • 只需在行和列上应用一维高斯。
  • I=zeros(512,512);我(256,256)=1;对于 i=1:512 I_row=I(:,i);I_row_f=GenerateBoxBlurKernel(I_row, 6 ); I_col=I(i,:); GenerateBoxBlurKernel(I_col, 6 );结束 I_2D=sqrt(I_row.^2+I_col.^2);对吗?
猜你喜欢
  • 2015-11-05
  • 1970-01-01
  • 1970-01-01
  • 2018-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-30
  • 2011-12-07
相关资源
最近更新 更多