OpenCV9-窗口交互操作

OpenCV9-窗口交互操作


1.图像窗口滑动条

图像窗口滑动条就是显示在图像的窗口中,能够通过滑动改变数值的滑动条。OpenCV中使用createTrackbar函数在显示图像的窗口中创建滑动条:

cpp 复制代码
int createTrackbar(
    const String& trackbarname,  // 滑动条的名称
    const String& winname,       // 图像显示的窗口名
    int* value,   // 滑动条的初始位置
    int count,    // 滑动条的最大取值
    TrackbarCallback onChange = 0, // 滑块更改位置时的回调函数
    void* userdata = 0 // 传递给回调函数的参数
);

// pos是轨迹栏位置,userdata是用户数据
typedef void (*TrackbarCallback)(int pos, void* userdata);

下面是拖动滑动条改变图像亮度的代码:

cpp 复制代码
#include <opencv2\opencv.hpp>
#include <opencv2/core/utils/logger.hpp> // debug no log
#include <iostream>
using namespace cv;
using namespace std;

//为了能在被调函数中使用,所以设置成全局的
int value;
void callBack(int, void*);  //滑动条回调函数
Mat img1, img2;

int main()
{
	cout << "OpenCV Version: " << CV_VERSION << endl;
	utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);

	img1 = imread("lena.png");
	if (!img1.data)
	{
		cout << "请确认是否输入正确的图像文件" << endl;
		return -1;
	}
	namedWindow("滑动条改变图像亮度");
	imshow("滑动条改变图像亮度", img1);
	value = 100;  //滑动条创建时的初值
	//创建滑动条
	createTrackbar("亮度值百分比", "滑动条改变图像亮度", &value, 600, callBack, 0);

	waitKey(0);
	return 0;
}

static void callBack(int, void*)
{
	float a = value / 100.0;
	img2 = img1 * a;
	imshow("滑动条改变图像亮度", img2);
}

2.鼠标响应

OpenCV提供了鼠标响应相关函数setMouseCallback:

cpp 复制代码
void setMouseCallback(
    const String& winname, // 图像所在窗口名
    MouseCallback onMouse, // 鼠标响应回调函数
    void* userdata = 0     // 传递给回调函数参数
);

鼠标响应的回调函数:

cpp 复制代码
typedef void (*MouseCallback)(
    int event, 
    int x, int y,   // 鼠标指针在图像坐标戏中的坐标 
    int flags, 
    void* userdata
);

event鼠标响应事件:EVENT_RBUTTONDOWN表示鼠标右键按下,EVENT_MOUSEMOVE鼠标移动。

cpp 复制代码
enum MouseEventTypes {
       EVENT_MOUSEMOVE      = 0, //!< indicates that the mouse pointer has moved over the window.
       EVENT_LBUTTONDOWN    = 1, //!< indicates that the left mouse button is pressed.
       EVENT_RBUTTONDOWN    = 2, //!< indicates that the right mouse button is pressed.
       EVENT_MBUTTONDOWN    = 3, //!< indicates that the middle mouse button is pressed.
       EVENT_LBUTTONUP      = 4, //!< indicates that left mouse button is released.
       EVENT_RBUTTONUP      = 5, //!< indicates that right mouse button is released.
       EVENT_MBUTTONUP      = 6, //!< indicates that middle mouse button is released.
       EVENT_LBUTTONDBLCLK  = 7, //!< indicates that left mouse button is double clicked.
       EVENT_RBUTTONDBLCLK  = 8, //!< indicates that right mouse button is double clicked.
       EVENT_MBUTTONDBLCLK  = 9, //!< indicates that middle mouse button is double clicked.
       EVENT_MOUSEWHEEL     = 10,//!< positive and negative values mean forward and backward scrolling, respectively.
       EVENT_MOUSEHWHEEL    = 11 //!< positive and negative values mean right and left scrolling, respectively.
};

flags鼠标响应标志:EVENT_FLAG_LBUTTON表示按住鼠标左键拖拽

cpp 复制代码
enum MouseEventFlags {
       EVENT_FLAG_LBUTTON   = 1, //!< indicates that the left mouse button is down.
       EVENT_FLAG_RBUTTON   = 2, //!< indicates that the right mouse button is down.
       EVENT_FLAG_MBUTTON   = 4, //!< indicates that the middle mouse button is down.
       EVENT_FLAG_CTRLKEY   = 8, //!< indicates that CTRL Key is pressed.
       EVENT_FLAG_SHIFTKEY  = 16,//!< indicates that SHIFT Key is pressed.
       EVENT_FLAG_ALTKEY    = 32 //!< indicates that ALT Key is pressed.
};

