18. CVUI 2.7.0 鼠标和 OpenCV 窗口:Mouse(官方文档翻译)

官方文档链接:https://dovyski.github.io/cvui/advanced-mouse/


Mouse

cvui 拥有自己的鼠标 API 可以追踪鼠标点击和光标位置。与鼠标相关的所有内容都可以从 cvui::mouse() 中访问到。以下部分将详细介绍所有可用的鼠标信息。


光标位置(Cursor position)

用户可以通过调用 cvui::mouse() 随时查询鼠标光标的位置,它返回一个 cv::Point()

cv::Point mouse(const cv::String& theWindowName = "")

示例

// Save the mouse cursor to a point object
cv::Point cursor = cvui::mouse();
std::cout << "x: " << cursor.x << " y: " << cursor.y << std::endl;

// or access the position directly
std::cout << "x: " << cvui::mouse().x << " y: " << cvui::mouse().y << std::endl;

cvui::mouse() 的调用始终返回当前信息,因此用户不需要监听鼠标事件。只要调用 cvui::mouse(),就可以得到鼠标光标的最新位置。


检测事件 (Detect events)

用户可以通过调用 cvui::mouse(int) 来查询鼠标的状态,例如单击,其函数声明如下:

bool mouse(int theQuery)

参数 theQuery 是指定查询的整数。可用查询包括:

  • cvui::DOWN:查询是否按下了任何鼠标按键。cvui::mouse() 只对单个帧(鼠标按键按下的帧)返回 true。
  • cvui::UP:查询是否由鼠标按键被释放。cvui::mouse()只对单个帧(鼠标按键向上的帧)返回 true。
  • cvui::CLICK:查询是否单击了任何鼠标按键(按下然后释放,不管中间有多少帧)。cvui::mouse() 只对单个帧返回 true。
  • cvui::IS_DOWN:查询当前是否按下了任何鼠标按键。只要按下鼠标按键,cvui::mouse() 返回 true。

重要:对 cvui::mouse(int) 的调用将查询所有鼠标按键,因此如果按下任何鼠标按键,则调用 cvui::mouse(cvui::DOWN) 将返回 true。

在下面的例子中,当按下任意鼠标按键,将会显示信息:

if(cvui::mouse(cvui::DOWN)) 
{
    std::cout << "Any mouse button just went down." << std::endl;
}

在下面的例子中,当点击鼠标按键,将会显示信息(按下然后释放):

if(cvui::mouse(cvui::CLICK))
{
    std::cout << "A mouse click just happened." << std::endl;
}

逐个检查鼠标按钮 (Check mouse buttons individually)

用户可以查询特定的鼠标按键的状态,例如对鼠标左键上的单击做出反应。

可以通过 cvui::mouse(int, int) 查询特定的鼠标按键,其函数声明为:

bool mouse(int theButton, int theQuery)

参数 theButton 允许用户指定要查询的鼠标按钮。可用的按钮有 cvui::LEFT_BUTTONcvui::MIDDLE_BUTTONcvui::RIGHT_BUTTON

函数 cvui::mouse(int theButton, int theQuery) 的工作方式与 cvui::mouse(int theQuery) 完全相同,唯一的区别是查询的目标是特定的按键,而不是所有的按键。

下面是按下鼠标左键时打印信息的示例:

if(cvui::mouse(cvui::LEFT_BUTTON, cvui::DOWN))
{
    std::cout << "Left mouse button just went down." << std::endl;
}

输出结果

在这里插入图片描述

点击窗口任意位置即可触发输出事件。


示例一

完整代码

#define CVUI_IMPLEMENTATION
#define CVUI_DISABLE_COMPILATION_NOTICES
#include "cvui.h"

#include <iostream>

#include <opencv2/core/core.hpp>
#include <opencv2/imgcodecs/imgcodecs.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

#define WINDOW_NAME "CVUI Test"

