本章将学习内容如下:
- 如何通过一种称为图像修复的方法去除旧照片中的细小噪点、划痕等瑕疵
- 了解OpenCV中的图像修复功能
基础知识
大多数人家里可能都有一些老旧褪色的照片,上面带有黑点或划痕等。 那么是否想过要修复它们?我们无法直接用绘图工具擦除这些瑕疵,因为这样只会用白色结构替换黑色结构,毫无意义。 这时就需要使用图像修复技术。 其基本原理很简单:用邻近像素替换这些瑕疵区域,使其与周围环境自然融合。 请看下图示例(引自维基百科):
OpenCV为此提供了两种算法,均通过cv2.inpaint()
函数调用。
第一种算法基于Alexandru Telea 2004年发表的论文《基于快速行进方法的图像修复技术》,采用快速行进法(FMM)。
算法从待修复区域的边界开始,逐步向内推进,优先填充边界区域。
对于每个待修复像素,算法会考察其周围小邻域内所有已知像素,通过归一化加权求和进行替换——权重分配至关重要:
靠近当前点、临近边界法线方向以及位于边界轮廓上的像素将获得更高权重。
采用快速行进法确保邻近已知像素的区域优先修复,其过程类似人工修复操作。
通过cv2.INPAINT_TELEA
标志启用该算法。
第二种算法基于Bertalmio、Bertozzi和Sapiro 2001年发表的《纳维-斯托克斯方程、流体力学与图像视频修复》论文,基于流体动力学原理并运用偏微分方程。
其核心启发式原理是:先沿着已知区域到未知区域的边缘推进(保持边缘连续性),通过延续等强度线(类似连接等高线的概念),同时在修复区域边界匹配梯度向量。
该过程运用流体动力学方法,最后通过色彩填充使该区域方差最小化。
使用cv2.INPAINT_NS
标志启用此算法。
代码实现
需要创建与输入图像尺寸相同的掩膜,其中非零像素对应待修复区域。其他操作都很简单。 示例图像被手动添加了黑色划痕作为退化效果,并使用绘图工具制作了对应的修复掩膜。
import numpy as np
import cv2
img = cv2.imread('/data/cvdata/messi_2.jpg')
# mask = cv2.imread('/data/cvdata/mask2.png',0)
mask = cv2.imread('/data/cvdata/mask2.png',0)
# dst = cv2.inpaint(img,mask,3,cv2.INPAINT_TELEA)
dst = cv2.inpaint(img,mask,3,cv2.INPAINT_TELEA)
# cv2.imshow('dst',dst)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
%matplotlib inline
import matplotlib.pyplot as plt
plt.imshow(img)
<matplotlib.image.AxesImage at 0x7f14867078c0>
plt.imshow(mask)
<matplotlib.image.AxesImage at 0x7f1486593200>
plt.imshow(dst)
<matplotlib.image.AxesImage at 0x7f1486488fb0>
如下图所示。 第一张图显示退化的输入图像,第二张图为对应的修复掩膜,第三张图是第一种算法的修复结果,最后一张图则是第二种算法的处理效果。
扩展阅读
- Bertalmio, Marcelo, Andrea L. Bertozzi 和 Guillermo Sapiro 合著的《纳维-斯托克斯方程、流体力学与图像视频修复》,收录于 2001 年 IEEE 计算机视觉与模式识别会议论文集第一卷 I-355 页。
- Telea, Alexandru 所著的《基于快速行进方法的图像修复技术》,发表于《图形工具期刊》2004 年第 9 卷第 1 期 23-34 页。
练习
- OpenCV 自带了一个图像修复的交互式示例
samples/python2/inpaint.py
,建议尝试运行。 - 数月前,我曾观看过关于 Adobe Photoshop 中"内容识别填充"(一种高级图像修复技术)的视频教程。经进一步搜索发现,GIMP 图像处理软件也内置了相同技术,命名为"Resynthesizer"(需单独安装插件)。相信您会喜欢这项技术。