实际应用中,我们的图像常常会被噪声腐蚀,这些噪声可能是划痕,涂鸦等。或者图像的部分本身已经损毁。这就需要对图片进行还原。
结合另一篇内容:OpenCV–0016:图像ROI与ROI操作
图像的修复原理:
利用那些已经被破坏的区域的边缘,即边缘的颜色和结构,根据这些图像留下的信息去推断被破坏的信息区域的信息内容,然后对破坏区进行填补,以达到图像修补的目的。
OpenCV中的两种修复算法
1、inpaint函数
-
说明
使用区域邻域恢复图像中的选定区域。函数实现关键是图像掩码的确定,可以通过阈值筛选或者手工选定。
该功能从区域边界附近的像素重建选定的图像区域。该功能可用于去除扫描照片上的灰尘和划痕,或去除静止图像或视频中不需要的物体。
-
声明
void inpaint( InputArray src, InputArray inpaintMask, OutputArray dst, double inpaintRadius, int flags );
-
参数
src 输入8位或16位无符号或32位浮点型1通道或8位3通道图像。 inpaintMask 图像的掩码,单通道图像,大小跟原图像一致,inpaintMask图像上除了需要修复的部分之外其他部分的像素值全部为0; dst 输出的经过修复的图像; inpaintRadius 修复算法取的邻域半径,用于计算当前像素点的差值; flag 修复算法,有两种:INPAINT_NS 和I NPAINT_TELEA;
2、OpenCV中实现的两种图像修复算法
2.1、INPAINT_NS : 基于Navier-Stokes的修复方法
在下图中,我们的目标是填充暗区并获得一个看起来像右边的图像。
我们如何填充这个黑色的区域?
- 第一个约束:边缘进入点A应该连接边缘离开点B。
- 另一个约束:连接A和B的曲线右边的区域应该是白色,而左边的区域应该是蓝色的。
以上两个约束基本上要求:保留渐变(即边缘特征)和继续在平滑区域中传播颜色信息。
基于Bertalmio,Marcelo,Andrea L. Bertozzi和Guillermo Sapiro于2001年撰写的“Navier-Stokes,流体动力学和图像和视频修补”一文。该算法基于流体动力学并利用偏微分方程。基本原则是heurisitic。它首先沿着已知区域的边缘行进到未知区域(因为边缘是连续的)。它继续等照片(连接具有相同强度的点的线,就像轮廓连接具有相同高度的点一样),同时在修复区域的边界处匹配渐变矢量。为此,使用来自流体动力学的一些方法。获得颜色后,填充颜色以减少该区域的最小差异。使用标志cv2.INPAINT_NS启用此算法。
2. INPAINT_TELEA : 基于图像梯度的快速匹配方法(Telea法)
该方法实现使用不同的技术解决了相同的约束。作者不使用图像拉普拉斯算子作为平滑度的估计,而是使用像素的已知图像邻域上的加权平均值来补绘。已知的邻域像素和梯度用于估计要修复的像素的颜色。
基于Alexandru Telea于2004年发表的“基于快速行进方法的图像修复技术”。它基于快速行进方法。考虑图像中要修复的区域。算法从该区域的边界开始,然后进入区域内,逐渐填充边界中的所有内容。它需要在邻近的像素周围的一个小邻域进行修复。该像素由邻居中所有已知像素的归一化加权和代替。选择权重是一个重要的问题。对于靠近该点的那些像素,靠近边界的法线和位于边界轮廓上的像素,给予更多的权重。一旦像素被修复,它将使用快速行进方法移动到下一个最近的像素。 FMM确保首先修复已知像素附近的像素,这样它就像手动启发式操作一样工作。使用标志cv2.INPAINT_TELEA启用此算法。
3、应用
3.1 应用一
1.图像转化成灰度图像
2.图像通过阈值处理生成Mask
3.对Mask进行膨胀处理,增加Mask面积
4.图像修复
void inpaintTest(Mat& src) {
//1.图像转化成灰度图像
Mat gray;
cvtColor(src, gray