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

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

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

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

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

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

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

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

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

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

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

  1. #include <imgproc\imgproc.hpp>
  2. #include <highgui\highgui.hpp>
  3. #include <photo\photo.hpp>
  4. using namespace cv;
  5. //全区域阈值处理+Mask膨胀处理
  6. int main()
  7. {
  8. Mat imageSource = imread("lol17.png");
  9. if (!imageSource.data)
  10. {
  11. return -1;
  12. }
  13. imshow("原图", imageSource);
  14. Mat imageGray;
  15. //转换为灰度图
  16. cvtColor(imageSource, imageGray, CV_RGB2GRAY, 0);
  17. Mat imageMask = Mat(imageSource.size(), CV_8UC1, Scalar::all(0));
  18. //通过阈值处理生成Mask
  19. threshold(imageGray, imageMask, 240, 255, CV_THRESH_BINARY);
  20. Mat Kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
  21. //对Mask膨胀处理,增加Mask面积
  22. dilate(imageMask, imageMask, Kernel);
  23. //图像修复
  24. inpaint(imageSource, imageMask, imageSource, 5, INPAINT_TELEA);
  25. imshow("Mask", imageMask);
  26. imshow("修复后", imageSource);
  27. waitKey();
  28. }

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

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

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

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

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

  1. #include <imgproc/imgproc.hpp>
  2. #include <highgui/highgui.hpp>
  3. #include <core/core.hpp>
  4. #include <photo/photo.hpp>
  5. using namespace cv;
  6. Point ptL, ptR; //鼠标画出矩形框的起点和终点
  7. Mat imageSource, imageSourceCopy;
  8. Mat ROI; //原图需要修复区域的ROI
  9. //鼠标回调函数
  10. void OnMouse(int event, int x, int y, int flag, void *ustg);
  11. //鼠标圈定区域阈值处理+Mask膨胀处理
  12. int main()
  13. {
  14. imageSource = imread("lol17.png");
  15. if (!imageSource.data)
  16. {
  17. return -1;
  18. }
  19. imshow("原图", imageSource);
  20. setMouseCallback("原图", OnMouse);
  21. waitKey();
  22. }
  23. void OnMouse(int event, int x, int y, int flag, void *ustg)
  24. {
  25. if (event == CV_EVENT_LBUTTONDOWN)
  26. {
  27. ptL = Point(x, y);
  28. ptR = Point(x, y);
  29. }
  30. if (flag == CV_EVENT_FLAG_LBUTTON)
  31. {
  32. ptR = Point(x, y);
  33. imageSourceCopy = imageSource.clone();
  34. rectangle(imageSourceCopy, ptL, ptR, Scalar(255, 0, 0));
  35. imshow("原图", imageSourceCopy);
  36. }
  37. if (event == CV_EVENT_LBUTTONUP)
  38. {
  39. if (ptL != ptR)
  40. {
  41. ROI = imageSource(Rect(ptL, ptR));
  42. imshow("ROI", ROI);
  43. waitKey();
  44. }
  45. }
  46. //单击鼠标右键开始图像修复
  47. if (event == CV_EVENT_RBUTTONDOWN)
  48. {
  49. imageSourceCopy = ROI.clone();
  50. Mat imageGray;
  51. cvtColor(ROI, Gray, CV_RGB2GRAY); //转换为灰度图
  52. Mat imageMask = Mat(ROI.size(), CV_8UC1, Scalar::all(0));
  53. //通过阈值处理生成Mask
  54. threshold(imageGray, imageMask, 235, 255, CV_THRESH_BINARY);
  55. Mat Kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
  56. dilate(imageMask, imageMask, Kernel); //对Mask膨胀处理
  57. inpaint(ROI, imageMask, ROI, 9, INPAINT_TELEA); //图像修复
  58. imshow("Mask", imageMask);
  59. imshow("修复后", imageSource);
  60. }
  61. }

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

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

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

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

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

