使用OpenCV实现马赛克效果

一、马赛克效果

马赛克的实现原理是把图像上某个像素点一定范围邻域内的所有点用邻域内随机选取的一个像素点的颜色代替,这样可以模糊细节,但是可以保留大体的轮廓。
效果图如下在这里插入图片描述

代码如下:

typedef struct UserData
{
	Point  startPt=Point(-1,-1);
	Mat* m1;
	Mat* m2;
}UserData;

void COpenCVDmeo::mosaic()
{
	Mat  image;
	image = imread(m_imagePath);
	showWindow("原图", image);
	UserData  data;
	data.m1=ℑ
	Mat  m2 = image.clone();
	data.m2 = &m2;
	namedWindow("马赛克", WINDOW_NORMAL);

	setMouseCallback("马赛克",&COpenCVDmeo::mosaicCallBack,(void *)(&data));
	imshow("马赛克", image);
	waitKey(0);
}

void COpenCVDmeo::mosaicCallBack(int event, int x, int y, int flags, void* userdata)
{
	UserData* data = static_cast<UserData*>(userdata);
	data->m1->copyTo(*data->m2);
	
	if (event == EVENT_LBUTTONDOWN) {
		data->startPt.x = x;
		data->startPt.y = y;
	}
	else  if(event == EVENT_MOUSEMOVE)
	{
	
		if (data->startPt.x<0||data->startPt.y<0)
				return;
		int dx = x - data->startPt.x;
		int dy = y - data->startPt.y;
		//rectangle(*data->m2, Rect(data->startPt, Point(x, y)), Scalar(255, 0, 0), 2);
		Mat mat = (*data->m2)(Rect(data->startPt, Point(x, y)));
		
	//	cout << "框选区域:"<<"rows:"<<mat.rows<<"cols:"<<mat.cols << "\n" << mat << endl;
		int len = 15;
			for (int j = 0; j + len <= mat.rows; j += len)
		{
				for (int i = 0; i + len <= mat.cols; i += len)
			{
				//cout << "通道数:" << mat.channels()<<endl;
				Mat m1 = mat(Rect(Point(i, j), Point(i + len, j + len)));
			//	cout << "原图:(i ,j): (" << i << "," << j << ")\n" << m1 << endl;
				for (int k = 0; k < len; k++)
				{
					for (int l = 0; l < len; l++)
					{
						m1.at<Vec3b>(k, l)[0] = m1.at<Vec3b>(0, 0)[0];
						m1.at<Vec3b>(k, l)[1] = m1.at<Vec3b>(0, 0)[1];
						m1.at<Vec3b>(k, l)[2] = m1.at<Vec3b>(0, 0)[2];
					}
				}
			//	cout << "转换后图:(i ,j): (" <<i<<"," << j << ")\n" << m1 << endl;
			}
		}
		imshow("马赛克", *data->m2);
	}
	else  if (event == EVENT_LBUTTONUP)
	{
		if (data->startPt.x < 0 || data->startPt.y < 0)
			return;
		int dx = x - data->startPt.x;
		int dy = y - data->startPt.y;
		//rectangle(*data->m2, Rect(data->startPt, Point(x, y)), Scalar(255, 0, 0), 2);
		Mat mat = (*data->m2)(Rect(data->startPt, Point(x, y)));
		//cout << "框选区域:\n" << mat << endl;

		int len = 15;
		for (int j = 0; j + len <= mat.rows; j += len)
		{
			for (int i = 0; i + len <= mat.cols; i += len)
			{
				//cout << "通道数:" << mat.channels() << endl;
				Mat m1 = mat(Rect(Point(i, j), Point(i + len, j + len)));
				//	cout << "原图:(i ,j): (" << i << "," << j << ")\n" << m1 << endl;
				for (int k = 0; k < len; k++)
				{
					for (int l = 0; l < len; l++)
					{
						m1.at<Vec3b>(k, l)[0] = m1.at<Vec3b>(0, 0)[0];
						m1.at<Vec3b>(k, l)[1] = m1.at<Vec3b>(0, 0)[1];
						m1.at<Vec3b>(k, l)[2] = m1.at<Vec3b>(0, 0)[2];
					}
				}
				//	cout << "转换后图:(i ,j): (" <<i<<"," << j << ")\n" << m1 << endl;
			}
		}
		imshow("马赛克", *data->m2);
		data->startPt.x = -1;
		data->startPt.y = -1;
		data->m2->copyTo(*data->m1);
	//	waitKey(0);
	}
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值