在OpenCV的“photo.hpp”中定义了一个inpaint函数,可以用来实现图像的修复和复原功能,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;

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


方法一、全区域阈值处理+Mask膨胀处理

#include <imgproc\imgproc.hpp>
#include <highgui\highgui.hpp>
#include <photo\photo.hpp> using namespace cv; //全区域阈值处理+Mask膨胀处理
int main()
{
Mat imageSource = imread("Test.jpg");
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)); //通过阈值处理生成Mask
threshold(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();
}

原始图像:

根据阈值处理得到的图像掩码:

图像复原结果:

由于是图像全区域做阈值处理获得的掩码,图像上部分区域也被当做掩码对待,导致部分图像受损。

方法二、鼠标框选区域+阈值处理+Mask膨胀处理

#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("Test.jpg");
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, imageGray, CV_RGB2GRAY); //转换为灰度图
Mat imageMask = Mat(ROI.size(), CV_8UC1, Scalar::all(0)); //通过阈值处理生成Mask
threshold(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);
}
}

鼠标圈定的ROI:

图像复原结果:

选定区域之外的图像不受修复影响,没有额外的损伤。


方法三、鼠标划定整个区域作为修复对象

这个方法选定一个矩形区域,把整个矩形区域作为要修复的对象,该方法适用于图像结构比较简单,特别是纯色图像,并且选定区域面积占比不大的情况,效果较好。

#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); //鼠标圈定区域
int main()
{
imageSource = imread("Test.jpg");
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 = Mat(imageSource.size(), CV_8UC1, Scalar::all(0));
Mat imageMask = imageSourceCopy(Rect(ptL, ptR));
//生成一个跟ROI大小一样的值全为1的区域
Mat imageMaskCopy = Mat(imageMask.size(), CV_8UC1, Scalar::all(1));
imageMaskCopy.copyTo(imageMask);
inpaint(imageSource, imageSourceCopy, imageSource, 9, INPAINT_TELEA); //图像修复
imshow("Mask", imageSourceCopy);
imshow("修复后", imageSource);
}
}

原始图像:

图像复原结果:

OpenCV图像修复的更多相关文章

  1. opencv 图像修复函数

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

  2. OpenCV探索之路(十):图像修复技术

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

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

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

  4. OpenCV图像金字塔:高斯金字塔、拉普拉斯金字塔与图片尺寸缩放

    这篇已经写得很好,真心给作者点个赞.题目都是直接转过来的,直接去看吧. Reference Link : http://blog.csdn.net/poem_qianmo/article/detail ...

  5. 【OpenCV新手教程之十三】OpenCV图像金字塔:高斯金字塔、拉普拉斯金字塔与图片尺寸缩放

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/26157633 作者:毛星云(浅墨) ...

  6. Opencv 图像叠加 添加水印

    Opencv 图像叠加 添加水印 C++: void Mat::copyTo(OutputArray m) const C++: void Mat::copyTo(OutputArray m, Inp ...

  7. opencv图像读取-imread

    前言 图像的读取和保存一定要注意imread函数的各个参数及其意义,尽量不要使用默认参数,否则就像数据格式出现错误(here)一样,很难查找错误原因的: re: 1.opencv图像的读取与保存; 完

  8. 学习 opencv---(12)OpenCV 图像金字塔:高斯金字塔,拉普拉斯金字塔与图片尺寸缩放

    在这篇文章里,我们一起学习下 图像金字塔 的一些基本概念,如何使用OpenCV函数pyrUp和pyrDown 对图像进行向上和向下采样,以及了解专门用于缩放图像尺寸的resize函数的用法.此博文一共 ...

  9. [OpenCV Qt教程] 在Qt图形界面中显示OpenCV图像的OpenGL Widget(第二部分)

    本文译自:http://www.robot-home.it/blog/en/software/tutorial-opencv-qt-opengl-widget-per-visualizzare-imm ...

随机推荐

  1. Apache与weblogic整合实战(独家研究)

    用apache来处理外界的请求,再把请求转发给wls,这样就行突破wls express版本号的5用户限制 详细配置例如以下 copy ${WLS_Server}/server/lib下的mod_wl ...

  2. vue学习笔记三:常见的表单绑定

    <template> <div id="app"> <input type="checkbox" id="checked ...

  3. Effective C++ 条款28

    避免返回handles指向对象内部成分 本节作者讲述的知识核心是对于一个类来说,应该避免类返回自己内部的私有数据. 例如以下: class Point{ public: Point(int x, in ...

  4. Android系统开发(1)——GCC编译器的编译和安装过程

    GCC编译器介绍 GCC编译器(GNG C Compiler)是GNU项目中符合ANSI C标准的编译系统,能够编译C  C++  Object C等语言编写的程序,同时GCC也是一个交叉编译器,特别 ...

  5. CSS文本阴影实例

    原文 简书原文:https://www.jianshu.com/p/5abf2fa2f1b9 前言 以下的实例是我从<CSS实战>中看到的实例,当我看到这些实例的时候,发现平时不是很在意的 ...

  6. python 设计模式之 单例模式

    单例模式是做为"全局变量"的替代品出现的.所以它具有全局变量的特点:全局可见.贯穿应用程序的整个生命期,保证在程序执行中,某个类仅仅存在一个实例,所以通常不希望类中的构造函数被调用 ...

  7. js进阶 11-1 jquery中的页面内容操作的三个方法

    jquery中的页面内容操作的三个方法 一.总结 一句话总结:记三个方法即可.text,html,val.因为这里是方法,所以设置值的是后面方法的参数. 1.jquery中的页面内容操作的三个方法? ...

  8. ios9 xcode7以后编译需要进行的几项设置

    http://blog.csdn.net/hero82748274/article/details/48629461 1.库后缀变了:.dylib->tbd libsqlite3.0.dylib ...

  9. iOS app审核参考信息地址

    发件人:(苹果开发支持邮箱地址) 中国区电话:400-670-1855 chinadev<chinadev@asia.apple.com>   您好: 感谢您与 Apple 开发者计划支持 ...

  10. OOA/OOD/OOP 转载

    OOA/OOD/OOP OOA Object-Oriented Analysis:面向对象分析方法 是在一个系统的开发过程中进行了系统业务调查以后,按照面向对象的思想来分析问题.OOA与结构化分析有较 ...