天天看點

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():

示例:

// 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) 來查詢滑鼠的狀态,例如單擊,其函數聲明如下:

參數 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) 查詢特定的滑鼠按鍵,其函數聲明為:

參數 theButton 允許使用者指定要查詢的滑鼠按鈕。可用的按鈕有 cvui::LEFT_BUTTON,cvui::MIDDLE_BUTTON,cvui::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;
}
           

輸出結果:

18. CVUI 2.7.0 滑鼠和 OpenCV 視窗:Mouse(官方文檔翻譯)

點選視窗任意位置即可觸發輸出事件。

示例一

完整代碼:

#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;
}
           

輸出結果:

18. CVUI 2.7.0 滑鼠和 OpenCV 視窗:Mouse(官方文檔翻譯)

此程式運作時,按下滑鼠會在 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;
}
           

輸出圖像:

18. CVUI 2.7.0 滑鼠和 OpenCV 視窗:Mouse(官方文檔翻譯)

示例三

完整代碼:

#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;
}
           

輸出結果:

18. CVUI 2.7.0 滑鼠和 OpenCV 視窗:Mouse(官方文檔翻譯)