概述
图像修复(Image Inpainting)是计算机视觉中的重要研究方向,其目标是:
在已知图像部分区域缺失或受损的情况下,利用周围有效信息,对缺失区域进行合理补全,使修复结果在视觉上自然、连贯。
在实际工程中,图像修复常用于:
- 老照片修复
- 去除水印、划痕、污点
- 视频目标移除
- 医学图像修补
图像修复问题建模
1. 输入要素
图像修复通常需要以下两个输入:
- 原始图像(Source Image)
- 掩膜图像(Mask Image)
其中:
- 掩膜中 非零区域 表示需要被修复的区域
- 掩膜中 零值区域 表示保持不变
2. 修复目标
理想的图像修复应满足:
- 结构连续(边缘、轮廓自然延伸)
- 纹理一致(颜色、亮度平滑过渡)
- 无明显人工痕迹
3. 本质问题
图像修复本质是一个信息推断问题:
根据已知像素,推断未知像素的合理取值
OpenCV 图像修复算法
Navier-Stokes(NS)图像修复算法
1. 算法原理
NS 算法基于流体力学中的 Navier-Stokes 方程,其核心思想是:
将图像的灰度变化视为流体流动,使边缘信息沿着等亮度线方向传播到待修复区域。
主要特点:
- 强调结构信息传递
- 适合修复细长裂痕、划痕
2. 修复过程
- 计算图像梯度
- 沿等亮度线传播边缘信息
- 逐步填充缺失区域
3. 优缺点分析
优点
- 边缘连续性好
- 适合线性结构修复
缺点
- 纹理恢复能力有限
- 计算复杂度相对较高
- 对大面积缺失效果一般
4. OpenCV 使用示例
python
cv2.inpaint(src, mask, dst, 3, cv2.INPAINT_NS)
5. 完整示例
python
import cv2
import numpy as np
def main():
# 1. 读取原始图像
img = cv2.imread("input.jpg")
if img is None:
print("Error: Cannot read image")
return
# 2. 生成修复掩膜(示例:黑白划痕)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 使用 Canny 边缘检测模拟划痕 mask(示例)
edges = cv2.Canny(gray, 100, 200)
# 二值化作为修复掩膜
_, mask = cv2.threshold(
edges, 1, 255, cv2.THRESH_BINARY
)
# 扩展 mask,使划痕更连续
kernel = cv2.getStructuringElement(
cv2.MORPH_RECT, (3, 3)
)
mask = cv2.dilate(mask, kernel, iterations=1)
# 3. Navier-Stokes 图像修复
inpaint_radius = 3
dst = cv2.inpaint(
img,
mask,
inpaint_radius,
cv2.INPAINT_NS
)
# 4. 显示结果
cv2.imshow("Original", img)
cv2.imshow("Mask", mask)
cv2.imshow("Inpaint Result (Navier-Stokes)", dst)
cv2.imwrite("result_ns.jpg", dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == "__main__":
main()
Telea 快速修复算法
1. 算法原理
Telea 算法是一种基于 Fast Marching Method(快速行进法) 的图像修复方法。
核心思想:
从修复区域边界向内部逐步推进,根据已知像素加权估计未知像素。
权重因素包括:
- 距离
- 方向
- 梯度
2. 算法特点
- 局部修复
- 速度快
- 对纹理和颜色平滑区域效果好
3. 优缺点分析
优点
- 速度快,适合实时应用
- 实现简单
- 对小区域修复效果自然
缺点
- 对复杂结构(大面积遮挡)能力有限
- 可能产生模糊现象
4. OpenCV 使用示例
python
cv2.inpaint(src, mask, dst, 3, cv2.INPAINT_TELEA)
5. 完整示例
python
import cv2
import numpy as np
def main():
# 1. 读取原始图像
img = cv2.imread("input.jpg")
if img is None:
print("Error: Cannot read image")
return
# 2. 生成修复掩膜
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 阈值分割得到 mask
_, mask = cv2.threshold(
gray, 240, 255, cv2.THRESH_BINARY
)
# 适当膨胀 mask,覆盖完整修复区域
kernel = cv2.getStructuringElement(
cv2.MORPH_RECT, (3, 3)
)
mask = cv2.dilate(mask, kernel, iterations=2)
# 3. Telea 图像修复
inpaint_radius = 3
dst = cv2.inpaint(
img,
mask,
inpaint_radius,
cv2.INPAINT_TELEA
)
# 4. 显示结果
cv2.imshow("Original", img)
cv2.imshow("Mask", mask)
cv2.imshow("Inpaint Result (Telea)", dst)
cv2.imwrite("result_telea.jpg", dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == "__main__":
main()
总结
OpenCV 图像修复算法虽然属于传统方法,但在以下场景中仍具优势:
- 实时性要求高
- 硬件资源受限
- 修复区域较小
- 工程稳定性优先
Telea 算法 适合大多数通用场景。
Navier-Stokes 算法更适合结构修复。
在实际工程中,图像修复往往不是孤立模块,而是与:
- 前景检测
- 图像分割
- 视频处理
等模块结合,构成完整的视觉处理链路。