OpenCV探索之路(十):图像修复技术的更多相关文章

  1. 结构感知图像修复:ICCV2019论文解析

    结构感知图像修复:ICCV2019论文解析 StructureFlow: Image Inpainting via Structure-aware Appearance Flow 论文链接: http ...

  2. OpenCV探索之路(二十四)图像拼接和图像融合技术

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

  3. opencv 图像修复函数

    void cv::inpaint( const Mat& src, const Mat& mask, Mat& dst, double inpaintRange, int fl ...

  4. OpenCV学习2-----使用inpaint函数进行图像修复

    安装opencv时,在opencv的安装路径下, sources\samples\cpp\  路径里面提供了好多经典的例子,很值得学习. 这次的例子是利用inpaint函数进行图像修复. CV_EXP ...

  5. OpenCV探索之路(二十七):皮肤检测技术

    好久没写博客了,因为最近都忙着赶项目和打比赛==| 好吧,今天我打算写一篇关于使用opencv做皮肤检测的技术总结.那首先列一些现在主流的皮肤检测的方法都有哪些: RGB color space Yc ...

  6. OpenCV图像修复

    在OpenCV的"photo.hpp"中定义了一个inpaint函数,可以用来实现图像的修复和复原功能,inpaint函数的原型如下: void inpaint( InputArr ...

  7. Android热修复技术原理详解(最新最全版本)

    本文框架 什么是热修复? 热修复框架分类 技术原理及特点 Tinker框架解析 各框架对比图 总结   通过阅读本文,你会对热修复技术有更深的认知,本文会列出各类框架的优缺点以及技术原理,文章末尾简单 ...

  8. android Qzone的App热补丁热修复技术

    转自:https://mp.weixin.qq.com/s?__biz=MzI1MTA1MzM2Nw==&mid=400118620&idx=1&sn=b4fdd5055731 ...

  9. PorterDuffXfermode 图像混合技术在漫画APP中的应用

    此文已由作者游葳授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 写在开头 随着应用开发的深入,视觉同学在完成了页面的基本设计后,再也按耐不住心中的寂寞,开始对各种细节不满意, ...

随机推荐

  1. Struts2的类型转换(下)

    Struts2提供的类型转换: Struts2提供的是一个名叫StrutsTypeConverter的抽象类,这个类实际上是DefaultTypeConverter的子类.当我们继承自该抽象类 时,要 ...

  2. 使用$.post和action或servlet交互 URL出现 http://localhost:8080/../[object%20Object] 错误的问题解决

    使用$.post时,如下所示: $.post({ url : "./test/ajaxTest", }); 控制台报:There is no Action mapped for n ...

  3. python+robot framework实现测报告定制化和邮件发送

    前面已经介绍了python+robot framework自动化框架和基本原理的实现,详情请看 python+robot framework接口自动化测试 本章主要讲解报告已经产生那如何以自动化的方式 ...

  4. JavaScript运算符优先级

    图片引用自:http://www.cnblogs.com/xxcanghai/p/5189353.html

  5. Java线程池(ThreadPool)详解

    线程五个状态(生命周期): 线程运行时间 假设一个服务器完成一项任务所需时间为:T1 创建线程时间,T2 在线程中执行任务的时间,T3 销毁线程时间.    如果:T1 + T3 远大于 T2,则可以 ...

  6. linux入门之用户管理

    用户管理 添加用户 以root用户执行 adduser  或 useradd [new_account] -u  UID   -d 指定家目录 -g GID 指定一个基本组ID   -G指定一个附加组 ...

  7. NOIP2001T4car的旅行计划

    洛谷传送门 一看数据就是floyed(毕竟年代久远),然而建图不是那么好贱好建,只知道三个机场,需要判断斜边来求第4个机场坐标. 往后一些麻烦的建图. 最后floyed就好. --代码 #includ ...

  8. ZOJ 3195 Design the city 题解

    这个题目大意是: 有N个城市,编号为0~N-1,给定N-1条无向带权边,Q个询问,每个询问求三个城市连起来的最小权值. 多组数据 每组数据  1 < N < 50000  1 < Q ...

  9. 串口屏Modbus协议,串口屏的modbus协议资料,串口屏modbus通讯协议开发,串口屏之modbus协议使用技巧

    串口屏Modbus协议,串口屏的modbus协议资料,串口屏modbus通讯协议开发,串口屏之modbus协议使用技巧 本例程中用51单片机作为Modbus从机,从机的设备地址为2,从机有4个寄存器, ...

  10. 想询问一个职业规划的问题,前端开发 or nodejs?

    先说说个人情况,目前个人定位于初中级前端吧,工作近两年,目前前端开发和nodejs都有一定的了解,水平感觉可以搭一些小型的网站.作为前端开发,目前掌握的技术是javascript,平时更多的是用jqu ...