• opencv入门四


    鼠标操作与响应

    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));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    在这里插入图片描述

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

    
    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();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    在这里插入图片描述

    提取图像框选中部分

    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();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    展示效果:

    在这里插入图片描述

    绘制圆形

    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();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

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

    在这里插入图片描述

    图像像素归一化

    • 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默认值为空
     )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    类型转换

    • 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
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    使用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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    将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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

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

    原理

    • 其中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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

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

    在这里插入图片描述

    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);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    在这里插入图片描述

  • 相关阅读:
    Vue官方文档(48): vuex的基本使用
    Linux搭建我的世界服务器 + 公网远程联机教程「不需要公网IP」
    springboot+Mybatis项目初始化
    企业微信+SCRM的整体营销工作要如何形成合力?
    算法 主持人调度-(双指针+贪心)
    2、排序算法概述
    Vue - 实现微信扫码登录功能(项目植入微信扫码登录功能)超详细完整流程详解及详细代码及注释,附带完整功能源码、常见问题解决方案
    修改 Stable Diffusion 使 api 接口增加模型参数
    Linux之计划任务
    5.Nacos
  • 原文地址:https://blog.csdn.net/m0_53421868/article/details/126676665