【OpenCV学习记录】3.HighGUI——鼠标的基本事件

今天学习了下HighGUI的鼠标事件,书上的例程完成了随机颜色的矩形框的绘制,代码如下:

// 鼠标测试:绘制彩色矩形框

#include "pch.h"
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
#define WINDOW_NAME "【程序窗口】"
//--------------------【全局函数声明部分】---------------------
//     描述:全局函数的声明
//----------------------------------------------------------
//鼠标回调函数
void on_MouseHandle(int event, int x, int y, int flags, void * param);
void DrawRactangle(Mat & img, Rect box);
//---------------------【全局变量声明部分】--------------------
//     描述:全局变量的声明
//----------------------------------------------------------
Rect g_rectangle;//矩形框变量
bool g_bDrawingBox = false;//是否进行绘制
RNG g_rng(12345);
//-------------------------【主函数】------------------------
//     描述:主函数
//----------------------------------------------------------
int main(int argc, char ** argv)
{
	//准备参数
	g_rectangle = Rect(-1, -1, 0, 0);
	Mat srcImage(600, 800, CV_8UC3), tempImage;
	srcImage.copyTo(tempImage);
	srcImage = Scalar::all(0);
	// 设置鼠标操作回调函数
	namedWindow(WINDOW_NAME);
	setMouseCallback(WINDOW_NAME, on_MouseHandle, (void *)&srcImage);
	// 程序主循环,当进行绘制的标识符为真的时候进行绘制
	while (1)
	{
		srcImage.copyTo(tempImage);       // 复制源图到临时变量
		if (g_bDrawingBox)
		{
			DrawRactangle(tempImage, g_rectangle);   //进行绘制
		}
		imshow(WINDOW_NAME, tempImage);
		if (waitKey(10) == 27)            // 按下ESC键,程序退出
			break;
	}
	return 0;
}
//------------------------【on_MouseHandle(函数)】------------
//     描述:鼠标回调函数,根据不同的鼠标事件进行不同的操作
//-----------------------------------------------------------
void on_MouseHandle(int event, int x, int y, int flags, void * param)
{
	Mat & image = *(Mat*)param;
	switch (event)
	{
	case EVENT_MOUSEMOVE:
	{
		if (g_bDrawingBox)   //如果是否进行绘制的标识符为真,则记录下长和宽到RECT型变量中
		{
			g_rectangle.width = x - g_rectangle.x;
			g_rectangle.height = y - g_rectangle.y;
		}
	}
	break;
	// 左键按下消息
	case EVENT_LBUTTONDOWN:
	{
		g_bDrawingBox = true;
		g_rectangle = Rect(x, y, 0, 0);   //记录起点
	}
	break;
	//左键抬起消息
	case EVENT_LBUTTONUP:
	{
		// 标识符为false
		g_bDrawingBox = false;
		//对宽和高小于0的处理
		if (g_rectangle.width < 0)
		{
			g_rectangle.x += g_rectangle.width;
			g_rectangle.width *= -1;
		}
		if (g_rectangle.height < 0)
		{
			g_rectangle.y += g_rectangle.height;
			g_rectangle.height *= -1;
		}
		//调用函数进行绘制
		DrawRactangle(image, g_rectangle);
	}
	break;
	}
}
void DrawRactangle(Mat & img, Rect box)
{
	// tl(top left) br(below right)
	rectangle(img, box.tl(), box.br(), Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255)));
}

示例结果:
在这里插入图片描述
在此基础之上,我完成了一个鼠标框选截图的功能,代码如下:

// 鼠标框选截图
#include "pch.h"
#include <iostream>
#include <opencv2/opencv.hpp>
#include <string>
using namespace cv;
using namespace std;
//定义全局变量
#define WINDOW_NAME "鼠标框选截图"//窗口名
bool Draw_or_not = false;//是否绘图标识符
Rect Draw_Rect = Rect(-1, -1, 0, 0);//矩形框变量
/*---------------------------------------------------------【函数部分】---------------------------------------------------------------------*/
//绘图函数
//输入:图片地址,矩形框变量
//调用后在图中指定位置绘制白色矩形框
void DrawRactangle(Mat &image, Rect rect)
{
	// tl(top left) br(below right)
	rectangle(image, rect.tl(), rect.br(), Scalar::all(255));
}
//输出截图
//输入:原图,截取矩形框,新窗口名称
//调用后在新窗口中显示截取后的子图
void CroppedImage(Mat image, Rect rect, string window_name)
{
	Mat cropped_image = image(rect);
	imshow(window_name, cropped_image);
}
//鼠标回调函数,根据鼠标操作改变矩形框变量值,并绘制矩形框
void on_MouseHandle(int event, int x, int y, int flags, void * param)
{
	Mat &image = *(Mat*)param;
	//存储原图
	Mat source_image;
	image.copyTo(source_image);
	//处理鼠标事件
	switch (event)
	{
	case EVENT_MOUSEMOVE:
	{
		if (Draw_or_not)   //如果是否进行绘制的标识符为真,则记录下长和宽到RECT型变量中
		{
			Draw_Rect.width = x - Draw_Rect.x;
			Draw_Rect.height = y - Draw_Rect.y;
		}
	}
	break;
	// 左键按下消息
	case EVENT_LBUTTONDOWN:
	{
		Draw_or_not = true;
		Draw_Rect = Rect(x, y, 0, 0);   //记录起点
	}
	break;
	//左键抬起消息
	case EVENT_LBUTTONUP:
	{
		// 标识符为false
		Draw_or_not = false;
		//对宽和高小于0的处理
		if (Draw_Rect.width < 0)
		{
			Draw_Rect.x += Draw_Rect.width;
			Draw_Rect.width *= -1;
		}
		if (Draw_Rect.height < 0)
		{
			Draw_Rect.y += Draw_Rect.height;
			Draw_Rect.height *= -1;
		}
		//调用函数进行绘制
		DrawRactangle(image, Draw_Rect);
		//截图输出
		CroppedImage(image, Draw_Rect, "截图");
		//图像还原
		source_image.copyTo(image);
	}
	break;
	}
}
//主函数
int main()
{
    //读取图片
	Mat image = imread("image.jpg");
	if (!image.data)
		cout << "【图片读取失败】" << endl;
	//临时图片
	Mat tem_image;
	//设置鼠标回调函数
	namedWindow(WINDOW_NAME);
	setMouseCallback(WINDOW_NAME, on_MouseHandle, (void *)&image);
	while (waitKey(10) != 27)
	{
		image.copyTo(tem_image);
		if(Draw_or_not)
			DrawRactangle(tem_image, Draw_Rect);
		imshow(WINDOW_NAME, tem_image);
	}
}

运行结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值