int main(int argc, char** argv)
{
	cvui::init(WINDOW_NAME);

	cv::Mat frame = cv::Mat(cv::Size(800, 600), CV_8UC3);

	cv::Rect rectangle(0, 0, 0, 0);

	while (true)
	{
		frame = cv::Scalar(100, 100, 100);

		cvui::text(frame, 10, 30, "Click (any) mouse button and drag the pointer around to select an area.");
		cvui::printf(frame, 10, 50, "Mouse pointer is at (%d, %d)", cvui::mouse().x, cvui::mouse().y);

		if (cvui::mouse(cvui::DOWN))
		{
			rectangle.x = cvui::mouse().x;
			rectangle.y = cvui::mouse().y;
		}

		if (cvui::mouse(cvui::IS_DOWN))
		{
			rectangle.width = cvui::mouse().x - rectangle.x;
			rectangle.height = cvui::mouse().y - rectangle.y;

			cvui::printf(frame, rectangle.x + 5, rectangle.y + 5, 0.3, 0xffffff, "(%d, %d)", rectangle.x, rectangle.y);
			cvui::printf(frame, cvui::mouse().x + 5, cvui::mouse().y + 5, 0.3, 0xffffff, "w:%d, h:%d", rectangle.width, rectangle.height);
		}

		if (cvui::mouse(cvui::UP))
		{
			rectangle.x = 0;
			rectangle.y = 0;
			rectangle.width = 0;
			rectangle.height = 0;
		}

		if (cvui::mouse(cvui::CLICK))
			cvui::text(frame, 10, 70, "Mouse was clicked!");

		//cvui::rect(frame, rectangle.x, rectangle.y, rectangle.width, rectangle.height, 0xff0000);
		cvui::rect(frame, rectangle.x, rectangle.y, rectangle.width, rectangle.height, 0xff0000, 0xffffffff);
		
		

		cvui::imshow(WINDOW_NAME, frame);

		if (cv::waitKey(20) == 27)
			break;
	}
	

	return 0;
}

输出结果

在这里插入图片描述

此程序运行时,按下鼠标会在 frame 中的对应位置显示坐标,同时拖动鼠标会在 frame 的对应区域处形成一个矩形框,矩形框的右下角将显示矩形框的宽度和高度。

值得注意的是如下代码:

if (cvui::mouse(cvui::DOWN))
{
	rectangle.x = cvui::mouse().x;
	rectangle.y = cvui::mouse().y;
}

if (cvui::mouse(cvui::IS_DOWN))
{
	rectangle.width = cvui::mouse().x - rectangle.x;
	rectangle.height = cvui::mouse().y - rectangle.y;

	cvui::printf(frame, rectangle.x + 5, rectangle.y + 5, 0.3, 0xffffff, "(%d, %d)", rectangle.x, rectangle.y);
	cvui::printf(frame, cvui::mouse().x + 5, cvui::mouse().y + 5, 0.3, 0xffffff, "w:%d, h:%d", rectangle.width, rectangle.height);
}

cvui::DOWN 可以用来表示鼠标按下的这个动作,而 cvui::IS_DOWN 可以用来表示鼠标一直处于按下的状态。

示例二

完整代码

#define CVUI_IMPLEMENTATION
#define CVUI_DISABLE_COMPILATION_NOTICES
#include "cvui.h"

#include <iostream>

#include <opencv2/core/core.hpp>
#include <opencv2/imgcodecs/imgcodecs.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

#define WINDOW_NAME "Mouse - ROI interaction"
#define ROI_WINDOW "ROI"

