OpenCV  4.10.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\) 是逐元素矩阵乘法(哈达玛积)。公式更新为

\[ 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 = image & mask1
* input2 = image & mask2
* input3 = image & 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:812
void copyTo(OutputArray m) const
将矩阵复制到另一个矩阵。
int main(int argc, char *argv[])
定义 highgui_qt.cpp:3
与磁盘上的文件关联的文件存储的“黑盒”表示。
定义 core.hpp:102
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)