鼠标操作[OpenCV 笔记10]
void setMouseCallback(const string& winname, MouseCallback onMouse, void* userdata=0)
winname
窗口名字
onMouse
指定窗口每次鼠标事件发生的时候,被调用的函数指针。函数的原型应为void Foo(int event, int x, int y, int flags, void* param)。
- event: 变量EVENT_XXX,例如
- EVNET_MOUSEMOVE: 鼠标移动消息
- EVENT_LBUTTONDOWN: 鼠标左键按下消息
- x, y: 鼠标指针在图像坐标系中的坐标值(不是窗口坐标系)
- flags: EVENT_FLAG的组合
- param: 用户定义的传到SetMouseCallback函数调用的参数
userdata
用户定义的传递到回调函数的参数
示例
用鼠标在画框中华矩形,MouseEvent.cxx:
#include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp> #define WINDOW_NAME "Painting Window" // global function declaration void on_MouseHandle( int event, int x, int y, int flags, void* param ); void DrawRectangle( cv::Mat& img, cv::Rect box ); void ShowHelpText(); // global variables cv::Rect g_rectangle; bool g_bDrawingBox = false; // draw or not cv::RNG g_rng(12345); // main int main( int argc, char** argv ) { // initialize parameters g_rectangle = cv::Rect( -1, -1, 0, 0 ); cv::Mat srcImage( 600, 800, CV_8UC3 ), tempImage; srcImage.copyTo( tempImage ); g_rectangle = cv::Rect( -1, -1, 0, 0 ); srcImage = cv::Scalar::all(0); // create window cv::namedWindow(WINDOW_NAME); // set call back function cvSetMouseCallback(WINDOW_NAME, on_MouseHandle, (void*)&srcImage); while(1) { srcImage.copyTo(tempImage); // show rectangle while the mouse moves if (g_bDrawingBox) DrawRectangle(tempImage, g_rectangle); cv::imshow(WINDOW_NAME, tempImage); if (cvWaitKey(10)==27) { cv::imwrite("result.jpg", tempImage); break; // Press ECS to exit. } } return 0; } // mouse call back function void on_MouseHandle( int event, int x, int y, int flags, void* param ) { cv::Mat& image = *(cv::Mat*) param; switch (event) { case cv::EVENT_MOUSEMOVE: // if mouse moved and drawing flag is true, update the rectangle size if (g_bDrawingBox) { g_rectangle.width = x-g_rectangle.x; g_rectangle.height = y-g_rectangle.y; } break; case cv::EVENT_LBUTTONDOWN: // if left button was clicked, prepare to draw rectangle // (set the flag as true and mark the start position) { g_bDrawingBox = true; g_rectangle = cv::Rect( x, y, 0, 0 ); // mark the start point } break; case cv::EVENT_LBUTTONUP: { g_bDrawingBox = false; 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; } // draw DrawRectangle(image, g_rectangle); } break; } } // user defined function to draw rectangle void DrawRectangle( cv::Mat& img, cv::Rect box ) { // random color cv::rectangle(img, box.tl(), box.br(), cv::Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255))); }
结果图
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通