int main(int argc, char** argv)
{
	cvui::init(WINDOW_NAME);

	cv::Mat lena = cv::imread("lena.jpg");
	cv::Mat frame = lena.clone();

	cv::Point anchor;
	cv::Rect roi(0, 0, 0, 0);

	bool working = false;

	while (true)
	{
		lena.copyTo(frame);

		cvui::text(frame, 10, 10, "Click (any) mouse button and drag the pointer around to select a ROI.");
		
		if (cvui::mouse(cvui::DOWN))
		{
			anchor.x = cvui::mouse().x;
			anchor.y = cvui::mouse().y;

			working = true;
		}

		if (cvui::mouse(cvui::IS_DOWN))
		{
			int width = cvui::mouse().x - anchor.x;
			int height = cvui::mouse().y - anchor.y;

			roi.x = width < 0 ? anchor.x + width : anchor.x;
			roi.y = height < 0 ? anchor.y + height : anchor.y;
			roi.width = std::abs(width);
			roi.height = std::abs(height);

			cvui::printf(frame, roi.x + 5, roi.y + 5, 0.3, 0xffffff, "(%d, %d)", roi.x, roi.y);
			cvui::printf(frame, cvui::mouse().x + 5, cvui::mouse().y + 5, 0.3, 0xffffff, "w:%d, h:%d", roi.width, roi.height);
		}

		if (cvui::mouse(cvui::UP))
			working = false;

		roi.x = roi.x < 0 ? 0 : roi.x;
		roi.y = roi.y < 0 ? 0 : roi.y;
		roi.width = roi.x + roi.width > lena.cols ? roi.width + lena.cols - (roi.x + roi.width) : roi.width;
		roi.height = roi.y + roi.height > lena.rows ? roi.height + lena.rows - (roi.y + roi.height) : roi.height;

		cvui::rect(frame, roi.x, roi.y, roi.width, roi.height, 0xff0000);

		cvui::imshow(WINDOW_NAME, frame);

		if (roi.area() > 0 && !working)
			cv::imshow(ROI_WINDOW, lena(roi));

		if (cv::waitKey(20) == 27)
			break;
	}
	

	return 0;
}

输出图像

在这里插入图片描述

示例三

完整代码

#define CVUI_IMPLEMENTATION
#define CVUI_DISABLE_COMPILATION_NOTICES
#include "cvui.h"

#include <iostream>

#include <opencv2/core/core.hpp>
#include <opencv2/imgcodecs/imgcodecs.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

#define WINDOW_NAME "Mouse complex buttons - ROI interaction"

int main(int argc, char** argv)
{
	cv::Mat lena = cv::imread("lena.jpg");
	cv::Mat frame = lena.clone();
	cv::Point anchors[3];
	cv::Rect rois[3];
	unsigned int colors[] = { 0xff0000, 0x00ff00, 0x0000ff };

	cvui::init(WINDOW_NAME);

	while (true) {
		lena.copyTo(frame);

		cvui::text(frame, 10, 10, "Click (any) mouse button then drag the pointer around to select a ROI.");
		cvui::text(frame, 10, 25, "Use different mouse buttons (right, middle and left) to select different ROIs.");

		for (int button = cvui::LEFT_BUTTON; button <= cvui::RIGHT_BUTTON; button++)
		{
			cv::Point& anchor = anchors[button];
			cv::Rect& roi = rois[button];
			unsigned int color = colors[button];

			if (cvui::mouse(button, cvui::DOWN))
			{
				anchor.x = cvui::mouse().x;
				anchor.y = cvui::mouse().y;
			}

			if (cvui::mouse(button, cvui::IS_DOWN))
			{
				int width = cvui::mouse().x - anchor.x;
				int height = cvui::mouse().y - anchor.y;

				roi.x = width < 0 ? anchor.x + width : anchor.x;
				roi.y = height < 0 ? anchor.y + height : anchor.y;
				roi.width = std::abs(width);
				roi.height = std::abs(height);

				cvui::printf(frame, roi.x + 5, roi.y + 5, 0.3, color, "(%d, %d)", roi.x, roi.y);
				cvui::printf(frame, cvui::mouse().x + 5, cvui::mouse().y + 5, 0.3, color, "w:%d, h:%d", roi.width, roi.height);
			}

			roi.x = roi.x < 0 ? 0 : roi.x;
			roi.y = roi.y < 0 ? 0 : roi.y;
			roi.width = roi.x + roi.width > lena.cols ? roi.width + lena.cols - (roi.x + roi.width) : roi.width;
			roi.height = roi.y + roi.height > lena.rows ? roi.height + lena.rows - (roi.y + roi.height) : roi.height;

			if (roi.area() > 0)
			{
				cvui::rect(frame, roi.x, roi.y, roi.width, roi.height, color);
				cvui::printf(frame, roi.x + 5, roi.y - 10, 0.3, color, "ROI %d", button);

				cv::imshow("ROI button " + std::to_string(button), lena(roi));
			}
		}
		
		cvui::update();

		cv::imshow(WINDOW_NAME, frame);

		if (cv::waitKey(20) == 27) {
			break;
		}
	}

	return 0;
}

输出结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值