Opencv鼠标回调选取多个区域
背景
在图像处理中我们常常需要选取多个区域来进行处理,下面将介绍Opencv中两种多个区域选取的方法。
方法一:
使用鼠标回调选择多个区域,主要功能如下
void cv::setMouseCallback ( const String & winname,
MouseCallback onMouse,
void * userdata = 0
)
范围:
winname:窗口的名字
onMouse:鼠标的回调函数
userdata:传入回调函数的用户参数
鼠标回调函数:
typedef void(* cv::MouseCallback) (int event, int x, int y, int flags, void *userdata)
范围:
event | cv::MouseEventTypes 鼠标事件 |
---|---|
x | 鼠标X坐标 |
y | 鼠标Y坐标 |
flags | one of the cv::MouseEventFlags constants. |
userdata | 用户参数 |
event事件:
Enumerator | |
---|---|
EVENT_MOUSEMOVE | 鼠标指针在窗口上已移动。 |
EVENT_LBUTTONDOWN | 鼠标左键按下 |
EVENT_RBUTTONDOWN | 鼠标右键按下 |
EVENT_MBUTTONDOWN | 鼠标中键按下 |
EVENT_LBUTTONUP | 鼠标左键抬起 |
EVENT_RBUTTONUP | 鼠标右键抬起 |
EVENT_MBUTTONUP | 鼠标中键抬起 |
EVENT_LBUTTONDBLCLK | 双击鼠标左键 |
EVENT_RBUTTONDBLCLK | 双击鼠标右键 |
EVENT_MBUTTONDBLCLK | 双击鼠标中键 |
EVENT_MOUSEWHEEL | 正值和负值分别表示鼠标滚轮向前和向后滚动。 |
EVENT_MOUSEHWHEEL | 正值和负值分别表示鼠标滚轮向右和向左滚动。 |
例子:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
void setROI(Mat input);
Point g_leftpoint;//鼠标左键按下时把点保存到这个变量
Point g_rightpoint;//鼠标左键抬起时把点保存到这个变量
Mat g_displyimg; //输入的图片
Mat displayrect;
Mat medio;
vector<Rect>dectionAOI;//检测区域
void on_mouse(int event, int x, int y, int flags, void* ustc); //鼠标回调函数
int main()
{
g_displyimg = imread("1.bmp");
setROI(g_displyimg);
}
void on_mouse(int event, int x, int y, int flags, void* ustc)
{
//左键单击与抬起(画矩形)
if (event == EVENT_LBUTTONDOWN)//检测到左键按下,将初始点赋值
{
g_leftpoint = Point(x, y);
g_rightpoint = Point(x, y);
}
if (event == EVENT_MOUSEMOVE && (flags & EVENT_FLAG_LBUTTON))
{
if (y >= g_displyimg.rows)
{
y = g_displyimg.rows;
}
if (x >= g_displyimg.cols)
{
x = g_displyimg.cols;
}
}
if (event == EVENT_LBUTTONUP)
{
g_rightpoint = Point(x, y);
int width = abs(g_rightpoint.x - g_leftpoint.x);
int heigh = abs(g_rightpoint.y - g_leftpoint.y);
Rect show;
show.x = g_leftpoint.x;
show.y = g_leftpoint.y;
show.width = width;
show.height = heigh;
rectangle(displayrect, show, Scalar(0, 0, 255), 3);
dectionAOI.push_back(show);
namedWindow("colorimg", 0);
imshow("colorimg", displayrect);
}
if (event == EVENT_MOUSEWHEEL)//鼠标滚轮事件
{
//缩放事件
}
if (event == EVENT_RBUTTONDOWN)
{
}
if (event == EVENT_MOUSEMOVE && (flags & EVENT_FLAG_RBUTTON))
{
}
return;
}
void setROI(Mat input)
{
input.copyTo(displayrect);
input.copyTo(medio);
namedWindow("colorimg", 0);
setMouseCallback("colorimg", on_mouse, 0);
imshow("colorimg", input);
int c = waitKey(0);
if (c == 27)//按下按键Esc退出
{
return;
}
}
方法二:
void cv::selectROIs ( const String & windowName,
InputArray img,
std::vector< Rect > & boundingBoxes,
bool showCrosshair = true,
bool fromCenter = false
)
范围:
windowName | 显示选择过程的窗口的名称。 |
---|---|
img | 选择区域的图像 |
boundingBoxes | 保存的区域 |
showCrosshair | 如果为TRUE则显示选择区域 |
fromCenter | 如果选择的中心为真,则将匹配鼠标的初始位置。 |
在相反的情况下,选择矩形的一角将对应于鼠标的初始位置。 |
使用方法:使用空格键和回车键去完成当前的区域选择和开始新的区域选择,使用Esc来退出多个区域的选择
示例代码
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
/*g_displyimg = imread("1.bmp");
setROI(g_displyimg);*/
Mat m_display = imread("1.bmp");
namedWindow("1", 0);
imshow("1", m_display);
vector<Rect>ROI;
selectROIs("1", m_display, ROI, true,false);
for (int i = 0; i < ROI.size(); i++)
{
rectangle(m_display, ROI[i], Scalar(0, 0, 255), 3);
}
imshow("1", m_display);
waitKey(0);
}
第二种方法简单好用,非常友好
文章出处登录后可见!
已经登录?立即刷新