在实际应用中,我们的图像常常会被噪声腐蚀,这些噪声或是镜头上的灰尘或水滴,或是旧照片的划痕,或者是图像遭到人为的涂画(比如马赛克)或者图像的部分本身已经损坏。如果我们想让这些受到破坏的额图片尽可能恢复到原样,Opencv能帮我们做到吗?

OpenCV真的有这个妙手回春的功能!别以为图像修补的工作只能用PS或者美图秀秀那些软件去做,其实由程序员自己写代码去做更加高效!

图像修复技术的原理是什么呢?

简而言之,就是利用那些已经被破坏的区域的边缘, 即边缘的颜色和结构,根据这些图像留下的信息去推断被破坏的信息区的信息内容,然后对破坏区进行填补 ,以达到图像修补的目的。

OpenCV中就是利用inpaint()这个函数来实现修复功能的。

void inpaint( InputArray src, InputArray inpaintMask,OutputArray dst, double inpaintRadius, int flags );
  • 第一个参数src,输入的单通道或三通道图像;

  • 第二个参数inpaintMask,图像的掩码,单通道图像,大小跟原图像一致,inpaintMask图像上除了需要修复的部分之外其他部分的像素值全部为0;

  • 第三个参数dst,输出的经过修复的图像;

  • 第四个参数inpaintRadius,修复算法取的邻域半径,用于计算当前像素点的差值;

  • 第五个参数flags,修复算法,有两种:INPAINT_NS 和I NPAINT_TELEA;

函数实现关键是图像掩码的确定,可以通过阈值筛选或者手工选定,按照这个思路,用三种方法生成掩码,对比图像修复的效果。

#include <imgproc\imgproc.hpp>
#include <highgui\highgui.hpp>
#include <photo\photo.hpp>using namespace cv;//全区域阈值处理+Mask膨胀处理
int main()
{Mat imageSource = imread("lol17.png");if (!imageSource.data){return -1;}imshow("原图", imageSource);Mat imageGray;//转换为灰度图cvtColor(imageSource, imageGray, CV_RGB2GRAY, 0);Mat imageMask = Mat(imageSource.size(), CV_8UC1, Scalar::all(0));//通过阈值处理生成Maskthreshold(imageGray, imageMask, 240, 255, CV_THRESH_BINARY);Mat Kernel = getStructuringElement(MORPH_RECT, Size(3, 3));//对Mask膨胀处理,增加Mask面积dilate(imageMask, imageMask, Kernel);//图像修复inpaint(imageSource, imageMask, imageSource, 5, INPAINT_TELEA);imshow("Mask", imageMask);imshow("修复后", imageSource);waitKey();
}

下面就是修复效果,感觉很不错吧!不过仔细一看,感觉跟原图还是发生了一些差异,比如图中剑圣头上的那颗亮点,颜色发生了变化。这个就是修复后的副作用!毕竟作出了修复,付点代价还是要的。受损是由于是图像全区域做阈值处理获得的掩码,图像上部分区域也被当做掩码对待,导致部分图像受损。

有些图片可能就会修复得很好,比如以下这幅,你根本看不出哪里有明显的副作用。

是不是所有受损的图片都能较好地还原呢?那当然不是,有些图片受损太严重的,或者在某些复杂区域受损的,OpenCV也很难帮你修复过来。

比如以下这幅,因为受损有些区域在一些很复杂的位置,所以修复起来效果不怎么样。

上面提到其他无辜的而区域会受损,这个问题能解决一下吗?可以的,那就得自己定义一块需要修复的而区域,不需要修复的区域我们不动它就是了。

#include <imgproc/imgproc.hpp>
#include <highgui/highgui.hpp>
#include <core/core.hpp>
#include <photo/photo.hpp>using namespace cv;Point ptL, ptR; //鼠标画出矩形框的起点和终点
Mat imageSource, imageSourceCopy;
Mat ROI; //原图需要修复区域的ROI//鼠标回调函数
void OnMouse(int event, int x, int y, int flag, void *ustg);//鼠标圈定区域阈值处理+Mask膨胀处理
int main()
{imageSource = imread("lol17.png");if (!imageSource.data){return -1;}imshow("原图", imageSource);setMouseCallback("原图", OnMouse);waitKey();
}
void OnMouse(int event, int x, int y, int flag, void *ustg)
{if (event == CV_EVENT_LBUTTONDOWN){ptL = Point(x, y);ptR = Point(x, y);}if (flag == CV_EVENT_FLAG_LBUTTON){ptR = Point(x, y);imageSourceCopy = imageSource.clone();rectangle(imageSourceCopy, ptL, ptR, Scalar(255, 0, 0));imshow("原图", imageSourceCopy);}if (event == CV_EVENT_LBUTTONUP){if (ptL != ptR){ROI = imageSource(Rect(ptL, ptR));imshow("ROI", ROI);waitKey();}}//单击鼠标右键开始图像修复if (event == CV_EVENT_RBUTTONDOWN){imageSourceCopy = ROI.clone();Mat imageGray;cvtColor(ROI, Gray, CV_RGB2GRAY); //转换为灰度图Mat imageMask = Mat(ROI.size(), CV_8UC1, Scalar::all(0));//通过阈值处理生成Maskthreshold(imageGray, imageMask, 235, 255, CV_THRESH_BINARY);Mat Kernel = getStructuringElement(MORPH_RECT, Size(3, 3));dilate(imageMask, imageMask, Kernel);  //对Mask膨胀处理inpaint(ROI, imageMask, ROI, 9, INPAINT_TELEA);  //图像修复imshow("Mask", imageMask);imshow("修复后", imageSource);}
}

