OpenCV 提供了两种经典的图像修复算法,可以方便地去除照片中的水印、划痕、日期戳,或者移除不需要的物体。它的核心思想是利用图像中完好的区域,来填充被标记为“损坏”的区域。
OpenCV 的 inpaint 函数支持两种算法,通过 flags 参数选择:
| 算法 | 原理简介 | 特点 |
|---|---|---|
cv2.INPAINT_NS |
基于 Navier-Stokes 方程,将图像强度看作流体,沿着边缘等照度线方向扩散信息进入待修复区域。 | 适合平滑连续的边缘,保持结构。 |
cv2.INPAINT_TELEA |
基于 快速行进法 (FMM),从区域边界开始逐步向内填充,优先处理边界像素,利用邻近已知像素加权平均。 | 计算更快,对纹理较少的区域效果好。 |
dst = cv2.inpaint(src, mask, inpaintRadius, flags)
src:输入图像(8位单/三通道,修复时通常用彩色图)。
mask:修复掩膜,8位单通道,非零像素表示需要修复的区域(通常用 255 表示白)。
inpaintRadius:修复时考虑的邻域半径。值越大,参考范围越广,但也可能更模糊。
flags:cv2.INPAINT_TELEA 或 cv2.INPAINT_NS。
# 图片修复,要求把一张图片上的测字擦除,代码如下:
import cv2
import numpy as np
from opencv_jupyter_ui import cv2_imshow
img = cv2.imread('./images/inpaint.png')
mask = cv2.imread('./images/inpaint_mask.png', 0)
dst1 = cv2.inpaint(img, mask, 5, cv2.INPAINT_TELEA)
dst2 = cv2.inpaint(img, mask, 5, cv2.INPAINT_NS)
# cv2_imshow('dst', np.hstack((img,mask,dst)))
cv2_imshow('dst', np.hstack((img,dst1,dst2)))
# cv2.imshow('dst', np.hstack((img,mask,dst)))
# cv2.waitKey(0)
# cv2.destroyAllWindows()
图像展示如下:
掩膜质量决定效果:修复区域必须精准覆盖缺陷,且边界最好稍微多包含几个像素(用膨胀操作),否则会在边缘留下模糊痕迹。
半径选择:
细划痕:半径可以小一些(3~5)
大块缺失:半径需要稍大(5~10),但过大会导致明显模糊。
可尝试不同值,观察修复痕迹。
两种算法比较:如果边界清晰、纹理简单,TELEA 够用且快;若希望更好保持边缘连贯性(比如移除线条),NS 有时更自然。
大物体移除:传统 inpaint 对大面积纹理区域效果有限,可能会出现模糊块,此时需要更高级的基于深度学习的修复方法(如 LaMa、Stable Diffusion Inpainting)。

全部评论