利用OpenCV实现图像修复(含源码链接)

图像修复技术应用在什么地方呢?

想想一下,我们有一张非常棒的相片,但是由于时间比较久远,没有电子版留底,而纸质版的又十分不便于保存。因此长采用扫描的方式获得电子版。但是非常不幸,扫描过程中落入了一根头发,或者是机器出现故障,对相片造成了影响,这个时候就可以通过图像修复技术解决这个问题。

强大的OpenCV库里集成了两种用与图像修复的方法

INPAINT_NS: 基于Navier-Stokes的图像修复

该方法在2001年提出,其神奇之处竟然是基于流体力学理论提出的方法。根据其作者提出,我们需要解决的问题可以抽象成在一个鞋子图片上有一个黑色的区域,通过填充黑色区域,使得最佳的恢复鞋子的样子。

对于如何填补这个黑色区域,可以抽象成存在一条曲线,使得由A到B将黑色区域分开,并且保证在曲线的一侧是蓝色,另一侧是白色。这个曲线应具有如下的约束:

  1. 保持边缘特征

  2. 在平滑区域中保持颜色信息

通过构建一个偏微分方程来更新具有上诉约束的区域内的图像强度,同时利用拉普拉斯算子估计图像平滑度信息,并沿着等照度传播。

由于这些方程与Navier-Stokes方程(流体力学中的方程,感兴趣的小伙伴可以自行百度)相关且类似,因此可以通过流体力学中的方法进行求解。

由于小白对流体力学不是很了解,具体就不详细解释了,感兴趣的小伙伴可以阅读该论文了解详情。

论文地址:http://www.math.ucla.edu/~bertozzi/papers/cvpr01.pdf

INPAINT_TELEA:基于快速行进方法的图像修复

该方法中没有使用拉普拉斯算子作为平滑度的估计,而是使用像素的已知图像邻域上的加权平均值来描述。同时利用邻域像素和梯度恢复填充区域像素的颜色。

当像素被修复之后,通过快速行进方法更新边界。

论文地址:

https://pdfs.semanticscholar.org/622d/5f432e515da69f8f220fb92b17c8426d0427.pdf

相关API介绍

C++:

void inpaint(
    Mat&src,
    Mat& inpaintMask,
    Mat& dst,
    double inpaintRadius,
    int flags)

Python:

dst =cv2.inpaint(
    src,
    inpaintMask,
    inpaintRadius,
    flags)

其中各参数的含义如下:

src =源图像

inpaintMask =二进制掩码,指示要修复的像素。

DST =目标图像

inpaintRadius =像素周围的邻域补绘。通常,如果要修复的区域很薄,使用较小的值会产生较少的模糊。

flags: INPAINT_NS(基于Navier-Stokes的方法)或INPAINT_TELEA(基于快速行进的方法)

示例

左边的第一个图像是输入图像,第二个图像是掩模,第三个图像是INPAINT_TELEA的结果,最终结果是INPAINT_NS

关于这个图片有一个小小的故事,1865年2月5日星期日,在华盛顿特区的加德纳画廊,亚历山大·加德纳拍摄了几张总统的多镜头照片。在本届会议结束之前,加德纳请求为总统拍摄最后一个姿势。他把相机拉得更近,拍了一张林肯头部、肩膀和胸部的照片。但是玻璃板在这个时候突然破裂,对拍摄图像产生影响。加德纳小心翼翼地将它带到了他的黑暗房间,制作一张相片,发现在林肯的脸上有一个不祥的裂缝。这张相片,即O-118,至今仍然存在。多年来,许多人认为这一裂缝是10周后林肯中弹的预言。

让我们看一个更复杂的例子,在图片上写上英文单词,之后通过opencv函数去修复该单词。

左:带有Scribbles的原始图像。中:使用快速行进方法修复,右:使用Navier-Stokes方法修复。

该程序的源码和使用的图片链接为:

https://github.com/spmallick/learnopencv/tree/master/Image-Inpainting

(0)

相关推荐