鼠标响应就是当鼠标位于对应图像窗口内时,时刻监测鼠标状态,当鼠标状态发生改变时,调用回调函数,并根据回调函数中的判断逻辑选择执行相应的操作。

下面的例子中:如果鼠标右键被按下,就会提示"点击鼠标左键才可以绘制轨迹",如果单机鼠标左键,就会输出当前鼠标坐标,并将该坐标定义为某段轨迹的起始位置。之后按住左键移动鼠标,会绘制鼠标的移动轨迹。

一种绘制轨迹的方法时每次调用回调函数获得鼠标位置时更改周围的图像像素值,这种方法比较直观但是回调函数有一定执行时间,因此当鼠标移动较快时绘制的图像轨迹会出现断点。第二种方法是在前一时刻和当前时刻鼠标位置绘制直线。

cpp 复制代码
#include <opencv2\opencv.hpp>
#include <opencv2/core/utils/logger.hpp> // debug no log
#include <iostream>
using namespace cv;
using namespace std;

Mat img, imgPoint; //全局的图像
Point prePoint; //前一时刻鼠标的坐标,用于绘制直线
void mouse(int event, int x, int y, int flags, void*);

int main()
{
	cout << "OpenCV Version: " << CV_VERSION << endl;
	utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);

	img = imread("lena.png");
	if (!img.data)
	{
		cout << "请确认输入图像名称是否正确! " << endl;
		return -1;
	}
	img.copyTo(imgPoint);
	imshow("图像窗口 1", img);
	imshow("图像窗口 2", imgPoint);
	setMouseCallback("图像窗口 1", mouse, 0);

	waitKey(0);
	return 0;
}

void mouse(int event, int x, int y, int flags, void*)
{
	if (event == EVENT_RBUTTONDOWN) //单击右键
	{
		cout << "点击鼠标左键才可以绘制轨迹" << endl;
	}
	if (event == EVENT_LBUTTONDOWN) //单击左键,输出坐标
	{
		prePoint = Point(x, y);
		cout << "轨迹起始坐标" << prePoint << endl;
	}
	if (event == EVENT_MOUSEMOVE && (flags & EVENT_FLAG_LBUTTON)) //鼠标按住左键移动第 3 章 图像基本操作
	{
		//通过改变图像像素显示鼠标移动轨迹
		imgPoint.at<Vec3b>(y, x) = Vec3b(0, 0, 255);
		imgPoint.at<Vec3b>(y, x - 1) = Vec3b(0, 0, 255);
		imgPoint.at<Vec3b>(y, x + 1) = Vec3b(0, 0, 255);
		imgPoint.at<Vec3b>(y + 1, x) = Vec3b(0, 0, 255);
		imgPoint.at<Vec3b>(y + 1, x) = Vec3b(0, 0, 255);
		imshow("图像窗口 2", imgPoint);

		//通过绘制直线显示鼠标移动轨迹
		Point pt(x, y);
		line(img, prePoint, pt, Scalar(0, 0, 255), 2, 5, 0);
		prePoint = pt;
		imshow("图像窗口 1", img);
	}
}
相关推荐
凯子坚持 c1 小时前
StreamingLLM:无需训练即可支持无限上下文的推理技术
人工智能
Tfly__1 小时前
在PX4 gazebo仿真中加入Mid360(最新)
linux·人工智能·自动驾驶·ros·无人机·px4·mid360
LLWZAI1 小时前
让朱雀AI检测无法判断的AI公众号文章,当创作者开始与算法「躲猫猫」
大数据·人工智能·深度学习
nLsUCWFJR1 小时前
(Matlab)基于贝叶斯优化卷积双向长短期记忆网络(CNN-BiLSTM)回归预测
opencv
深圳市九鼎创展科技1 小时前
瑞芯微 RK3399 开发板 X3399 评测:高性能 ARM 平台的多面手
linux·arm开发·人工智能·单片机·嵌入式硬件·边缘计算
HELLO程序员1 小时前
Claude Code 2.1 发布:2026 年 AI 智能体开发的范式革命
人工智能
智者知已应修善业1 小时前
【洛谷P9975奶牛被病毒传染最少数量推导,导出多样例】2025-2-26
c语言·c++·经验分享·笔记·算法·推荐算法
DFCED1 小时前
OpenClaw部署实战:5分钟搭建你的专属AI数字员工(附避坑指南)
人工智能·大模型·agent·openclaw
Java新手村1 小时前
基于 Vue 3 + Spring Boot 3 的 AI 面试辅助系统:实时语音识别 + 大模型智能回答
vue.js·人工智能·spring boot
Trouvaille ~1 小时前
【Linux】应用层协议设计实战(一):自定义协议与网络计算器
linux·运维·服务器·网络·c++·http·应用层协议