这种方法就需要我们人为地画出要修复的区域,这样就不会影响区域之外的图像了。

首先按住鼠标左键将待修复区域框出来。

然后对框出来的区域点击鼠标右键,就可以进行修复了。

修复的而效果确实比上面的方法要好!

总而言之,图像修复技术在一些简单,颜色单调的图像上进行修复得到的而效果是相当好的,而在一些细节或者复杂的部分进行修复,得到的复原图像的效果就比较一般了。比如在一些背景部分进行修复效果都不错,而在边缘细节上的修复就能看出问题了!

OpenCV精进之路(九):图像轮廓和图像分割修复——图像修复技术相关推荐

  1. OpenCV精进之路(二十):工具——图像标注小工具

    搞图像深度学习的童鞋一定碰过图像数据标注的东西,当我们训练网络时需要训练集数据,但在网上又没有找到自己想要的数据集,这时候就考虑自己制作自己的数据集了,这时就需要对图像进行标注.图像标注是件很枯燥又很 ...

  2. OpenCV精进之路(十六):图像分解和融合技术——图像拼接和图像融合技术

    图像拼接在实际的应用场景很广,比如无人机航拍,遥感图像等等,图像拼接是进一步做图像理解基础步骤,拼接效果的好坏直接影响接下来的工作,所以一个好的图像拼接算法非常重要. 再举一个身边的例子吧,你用你的手 ...

  3. 《OpenCV3编程入门》学习笔记8 图像轮廓与图像分割修复(一)查找并绘制轮廓

    第8章 图像轮廓与图像分割修复 8.1 查找并绘制轮廓 8.1.1 寻找轮廓:findContours()函数 1.作用:在二值图像中寻找轮廓 2.函数原型: void findcontours(In ...

  4. 图像轮廓、凸包、图像的矩、分水岭算法、图像修补

    文章目录 1.查找并绘制轮廓 1.1 寻找轮廓:findContours() 函数 1.2 绘制轮廓:drawContours() 函数 1.3 示例程序:轮廓查找 1.4 综合示例:查找并绘制轮廓 ...

  5. OpenCV精进之路(十四):图像矫正技术深入探讨

    刚进入实验室导师就交给我一个任务,就是让我设计算法给图像进行矫正.哎呀,我不太会图像这块啊,不过还是接下来了,硬着头皮开干吧! 那什么是图像的矫正呢?举个例子就好明白了. 我的好朋友小明给我拍了这几张 ...

  6. OpenCV精进之路(一):图像处理知识点串烧

    opencv图像初始化操作 #include<opencv2\opencv.hpp> #include<opencv2\highgui\highgui.hpp>using na ...

  7. opencv笔记二十九(轮廓发现)findContours(t2, contour, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));

    API: cv::findContours( //发现轮廓 InputOutputArray  binImg, // 输入图像,非0的像素被看成1,0的像素值保持不变,8-bit OutputArra ...

  8. Python机器视觉--OpenCV进阶(核心)--图像轮廓查找识别,绘制图像轮廓与图像轮廓的面积周长计算

    1.图像轮廓查找识别与绘制图像轮廓 1.1 什么是图像轮廓 图像轮廓是具有相同颜色或灰度的连续点的曲线. 轮廓在形状分析和物体的检测和识别中很有用. 轮廓的作用: 用于图形分析 物体的识别和检测 注意 ...

  9. 《OpenCV3编程入门》学习笔记8 图像轮廓与图像分割修复(四)图像的矩

    8.4 图像的矩 从一幅数字图形中计算出来的矩集,通常描述了该图像形状的全局特征,并提供了大量关于该图像不同类型的几何特性信息,如大小.位置.方向.形状等 (1)一阶矩与形状有关 (2)二阶矩显示曲线 ...

最新文章

  1. iMeta | 宏基因组生物信息期刊-创刊背景和简介
  2. html语言技术基础,第2章Web编程基础HTML语言技术方案.ppt
  3. Android之线程池深度剖析
  4. bash中时间、日期操作
  5. 【HDU - 6231】K-th Number(二分,思维)
  6. 改变定时器获取传感器频度_广东梅州梅县压力传感器*校对
  7. php自动加载基类文件
  8. 对docker隔离性的理解
  9. SystemVerilog中package(包)的基本使用
  10. 案例实操-Top10热门品类
  11. 一文详解三维重建中的立体匹配
  12. java删除文件夹及下面的所有文件
  13. 百词斩平板Android,百词斩ipad电脑版
  14. angular8.x + ngx-translate实现国际化
  15. 辉芒微IO单片机FT60F112
  16. 键盘移动小div(js原生)
  17. hihocoder #1272 : 买零食
  18. Vue+Element 实现订单列表【管理端】02
  19. 『XXG探索』canvas 获取图片主体颜色
  20. 程序员绝不要做“IT民工”

热门文章

  1. python tkinter界面 控件位置随窗体自动调整适应_如何实现python tkinter控件随窗口变化?...
  2. python如何快速登记凭证_如何高效地翻凭证?
  3. rabbitmq python 发送失败_python rabbitmq no_ack=false
  4. java经典源码 阅读_公开!阿里甩出“源码阅读指南”,原来源码才是最经典的学习范例...
  5. java笔试面试题---基础部分4
  6. OpenCV学习(14) 细化算法(2)
  7. linux的O的字体让我满意那些
  8. Android开发指南(41) —— Searchable Configuration
  9. 《Effective Python》笔记
  10. java collection 常用类_分析Collection常用的实现类