OpenCV学习18_ 图像修复

在这里插入图片描述

一、图像修补

在实际应用中,我们的图像常常会被噪声腐蚀,这些噪声或者是镜头上的灰尘或水滴,或者是旧照片的划痕,或者由于图像的部分本身已经损坏。而“图像修复” (Inpainting),就是妙手回春,解决这些问题的良方。图像修复技术简单来说,就是利用那些已经被破坏区域的边缘,即边缘的颜色和结构,繁殖和混合到损坏的图像中,以达到图像修补的目的。

如果被破坏的区域不是太大,并且在被破坏区域边缘包含足够多的纹理和颜色,那么图像修补技术可以很好地恢复图像。当然,当图像损坏区域过大时,我们“妙手回春”的能力也是有限的。

1.1 实现图像修补: inpaint()函数

在新版OpenCV中,图像修补技术由inpaint函数实现,它可以用来从扫描的照片中清除灰尘和划痕,或者从静态图像或视频中去除不需要的物体。其原型声明如下。

C++: void inpaint (InputArray src, InputArray inpaintMask, OutputArray dst, double inpaintRadius, int flags)
  • 第一个参数, InputArray类型的src,输入图像,即源图像,填Mat类的对象即可,且需为8位单通道或者三通道图像。
  • 第二个参数, InputArray类型的inpaintMask,修复掩膜,为8位的单通道图像。其中的非零像素表示需要修补的区域。
  • 第三个参数, OutputArray类型的dst,函数调用后的运算结果存在这里,和源图片有一样的尺寸和类型。
  • 第四个参数, double类型的inpaintRadius,需要修补的每个点的圆形邻域,为修复算法的参考半径。
  • 第五个参数, int类型的flags,修补方法的标识符,可以是表所示两者之一。

在这里插入图片描述

1.2 示例程序

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/photo/photo.hpp"
#include <iostream>
using namespace cv;
using namespace std;

#define WINDOW_NAME0 "【原始图参考】"        //为窗口标题定义的宏 
#define WINDOW_NAME1 "【原始图】"        //为窗口标题定义的宏 
#define WINDOW_NAME2 "【修补后的效果图】"        //为窗口标题定义的宏 

Mat srcImage0, srcImage1, inpaintMask;
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(int argc, char** argv)
{
	//载入原始图并进行掩膜的初始化
	Mat srcImage = imread("F:\\CV\\LearnCV\\files\\Zelda.jpg", -1);
	if (!srcImage.data) { printf("读取图片错误,请确定目录下是否有imread函数指定图片存在~! \n"); return false; }
	srcImage0 = srcImage.clone();
	srcImage1 = srcImage.clone();
	inpaintMask = Mat::zeros(srcImage1.size(), CV_8U);

	//显示原始图参考
	imshow(WINDOW_NAME0, srcImage0);
	//显示原始图
	imshow(WINDOW_NAME1, srcImage1);
	//设置鼠标回调消息
	setMouseCallback(WINDOW_NAME1, On_Mouse, 0);

	//轮询按键,根据不同的按键进行处理
	while (1)
	{
		//获取按键键值
		char c = (char)waitKey();

		//键值为ESC,程序退出
		if (c == 27)
			break;

		//键值为2,恢复成原始图像
		if (c == '2')
		{
			inpaintMask = Scalar::all(0);
			srcImage.copyTo(srcImage1);
			imshow(WINDOW_NAME1, srcImage1);
		}

		//键值为1或者空格,进行图像修补操作
		if (c == '1' || c == ' ')
		{
			Mat inpaintedImage;
			inpaint(srcImage1, inpaintMask, inpaintedImage, 3, INPAINT_TELEA);
			imshow(WINDOW_NAME2, inpaintedImage);
		}
	}

	return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值