说明:图像修复可以解决类似噪声或者是镜头上的灰尘或水滴或者旧照片上面的划痕等。
1、实现图像修补:inpaint()函数
说明:图像修补技术由inpaint()函数实现,可以用来从扫描的照片中清除灰尘和划痕,或者从静态图像或视频去除不需要的物体
void inpaint(InputArray src,InputArray inpaintMask,OutputArray dst,double inpaintRadius,int flags)
- 第一个参数:输入图像,即原图像
- 第二个参数:修复掩膜,为8位的单通道图像。其中的非零像素表示需要修补的区域
- 第三个参数:函数调用后的运算结果存在这里,和源图像有一样的尺寸和类型
- 第四个参数:需要修补的每个点的圆形邻域,为修复算法的参考半径
- 第五个参数:int类型的flags,修补方法标识符
2、opencv之鼠标响应函数
1)setMouseCallback()函数
void setMouseCallback( const string& winname, //图像视窗名称 MouseCallback onMouse, //鼠标响应函数,监视到鼠标操作后调用并处理相应动作 void* userdata = 0 //鼠标响应处理函数的ID,识别号 );
2)OnMouseAction()响应函数
void OnMouseAction(int event,int x,int y,int flags,void *user_data) { // 自定义 }
3)参数 - Event
#define CV_EVENT_MOUSEMOVE 0 //滑动 #define CV_EVENT_LBUTTONDOWN 1 //左键点击 #define CV_EVENT_RBUTTONDOWN 2 //右键点击 #define CV_EVENT_MBUTTONDOWN 3 //中键点击 #define CV_EVENT_LBUTTONUP 4 //左键放开 #define CV_EVENT_RBUTTONUP 5 //右键放开 #define CV_EVENT_MBUTTONUP 6 //中键放开 #define CV_EVENT_LBUTTONDBLCLK 7 //左键双击 #define CV_EVENT_RBUTTONDBLCLK 8 //右键双击 #define CV_EVENT_MBUTTONDBLCLK 9 //中键双击
4)参数 - flags
#define CV_EVENT_FLAG_LBUTTON 1 //左鍵拖曳 #define CV_EVENT_FLAG_RBUTTON 2 //右鍵拖曳 #define CV_EVENT_FLAG_MBUTTON 4 //中鍵拖曳 #define CV_EVENT_FLAG_CTRLKEY 8 //(8~15)按Ctrl不放事件 #define CV_EVENT_FLAG_SHIFTKEY 16 //(16~31)按Shift不放事件 #define CV_EVENT_FLAG_ALTKEY 32 //(32~39)按Alt不放事件
3、示例程序
#include<opencv2/opencv.hpp> #include<opencv2/imgproc/imgproc.hpp> #include<opencv2/highgui/highgui.hpp> #include<iostream> using namespace std; using namespace cv; #define WINDOW_NAME1 "【原始图】" #define WINDOW_NAME2 "【修复图】" Mat srcImage1, inpaintMask; static void ShowHelpText(); Point previousPoint(-1, -1); //响应鼠标的回调函数 static void On_Mouse(int event, int x, int y, int flags, void *) { //鼠标左键弹起消息 if (event == EVENT_LBUTTONUP || !(flags & EVENT_FLAG_LBUTTON)) previousPoint = Point(-1, -1); //鼠标左键按下 else if (event == EVENT_LBUTTONDOWN) previousPoint = Point(x, y); //鼠标移动进行绘制 else if (event == EVENT_MOUSEMOVE && (flags & EVENT_FLAG_LBUTTON)) { Point pt(x,y); if (previousPoint.x < 0) previousPoint = pt; //绘制白色线条 line(inpaintMask, previousPoint, pt, Scalar::all(255), 5, 8, 0); line(srcImage1, previousPoint, pt, Scalar::all(255), 5, 8, 0); previousPoint = pt; imshow(WINDOW_NAME1, srcImage1); } } int main() { system("color 2F"); ShowHelpText(); Mat srcImage = imread("E:\\Pec\\蜘蛛侠.jpg", -1); srcImage1 = srcImage.clone(); inpaintMask = Mat::zeros(srcImage1.size(), CV_8U); imshow(WINDOW_NAME1, srcImage); //设置鼠标回调消息 setMouseCallback(WINDOW_NAME1, On_Mouse, 0); while (1) { int c = waitKey(); if ((char)c == 27) break; //按键2按下时,恢复源图 if (c == '2') { inpaintMask = Scalar::all(0); srcImage.copyTo(srcImage1); imshow(WINDOW_NAME1, srcImage1); } //若检测到按键为1或者空格,则进行处理 if ((char)c == '1' || (char)c == ' ') { Mat inpaintedImage; inpaint(srcImage1, inpaintMask, inpaintedImage, 3, INPAINT_TELEA); imshow(WINDOW_NAME2, inpaintedImage); } } return 0; } static void ShowHelpText() { cout << "\n\t欢迎来到【图像修复】示例程序" << endl; cout << endl; cout << "\t\t在对图像操作之前,在【原始图】窗口进行适量绘制" << endl; cout << "\t\t按键操作如下:" << endl; cout << "\t\t\t按下按键【鼠标左键】-- 在图像绘制白条" << endl; cout << "\t\t\t按下按键【ESC】--退出程序" << endl; cout << "\t\t\t按下按键【1】 或者 【空格】-- 图像修复" << endl; }
左边是右边破环之后修复的图,可以观察到,左边修复那块有稍微的模糊,破坏程度不是很大。
不过如果我们大肆破坏,超过修复的限度,就会导致图像修复出现困难