一、话说图像修复
在实际应用中,我们的图像常常会被噪声腐蚀,这些噪声或是镜头上的灰尘或水滴,或是旧照片的划痕,或者是图像遭到人为的涂画(比如马赛克)或者图像的部分本身已经损坏。如果我们想让这些受到破坏的额图片尽可能恢复到原样,Opencv能帮我们做到吗?
OpenCV真的有这个妙手回春的功能!别以为图像修补的工作只能用PS或者美图秀秀那些软件去做,其实由程序员自己写代码去做更加高效!
图像修复技术的原理是什么呢?
简而言之,就是利用那些已经被破坏的区域的边缘, 即边缘的颜色和结构,根据这些图像留下的信息去推断被破坏的信息区的信息内容,然后对破坏区进行填补 ,以达到图像修补的目的。
OpenCV中实现的图像修复算法有两种。
基于Navier-Stokes的修复方法
基于图像梯度的快速匹配方法又称(Telea法)
对应的两个枚举类型分别如下:
CV_INPAINT_NS
CV_INPAINT_TELEA
二、API
void inpaint( InputArray src, InputArray inpaintMask, OutputArray dst, double inpaintRadius, int flags );
第一个参数src,输入的单通道或三通道图像;
第二个参数inpaintMask,图像的掩码,单通道图像,大小跟原图像一致,inpaintMask图像上除了需要修复的部分之外其他部分的像素值全部为0;
第三个参数dst,输出的经过修复的图像;
第四个参数inpaintRadius,修复算法取的邻域半径,用于计算当前像素点的差值;
第五个参数flags,修复算法,有两种:INPAINT_NS 和I NPAINT_TELEA;
函数实现关键是图像掩码的确定,可以通过阈值筛选或者手工选定。
三、实验
废话不多说,直接上代码
int main()
{
Mat src, dst,mask,temp;
src = imread("D:\\cv_study\\Exercise\\inpaint\\g.jpg");
temp = src.clone();
rectangle(temp, Rect(500, 500, 100, 100), Scalar(0, 0, 255), 3, 8);
inRange(temp, Scalar(0, 0, 250), Scalar(0, 0, 255), mask);
inpaint(temp, mask, dst,3, CV_INPAINT_TELEA);
waitKey();
return 0;
}
现在原图上画一个矩形,然后找到需要修复位置的掩膜,进而进行图像修复。可以看到,对于简单的图像损坏,修复的还是挺不错的。上面的图是网上随便下载的,可以看到左下角有图库网的logo,那么怎么将这个logo去掉呢?
int main()
{
Mat src, dst,mask,temp;
src = imread("D:\\cv_study\\Exercise\\inpaint\\g.jpg");
inRange(src, Scalar(235, 235, 235), Scalar(255, 255, 255), mask);
Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
morphologyEx(mask, mask, MORPH_DILATE,element, Point(-1, -1), 3);
inpaint(src, mask, dst, 5, CV_INPAINT_NS);
waitKey();
return 0;
}
上面提取mask的方式和第一个有点不同,原因是logo周边的区域,所以这里对mask做形态学处理,使周边的区域也包含进来,从结果中看到,最终效果还不错。今天讲的比较简单,但是希望大家和我一样都有所收获