获得两个图像之间的高斯模糊的西格玛

时间:2016-02-25 07:49:48

标签: opencv computer-vision

假设我有一个图像A,我用Sigam=3对其应用了高斯模糊,所以我得到了另一个图像B。如果给出A,B,有没有办法知道应用的sigma?

进一步澄清:

图片A:

Orignal Image

图片B:

enter image description here

我想编写一个带A,B并返回Sigma的函数:

double get_sigma(cv::Mat const& A,cv::Mat const& B);

有什么建议吗?

1 个答案:

答案 0 :(得分:4)

EDIT1: 建议的方法在原始形式的实践中不起作用(即仅使用3 x 3内核的9个方程式),我意识到这个以后。请参阅下面的EDIT1以获取解释,有关可行的方法,请参阅EDIT2。

EDIT2: 根据Humam的建议,我使用最小二乘估计(LSE)来查找系数。

我认为你可以通过在这种情况下求解线性方程组来估计滤波器内核。线性滤波器通过其系数对窗口中的像素进行加权,然后获取它们的总和并将该值分配给结果图像中窗口的中心像素。因此,对于像

这样的3 x 3过滤器

kernel

滤波图像中的结果像素值

result_pix_value = h11 * a(y, x) + h12 * a(y, x+1) + h13 * a(y, x+2) +
                   h21 * a(y+1, x) + h22 * a(y+1, x+1) + h23 * a(y+1, x+2) +
                   h31 * a(y+2, x) + h32 * a(y+2, x+1) + h33 * a(y+2, x+2)

其中a's是原始图像中窗口内的像素值。在这里,对于3 x 3过滤器,您有9个未知数,因此您需要9个方程式。您可以在结果图像中使用9个像素获得这9个方程式。然后,您可以形成一个Ax = b系统并求解x以获得滤波器系数。有了可用的系数,我想你可以找到sigma。

在下面的示例中,我使用非重叠窗口来显示方程式。 wins

您不必知道过滤器的大小。如果使用更大的尺寸,则不相关的系数将接近于零。

您的结果图像大小与输入图像不同,因此我没有使用该图像进行以下计算。我使用你的输入图像并应用我自己的过滤器。

我在Octave测试了这个。如果你有Octave / Matlab,你可以快速运行它。对于Octave,您需要加载图像包。

我正在使用以下内核来模糊图像:

h =

   0.10963   0.11184   0.10963
   0.11184   0.11410   0.11184
   0.10963   0.11184   0.10963

当我使用窗口大小5估计它时,我得到以下内容。正如我所说,不相关的系数接近于零。

g =

  9.5787e-015  -3.1508e-014  1.2974e-015  -3.4897e-015  1.2739e-014
  -3.7248e-014  1.0963e-001  1.1184e-001  1.0963e-001  1.8418e-015
  4.1825e-014  1.1184e-001  1.1410e-001  1.1184e-001  -7.3554e-014
  -2.4861e-014  1.0963e-001  1.1184e-001  1.0963e-001  9.7664e-014
  1.3692e-014  4.6182e-016  -2.9215e-014  3.1305e-014  -4.4875e-014

<强> EDIT1: 首先,我道歉。

  • 这种方法在实践中并没有真正起作用。我在代码中使用了filt = conv2(a, h, 'same');。在这种情况下得到的图像数据类型是双倍的,而在实际图像中,数据类型通常是uint8,因此信息丢失,我们可以将其视为噪声。我使用次要修改filt = floor(conv2(a, h, 'same'));模拟了这个,然后我没有得到预期的结果。
  • 采样方法并不理想,因为它可能会导致系统退化。更好的方法是使用随机抽样,避免边界并确保b向量中的条目是唯一的。在理想的情况下,就像在我的代码中一样,我们确保系统Ax = b以这种方式具有唯一的解决方案。
  • 一种方法是将其重新表述为Mv = 0系统,并尝试在约束Mv下最小化squared-norm v = 1的平方范数,我们可以使用SVD来解决这个问题。我可能在这里错了,我没试过。
  • 另一种方法是使用高斯核的对称性。然后3x3内核将只有3个未知数而不是9个。我认为,这样我们就对上段的v施加了额外的约束。
  • 我会尝试这些并发布结果,即使我没有得到预期的结果。

EDIT2:

  • 使用LSE,我们可以找到滤波器系数pinv(A'A)A'b。为了完成,我添加了一个简单(和慢速)的LSE代码。

初始八度代码:

clear all

im = double(imread('I2vxD.png'));

k = 5;
r = floor(k/2);

a = im(:, :, 1);  % take the red channel
h = fspecial('gaussian', [3 3], 5); % filter with a 3x3 gaussian
filt = conv2(a, h, 'same');

% use non-overlapping windows to for the Ax = b syatem
% NOTE: boundry error checking isn't performed in the code below
s = floor(size(a)/2);
y = s(1);
x = s(2);

w = k*k;
y1 = s(1)-floor(w/2) + r;
y2 = s(1)+floor(w/2);
x1 = s(2)-floor(w/2) + r;
x2 = s(2)+floor(w/2);

b = [];
A = [];
for y = y1:k:y2
  for x = x1:k:x2
    b = [b; filt(y, x)];
    f = a(y-r:y+r, x-r:x+r);
    A = [A; f(:)'];
  end
end

% estimated filter kernel
g = reshape(A\b, k, k)

LSE方法:

clear all

im = double(imread('I2vxD.png'));

k = 5;
r = floor(k/2);

a = im(:, :, 1);  % take the red channel
h = fspecial('gaussian', [3 3], 5); % filter with a 3x3 gaussian
filt = floor(conv2(a, h, 'same'));

s = size(a);
y1 = r+2; y2 = s(1)-r-2;
x1 = r+2; x2 = s(2)-r-2;

b = [];
A = [];

for y = y1:2:y2
  for x = x1:2:x2
    b = [b; filt(y, x)];
    f = a(y-r:y+r, x-r:x+r);
    f = f(:)';
    A = [A; f];
  end
end

g = reshape(A\b, k, k) % A\b returns the least squares solution
%g = reshape(pinv(A'*A)*A'*b, k, k)