获取两幅图像之间的高斯模糊西格玛
Obtain sigma of gaussian blur between two images
假设我有一张图片 A
,我用 Sigam=3
在上面应用了高斯模糊,所以我得到了另一张图片 B
。如果给出 A,B,有没有办法知道应用的西格玛?
进一步说明:
图片A:
图片 B:
我想写一个接受 A,B
和 return 的函数 Sigma
:
double get_sigma(cv::Mat const& A,cv::Mat const& B);
有什么建议吗?
EDIT1: 建议的方法在实践中以其原始形式不起作用(即只使用 9 个方程 3 x 3
kernel),后来我才意识到这一点。请参阅下面的 EDIT1 以了解有效的方法的解释和 EDIT2。
EDIT2: 根据 Humam 的建议,我使用最小二乘估计 (LSE) 来查找系数。
在这种情况下,我认为您可以通过求解线性方程组来估计滤波器内核。线性滤波器通过其系数对 window 中的像素进行加权,然后求和并将该值分配给结果图像中 window 的中心像素。因此,对于像
这样的 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
是原始图像中 window 内的像素值。此处,对于 3 x 3
过滤器,您有 9 个未知数,因此您需要 9 个方程。您可以使用结果图像中的 9 个像素获得这 9 个方程。然后你可以组成一个Ax = b
系统并求解x以获得滤波器系数。有了可用的系数,我想你可以找到 sigma。
在下面的示例中,我使用如图所示的非重叠 windows 来获得方程。
您不必知道过滤器的大小。如果使用更大的尺寸,则不相关的系数将接近于零。
您的结果图像大小与输入图像不同,因此我没有使用该图像进行后续计算。我使用您的输入图像并应用我自己的滤镜。
我在 Octave 中对此进行了测试。如果你有Octave/Matlab,你可以很快运行它。 Octave需要加载镜像包
我正在使用以下内核来模糊图像:
h =
0.10963 0.11184 0.10963
0.11184 0.11410 0.11184
0.10963 0.11184 0.10963
当我使用 window 尺寸 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
编辑 1:
首先,我很抱歉。
- 这种方法在实践中并不奏效。我在代码中使用了
filt = conv2(a, h, 'same');
。在这种情况下生成的图像数据类型是 double,而在实际图像中数据类型通常是 uint8
,因此会丢失信息,我们可以将其视为噪声。我用较小的修改 filt = floor(conv2(a, h, 'same'));
模拟了这个,然后我没有得到预期的结果。
- 采样方法并不理想,因为它可能会导致系统退化。更好的方法是使用随机抽样,避免边界并确保 b 向量中的条目是唯一的。在理想情况下,就像在我的代码中一样,我们确保系统
Ax = b
以这种方式具有唯一的解决方案。
- 一种方法是将其重新表述为
Mv = 0
系统,并尝试在约束 squared-norm v = 1
下最小化 Mv
的平方范数,我们可以使用 SVD 求解。我在这里可能是错的,我还没有尝试过。
- 另一种方法是利用高斯核的对称性。然后
3x3
内核将只有 3 个未知数而不是 9 个。我认为,这样我们就对上一段的 v
施加了额外的约束。
- 我会尝试这些并 post 结果,即使我没有得到预期的结果。
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)
假设我有一张图片 A
,我用 Sigam=3
在上面应用了高斯模糊,所以我得到了另一张图片 B
。如果给出 A,B,有没有办法知道应用的西格玛?
进一步说明:
图片A:
图片 B:
我想写一个接受 A,B
和 return 的函数 Sigma
:
double get_sigma(cv::Mat const& A,cv::Mat const& B);
有什么建议吗?
EDIT1: 建议的方法在实践中以其原始形式不起作用(即只使用 9 个方程 3 x 3
kernel),后来我才意识到这一点。请参阅下面的 EDIT1 以了解有效的方法的解释和 EDIT2。
EDIT2: 根据 Humam 的建议,我使用最小二乘估计 (LSE) 来查找系数。
在这种情况下,我认为您可以通过求解线性方程组来估计滤波器内核。线性滤波器通过其系数对 window 中的像素进行加权,然后求和并将该值分配给结果图像中 window 的中心像素。因此,对于像
这样的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
是原始图像中 window 内的像素值。此处,对于 3 x 3
过滤器,您有 9 个未知数,因此您需要 9 个方程。您可以使用结果图像中的 9 个像素获得这 9 个方程。然后你可以组成一个Ax = b
系统并求解x以获得滤波器系数。有了可用的系数,我想你可以找到 sigma。
在下面的示例中,我使用如图所示的非重叠 windows 来获得方程。
您不必知道过滤器的大小。如果使用更大的尺寸,则不相关的系数将接近于零。
您的结果图像大小与输入图像不同,因此我没有使用该图像进行后续计算。我使用您的输入图像并应用我自己的滤镜。
我在 Octave 中对此进行了测试。如果你有Octave/Matlab,你可以很快运行它。 Octave需要加载镜像包
我正在使用以下内核来模糊图像:
h =
0.10963 0.11184 0.10963
0.11184 0.11410 0.11184
0.10963 0.11184 0.10963
当我使用 window 尺寸 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
编辑 1: 首先,我很抱歉。
- 这种方法在实践中并不奏效。我在代码中使用了
filt = conv2(a, h, 'same');
。在这种情况下生成的图像数据类型是 double,而在实际图像中数据类型通常是uint8
,因此会丢失信息,我们可以将其视为噪声。我用较小的修改filt = floor(conv2(a, h, 'same'));
模拟了这个,然后我没有得到预期的结果。 - 采样方法并不理想,因为它可能会导致系统退化。更好的方法是使用随机抽样,避免边界并确保 b 向量中的条目是唯一的。在理想情况下,就像在我的代码中一样,我们确保系统
Ax = b
以这种方式具有唯一的解决方案。 - 一种方法是将其重新表述为
Mv = 0
系统,并尝试在约束squared-norm v = 1
下最小化Mv
的平方范数,我们可以使用 SVD 求解。我在这里可能是错的,我还没有尝试过。 - 另一种方法是利用高斯核的对称性。然后
3x3
内核将只有 3 个未知数而不是 9 个。我认为,这样我们就对上一段的v
施加了额外的约束。 - 我会尝试这些并 post 结果,即使我没有得到预期的结果。
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)