opencv入门四

发布于:2022-12-30 ⋅ 阅读:(457) ⋅ 点赞:(0)

鼠标操作与响应

static void on_draw(int event, int x, int y, int flags,  void* userobj)
{
	Mat image = *(Mat*)userobj;
	if (event == EVENT_LBUTTONDOWN) {
		//鼠标点击时	
		sp.x = x;
		sp.y = y;
		std::cout << "start:"  << sp << std::endl;
	}
	if (event == EVENT_LBUTTONUP) {
		//鼠标抬起后
		ap.x = x;
		ap.y = y;
		
		int dx = ap.x - sp.x;
		int dy = ap.y - sp.y;
		if (dx > 0 && dy > 0) {
			Rect box(sp.x, sp.y, dx, dy);
			//绘制矩形
			rectangle(image, box, Scalar(0,0,255), 1, 8, 0);
			imshow("绘制后", image);
		}

		std::cout << "end:"  << sp << std::endl;
	}
	
}

void QuickDemo::mouse_drawing_demo(Mat& image)
{
	namedWindow("绘制前", WINDOW_AUTOSIZE);
	imshow("绘制前", image);
	//设置回调机制
	setMouseCallback("绘制前",on_draw, (void*)(&image));
}

在这里插入图片描述

一个屏幕上只绘制一张图像,当鼠标移动的时候自动清空屏幕


Point sp(-1, -1);
Point ap(-1, -1);
Mat tmp;

static void on_draw(int event, int x, int y,int flags, void* userobj)
{
	Mat image = *(Mat*)userobj;
	if (event == EVENT_LBUTTONDOWN) {
		sp.x = x;
		sp.y = y;
		std::cout << "start: " << sp << std::endl;
	}
	//鼠标松开时确定结尾位置,并绘制矩形
	else if (event == EVENT_LBUTTONUP) {
		ap.x = x;
		ap.y = y;
		int dx = ap.x - sp.x;
		int dy = ap.y - sp.y;

		if (sp.x > 0 && sp.y > 0) {
			Rect box(sp.x, sp.y, dx, dy);
			rectangle(image, box, Scalar(0, 0, 255), 2, 8, 0);
			imshow("绘制前", image);

			//绘制完清空
			sp.x = -1;
			sp.y = -1;
		}
		std::cout << "end: " << ap << std::endl;
	}

	//当鼠标移动的时候会清空屏幕
	else if (event == EVENT_MOUSEMOVE) {
		tmp.copyTo(image);	//清除屏幕
	}
}

void QuickDemo::mouse_drawing_demo(Mat& image)
{
	namedWindow("绘制前", WINDOW_AUTOSIZE);
	imshow("绘制前", image);
	//设置回调机制
	setMouseCallback("绘制前",on_draw,(void *)(&image));
	tmp = image.clone();
}

在这里插入图片描述

提取图像框选中部分

Point sp(-1, -1);
Point ap(-1, -1);
Mat tmp;

static void on_draw(int event, int x, int y,int flags, void* userobj)
{
	Mat image = *(Mat*)userobj;
	if (event == EVENT_LBUTTONDOWN) {
		sp.x = x;
		sp.y = y;
		std::cout << "start: " << sp << std::endl;
	}
	//鼠标松开时确定结尾位置,并绘制矩形
	else if (event == EVENT_LBUTTONUP) {
		ap.x = x;
		ap.y = y;
		int dx = ap.x - sp.x;
		int dy = ap.y - sp.y;

		if (sp.x > 0 && sp.y > 0) {	//防止越界访问
			Rect box(sp.x, sp.y, dx, dy);
			rectangle(image, box, Scalar(0, 0, 255), 2, 8, 0);
			imshow("绘制前", image);

			if (dx > 0 && dy > 0) {  //防止越界访问
				tmp.copyTo(image);	//清楚红边框
				imshow("ROT截取", image(box));
			}

			sp.x = -1;
			sp.y = -1;
			std::cout << "end: " << ap << std::endl;
		}
		
	}

	//当鼠标移动的时候会清空屏幕
	else if (event == EVENT_MOUSEMOVE) {
		tmp.copyTo(image);	//清除屏幕
	}
}

void QuickDemo::mouse_drawing_demo(Mat& image)
{
	namedWindow("绘制前", WINDOW_AUTOSIZE);
	imshow("绘制前", image);
	//设置回调机制
	setMouseCallback("绘制前",on_draw,(void *)(&image));
	tmp = image.clone();
}

展示效果:

在这里插入图片描述

绘制圆形

Point p(-1, -1);
Mat tmp;
static void on_draw(int event, int x, int y ,int flags, void *userobj) 
{
	Mat image = *(Mat*)userobj;
	if (event == EVENT_LBUTTONDOWN) {
		p.x = x;
		p.y = y;
		std::cout << "start: " << p << std::endl;
	}
	else if (event == EVENT_LBUTTONUP) {
		circle(image, p, 80,  Scalar(0,0,255), -1);
		imshow("绘制前", image);
	}
	else if(event == EVENT_MOUSEMOVE){
		tmp.copyTo(image);	//清空屏幕
	}
}

void QuickDemo::mouse_drawing_demo(Mat& image)
{
	namedWindow("绘制前", WINDOW_AUTOSIZE);
	imshow("绘制前", image);
	//设置回调机制
	setMouseCallback("绘制前",on_draw,(void *)(&image));
	tmp = image.clone();
}

鼠标点击某一个点会自动画一个圆形

