图像去水印——opencv实现

图像去水印——opencv实现


功能简介:通过拖动鼠标实现指定区域水印或是斑点的去除。
实现原理:利用opencv鼠标操作setMouseCallback函数框选(左上到右下)需要处理的区域,按下鼠标开始选中,松开鼠标结束,对选中区域进行像素替换(根据不同图像,可选不同方式),再对选中区域周围高斯滤波,平滑处理,再对整体图像双边滤波(人像可美颜,增强立体感),对图像做进一步平滑处理。

代码如下:

#include <opencv2/core/core.hpp>  
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <stdio.h>  
using namespace cv;
//读入图像
Mat org = imread("E:/壁纸/tx.jpg");
Mat  img, tmp;
Mat src = org;
Mat  dst = Mat(src.size(), src.type(), CV_8UC3);
static Point pre_pt;//初始坐标 (选中区域左上角) 
static Point cur_pt;//实时坐标 (选中区域右下角) 


void on_mouse(int event, int x, int y, int flags, void *ustc);
int main()
{

	org.copyTo(img);
	org.copyTo(tmp);
	namedWindow("img", CV_WINDOW_AUTOSIZE);//定义一个img窗口  
	setMouseCallback("img", on_mouse);//调用回调函数  

	waitKey(0);
	return 0;
}
void on_mouse(int event, int x, int y, int flags, void *ustc)//event鼠标事件代号,x,y鼠标坐标,flags拖拽和键盘操作的代号  
{

	char temp[16];//定义坐标显示字符数组
	if (event == CV_EVENT_LBUTTONDOWN)//左键按下,读取初始坐标
	{


		//获取选中区域矩形左上角坐标
		pre_pt = Point(x, y);
		imshow("img", img);
	}
	else if (event == CV_EVENT_MOUSEMOVE && !(flags & CV_EVENT_FLAG_LBUTTON))//左键没有按下的情况下,鼠标移动  
	{
		img.copyTo(tmp);//将img复制到临时图像tmp上,用于显示实时坐标  
		sprintf_s(temp, "(%d,%d)", x, y);//坐标
		cur_pt = Point(x, y);//获取实时坐标
		putText(tmp, temp, cur_pt, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0, 255));//实时显示鼠标移动的坐标  
		imshow("img", tmp);
	}
	else if (event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON))//左键按下时,鼠标移动,则在图像上划矩形  
	{

		imshow("img", img);
	}
	else if (event == CV_EVENT_LBUTTONUP)//左键松开,将在图像上划矩形  
	{

		//获取实时坐标(选中区域矩形右下角)
		cur_pt = Point(x, y);

		//对选中区域进行像素替换,偏移3个像素,根据实际情况调节
		for (int i = min(pre_pt.y, cur_pt.y); i < max(cur_pt.y, pre_pt.y); i++)
		{
			for (int j = min(pre_pt.x, cur_pt.x); j < max(cur_pt.x, pre_pt.x); j++)
			{
				src.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i, j -3)[0];
				src.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i, j -3)[1];
				src.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i, j-3)[2];

			}
		}

		//对选中区域周围进行平滑处理
		Mat imageroi = src(Range(pre_pt.y - 3, cur_pt.y + 3), Range(pre_pt.x - 3, cur_pt.x + 3));
		GaussianBlur(imageroi, imageroi, Size(15, 15), 0, 0);

		//对整体图像双边滤波(对人像有美颜效果)
		bilateralFilter(src, dst, 15, 30, 9);

		//保存处理后的图像(如有必要)
		imwrite("E:/壁纸/txa.jpg", dst);

		//标记选中区域
		circle(img, pre_pt, 2, Scalar(255, 0, 0, 0), CV_FILLED, CV_AA, 0);
		rectangle(img, pre_pt, cur_pt, Scalar(0, 255, 0, 0), 1, 8, 0);
		//显示结果
		namedWindow("结果", CV_WINDOW_AUTOSIZE);
		imshow("结果", dst);


	}

}

结果显示
在这里插入图片描述
效果还不错!
也可考虑在鼠标操作函数之前对图像平滑处理,效果因图像而异。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值