OpenCV 4.12.0
开源计算机视觉
加载中...
搜索中...
无匹配项
使用 F 变换的图像修复

目标

在本教程中,您将学习如何使用 F 变换进行图像修复。它包含

  • 背后的基本理论,
  • 三种不同的算法。

简介

本教程的目标是展示逆 F 变换可以用于图像重建。图像重建是指重建损坏的图像,其中损坏包括原始图像中不包含的所有内容。它可以是噪声、文本、划痕等。建议借助近似技术解决重建问题。这意味着我们将寻找一个近似图像,该图像与给定图像接近,同时不包含我们认为是损坏的部分。此任务称为图像修复

模糊变换应用

正如我在之前的教程中展示的,F 变换是一种模糊数学工具,在图像处理中非常有用。让我重写公式,并使用之前引入的内核 \(g\)

\[ F^0_{kl}=\frac{\sum_{x=0}^{2h+1}\sum_{y=0}^{2h+1} \iota_{kl}(x,y) g(x,y)}{\sum_{x=0}^{2h+1}\sum_{y=0}^{2h+1} g(x,y)}, \]

其中 \(\iota_{kl} \subset I\) 以像素 \((k \cdot h,l \cdot h)\) 为中心,\(g\) 是内核。为了进行图像处理,使用二值掩码 \(S\) 如下

\[ g^s_{kl} = g \circ s_{kl} \]

其中 \(s_{k,l} \subset S\)。掩码 \(S\) 的子区域 \(s\) 对应于图像 \(I\) 的子区域 \(\iota\)。运算符 \(\circ\) 是逐元素矩阵乘法(Hadamard 积)。公式更新为

\[ F^0_{kl}=\frac{\sum_{x=0}^{2h+1}\sum_{y=0}^{2h+1} \iota_{kl}(x,y) g^s(x,y)}{\sum_{x=0}^{2h+1}\sum_{y=0}^{2h+1} g^s(x,y)}. \]

更多详细信息可以在相关论文中找到。

代码

/* 示例 - 图像修复
* 目标是使用 F 变换应用图像修复
* 在图像 "input.png" 上。图像已损坏
* 通过各种类型的损坏
*
* input1 = 图像 & mask1
* input2 = 图像 & mask2
* input3 = 图像 & mask3
*
* 三种算法 "ft::ONE_STEP", "ft::MULTI_STEP"
* 和 "ft::ITERATIVE" 在
* 适当的损坏类型上进行演示。
*
* ft::ONE_STEP
* "output1_inpaint.png": input1, mask1
*
* ft::MULTI_STEP
* "output2_inpaint.png": input2, mask2
* "output3_inpaint.png": input3, mask3
*
* ft::ITERATIVE
* "output4_inpaint.png": input3, mask3
*
* 半径为 2 的线性内核用于所有
* 示例。
*/
#include "opencv2/core.hpp"
using namespace std;
using namespace cv;
int main(void)
{
// 输入图像
Mat I = imread("input.png");
// 各种掩码
Mat mask1 = imread("mask1.png", IMREAD_GRAYSCALE);
Mat mask2 = imread("mask2.png", IMREAD_GRAYSCALE);
Mat mask3 = imread("mask3.png", IMREAD_GRAYSCALE);
// 应用损坏
Mat input1, input2, input3;
I.copyTo(input1, mask1);
I.copyTo(input2, mask2);
I.copyTo(input3, mask3);
// 使用各种算法进行修复
Mat output1, output2, output3, output4;
ft::inpaint(input1, mask1, output1, 2, ft::LINEAR, ft::ONE_STEP);
ft::inpaint(input2, mask2, output2, 2, ft::LINEAR, ft::MULTI_STEP);
ft::inpaint(input3, mask3, output3, 2, ft::LINEAR, ft::MULTI_STEP);
ft::inpaint(input3, mask3, output4, 2, ft::LINEAR, ft::ITERATIVE);
// 保存输出
imwrite("output1_inpaint.png", output1);
imwrite("output2_inpaint.png", output2);
imwrite("output3_inpaint.png", output3);
imwrite("output4_inpaint.png", output4);
// 保存损坏的输入以进行比较
imwrite("input1.png", input1);
imwrite("input2.png", input2);
imwrite("input3.png", input3);
return 0;
}
n 维密集数组类
定义 mat.hpp:830
void copyTo(OutputArray m) const
将矩阵复制到另一个矩阵。
int main(int argc, char *argv[])
定义 highgui_qt.cpp:3
定义 core.hpp:107
STL 命名空间。

说明

下面的示例演示了图像修复的用法。使用相同的输入和三种不同类型的损坏创建三个人工图像。在实际使用中,输入图像将已呈现,但在这里我们自己创建了它。

首先,我们必须加载我们的图像和用于人工损坏创建的三个掩码。

// 输入图像
Mat I = imread("input.png");
// 各种掩码
Mat mask1 = imread("mask1.png", IMREAD_GRAYSCALE);
Mat mask2 = imread("mask2.png", IMREAD_GRAYSCALE);
Mat mask3 = imread("mask3.png", IMREAD_GRAYSCALE);

请注意,掩码必须加载为 IMREAD_GRAYSCALE

在下一步中,掩码用于损坏我们的输入图像。

// 应用损坏
Mat input1, input2, input3;
I.copyTo(input1, mask1);
I.copyTo(input2, mask2);
I.copyTo(input3, mask3);

使用掩码,我们在相同的输入图像上应用了三种不同类型的损坏。这是结果。

input1、input2 和 input3

不要忘记,在实际使用中,图像 input1input2input3 是自然创建的,并直接用作输入。

接下来是输出图像的声明。在以下几行中,应用了图像修复的方法。让我逐一解释三种不同的算法。

第一个是 ONE_STEP

ft::inpaint(input1, mask1, output1, 2, ft::LINEAR, ft::ONE_STEP);

ONE_STEP 算法简单地计算直接 F 变换,使用半径为 2 的内核(如方法调用中指定)忽略损坏的部分。逆 F 变换使用来自附近组件的值填充缺失区域。由您决定选择足够大的半径。

第二个是 MULTI_STEP

ft::inpaint(input2, mask2, output2, 2, ft::LINEAR, ft::MULTI_STEP);
ft::inpaint(input3, mask3, output3, 2, ft::LINEAR, ft::MULTI_STEP);

MULTI_STEP 算法的工作方式相同,但如果发现半径不足,则会自动增加定义的半径(在本例中为 2)。如果您想填充孔,但不确定需要多大的半径,您可以选择 MULTI_STEP,让计算机来决定。将找到可能的最小值。

最后一个是 ITERATIVE

ft::inpaint(input3, mask3, output4, 2, ft::LINEAR, ft::ITERATIVE);

在大多数情况下,最佳选择是 ITERATIVE。这种处理方式对小类型的损坏使用基本函数的小半径,对较大的孔使用较大的半径。

output1 (ONE_STEP)、output2 (MULTI_STEP)、output3 (MULTI_STEP)、output4 (ITERATIVE)