在这里插入图片描述

图像像素归一化

  • opencv中提供了四种归一化的方式
  • NORM_MINMAX
  • NORM_INF
  • NORM_L1
  • NORM_L2

注:最常用的是NORM_MINMAX归一化方法

 void normalize(
	 InputArray src,	//输入图像
	 OutputArray dst,   //输出图像 
	 double alpha = 1,  //NORM_MINMAX时候最低值
	 double beta = 0,   //NORM_MINMAX时候最高值 
	 int norm_type = NORM_L2,  //只有alpha
	 int dtype = -1, 	//默认类型与src一致
	 InputArray mask = noArray() //mask默认值为空
 )

类型转换

  • CV_8UC3:3通道每个通道都是RGB 通道 ,每个通道的取值范围是[0, 255],每个通道是8位无符号字节数据类型。
  • CV_32F3:3通道每个通道都是RGB 通道 ,每个通道的取值范围是[0, 4294967295],每个通道是32位浮点数数据类型。
void QuickDemo::norm_demo(Mat& image) 
{
	Mat dst;  //存储转换后的结果
	std::cout << image.type() << std::endl;  //CV_8UC3
	image.convertTo(dst, CV_32FC3);
	std::cout << dst.type() << std::endl;    //CV_32FC3
}

使用normalize函数做归一化处理需要先将CV_8UC3字节类型的图像像素转换为浮点型处理, 因为归一化处理之后的数据范围都在[0, 1]之间,需要用到浮点数保存

void QuickDemo::norm_demo(Mat& image) 
{
	Mat dst;  //存储转换后的结果
	std::cout << image.type() << std::endl;  //CV_8UC3
	
	image.convertTo(image, CV_32FC3);
	std::cout << image.type() << std::endl;    //CV_32FC3
	
	normalize(image, dst, 1.0, 0,NORM_MINMAX);  //做归一化处理
	std::cout << dst.type() << std::endl;

	imshow("类型转换CV_32FC3之后", image);
	imshow("归一化处理之后", dst);
}

将CV_8UC3类型的数据转换成CV_32FC3数据类型后,可以看出图像的像素类型变了之后,与之前的差异比较大,可是做完归一化处理之后在肉眼观察基本上跟原图没有啥区别。

在这里插入图片描述

图像放缩插值

void QuickDemo::resize_demo(Mat& image) 
{
	Mat zoomin, zoomout;  //放大缩小对象
	int h = image.rows;  //行
	int w = image.cols;	 //列

	//按照宽高进行缩小
	resize(image, zoomout, Size(h / 2, w / 2));
	imshow("缩小", zoomout);
	//按照宽高进行放大
	resize(image, zoomin, Size(h * 1.5, w * 1.5));
	imshow("放大", zoomin);
}

鼠标滚动事件缩小和放大窗口

原理

  • 其中scale可以在外部定义为全局变量,通过响应CV_EVENT_MOUSEWHEEL滑轮事件获取Scale的具体值。

  • 获取Scale值需要关注两个问题,滑轮滑动的方向和滑动量的大小。滑动方向通过getMouseWheelDelta(flags)获取,

  • 当返回值>0时,表示向前滑动;

  • 当返回值<0时,表示向后滑动。滑动量根据滑动方向自行设置相应的滑动步长即可。

void call_back(int event, int x, int y, int flags, void*userobj) 
{
	Mat src = *(Mat*)userobj;
	Mat zoominout;
	int h = src.rows;
	int w = src.cols;

	//获取滚动事件
	if (event == cv::EVENT_MOUSEWHEEL) {
	
		//获取鼠标上下滚动时的值
		int Scale = getMouseWheelDelta(flags);
		if (Scale > 0) {
			Scale = Scale / 120 + 1.5;  //放大1.5倍
			resize(src, zoominout, Size(h * Scale, w * Scale), INTER_LINEAR);
		}
		if (Scale < 0) {
			Scale = abs(Scale / 120) + 1;  //缩小2倍
			resize(src, zoominout, Size(h / Scale, w / Scale), INTER_LINEAR);
		}
		imshow("触发后", zoominout);
	}
}

void QuickDemo::mouse_resize_demo(Mat& image)
{
	namedWindow("鼠标触发事件", WINDOW_AUTOSIZE);
	setMouseCallback("鼠标触发事件", call_back, (void *)(&image));
	imshow("鼠标触发事件", image);
}

将鼠标悬浮在鼠标触发事件窗口上,可以使用鼠标的滚轮进行放大和缩小

在这里插入图片描述

createTrackbar 创建滚动条的方式调整图片大小

Mat dst, m, src;
void on_track1(int val, void *userobj)
{
	int h = src.rows;
	int w = src.cols;

	resize(src, dst, Size(h + val, w + val), INTER_LINEAR);
	imshow("调整后", dst);
}

void QuickDemo::mycreateTrackbar(Mat& image) {
	int val = 50;
	dst = Mat::zeros(image.size(), image.type());
	m = Mat::zeros(image.size(), image.type());
	src = image.clone();	//深拷贝

	namedWindow("调整", WINDOW_AUTOSIZE);
	//当滚动按钮被拖动的时候,on_track函数会去调整光的亮度
	createTrackbar("调整", "调整", &val,
		200, on_track1, (void *)&image);

	on_track1(50, 0);		//固定写法
	imshow("调整", image);
}

在这里插入图片描述

本文含有隐藏内容,请 开通VIP 后查看