假设我有一个图像A
,我用Sigam=3
对其应用了高斯模糊,所以我得到了另一个图像B
。如果给出A,B,有没有办法知道应用的sigma?
进一步澄清:
图片A:
图片B:
我想编写一个带A,B
并返回Sigma
的函数:
double get_sigma(cv::Mat const& A,cv::Mat const& B);
有什么建议吗?
答案 0 :(得分:4)
EDIT1: 建议的方法在原始形式的实践中不起作用(即仅使用3 x 3
内核的9个方程式),我意识到这个以后。请参阅下面的EDIT1以获取解释,有关可行的方法,请参阅EDIT2。
EDIT2: 根据Humam的建议,我使用最小二乘估计(LSE)来查找系数。
我认为你可以通过在这种情况下求解线性方程组来估计滤波器内核。线性滤波器通过其系数对窗口中的像素进行加权,然后获取它们的总和并将该值分配给结果图像中窗口的中心像素。因此,对于像
这样的3 x 3
过滤器
滤波图像中的结果像素值
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。
您不必知道过滤器的大小。如果使用更大的尺寸,则不相关的系数将接近于零。
您的结果图像大小与输入图像不同,因此我没有使用该图像进行以下计算。我使用你的输入图像并应用我自己的过滤器。
我在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'));
模拟了这个,然后我没有得到预期的结果。Ax = b
以这种方式具有唯一的解决方案。Mv = 0
系统,并尝试在约束Mv
下最小化squared-norm v = 1
的平方范数,我们可以使用SVD来解决这个问题。我可能在这里错了,我没试过。3x3
内核将只有3个未知数而不是9个。我认为,这样我们就对上段的v
施加了额外的约束。EDIT2:
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)