Opencv之实现图像修复intpaint()函数

来源:互联网 发布:笔记本软件限制策略 编辑:程序博客网 时间:2024/05/22 23:35

无意中看到inpaint()这个函数,它具有图像修复功能,这个应该很有趣,故查找了相关资料,整理好并呈现在这里。

一、inpaint()函数介绍

void inpaint( const Mat& src, const Mat& inpaintMask,                           Mat& dst, double inpaintRange, int flags );第一个参数InputArray类型的src,为8位单通道或者三通道图像的输入图像(要修复的图像);第二个参数inpaintMask为修复掩膜,为8位单通道图像,其中非零像素表示要修补的区域;第三个参数为dst,该函数的输出结果就放在这里,它和src图像类型是一样的;第四个参数是double类型的inpaintRadius,需要修复点的附近的圆形区域,该值为修复区域的半径;最后一个参数是int型的flags,为修补方法的标识符,两种修饰方法见下表:

标识符说明INPAINT_NS基于Navier-Stokes方法INPAINT_TEELEAA了先倒入Telea方法

CV_INPAINT_NS - 基于Navier-Stokes的方法。

比较难懂,贴个链接:

http://wenku.baidu.com/link?url=aut0V0I8ngmDiQOl6uvjZqAukhfAYeiF38C2-EMS8NScb5VKB3ZMBTpicbO7hU_22yP7zcH2Lz9PDVQrzOYWIthrLWBqYNRAvHCuSZqD6qa


CV_INPAINT_TELEA - Alexandru Telea[Telea04]的方法。

Telea在2004年提出的基于快速行进的修复算法(后面简称FMM算法)。

论文题目:An Image Inpainting Technique Based on the Fast Marching Method (2004)

作者主页:http://www.cs.rug.nl/~alext/

论文下载: http://www.cs.rug.nl/~alext/PAPERS/index.html (编号36的那篇)

在opencv中实现修复有两种算法,这里介绍Telea的算法,即基于快速行进(FMM)的修复算法。

一、先说一下如何修复一个像素点的。

参考上图,Ω区域是待修复的区域;δΩ指Ω的边界);要修复Ω中的像素,就需要计算出新的像素值来代替原值。

现在假设p点是我们要修复的像素。以p为中心选取一个小邻域B(ε),该邻域中的点像素值都是已知的(只要已知的)。(这个ε就是opencv函数中参数 inpaintRadius)

显然,我们需要的是用邻域Bε(p)中的所有点计算p点的新灰度值。显然,各个像素点所起的作用应该是不同的,也就引入了权值函数来决定哪些像素的值对新像素值影响更大,哪些比较小。采用下面的公式(公式2):

 

这里的w(p, q)就是权值函数,是用来限定邻域中各像素的贡献大小的。

 w(p, q) = dir(p, q) · dst(p, q) · lev(p, q)

 

其中,d0和 T0分别为距离参数和水平集参数,一般都取为 1。方向因子 dir(p,q)保证了越靠近法线方向 N =  ?T的像素点对 p 点的贡献最大;几何距离因子 dst(p,q)保证了离 p 点越近的像素点对p 点贡献越大;水平集距离因子lev(p,q)保证了离经过点 p 的待修复区域的轮廓线越近的已知像素点对点 p 的贡献越大。


二、测试小程序

到底哪种方法更好呢?既然两种方法都收集到opencv库函数里,我认为它们难分仲伯。


#include <opencv2/opencv.hpp>#include <iostream>using namespace cv;using namespace std;#define WINDOW_NAME1 "原始图"        #define WINDOW_NAME2 "修补方法:_TELEA"       #define WINDOW_NAME3 "修补方法:_NS"  Mat srcImage, srcImage1, inpaintMask;Point previousPoint;//原来的点坐标static void On_Mouse(int event, int x, int y, int flags, void*){if (event == EVENT_LBUTTONDOWN)previousPoint = Point(x, y);else if (event == EVENT_MOUSEMOVE && (flags & EVENT_FLAG_LBUTTON)){Point pt(x, y);line(inpaintMask, previousPoint, pt, Scalar::all(255), 5, 8, 0);//单通道掩膜,需要修复的像素此时为白色line(srcImage, previousPoint, pt, Scalar::all(255), 5, 8, 0);previousPoint = pt;imshow(WINDOW_NAME1, srcImage);}}int main(){srcImage = imread("D:\\vvoo\\baboon.jpg", 1);//三通道彩色图像if (!srcImage.data){cout << "读取图片错误,请确定目录下是否有imread函数指定图片存在~!" << endl;return false;}inpaintMask = Mat::zeros(srcImage.size(), CV_8UC1);imshow(WINDOW_NAME1, srcImage);//设置鼠标回调消息setMouseCallback(WINDOW_NAME1, On_Mouse, 0);while (1){int key = waitKey(10);switch (key){case 'a':{Mat inpaintedImage;inpaint(srcImage, inpaintMask, inpaintedImage, 3, INPAINT_TELEA);imshow(WINDOW_NAME2, inpaintedImage);}break;case 'b':{Mat inpaintedImage;inpaint(srcImage, inpaintMask, inpaintedImage, 3, INPAINT_NS);imshow(WINDOW_NAME3, inpaintedImage);}break;}if (key == 27)break;}waitKey(0);return 0;}






结果:没看出来哪个好,可能选的图片不适合



三、资料参考

1.http://blog.csdn.net/sunboyiris/article/details/23554351?utm_source=tuicool&utm_medium=referral

2.Opencv编程入门  作者:浅墨


0 0
原创粉丝点击