Opencv鼠标回调选取多个区域

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)

范围:

eventcv::MouseEventTypes 鼠标事件
x鼠标X坐标
y鼠标Y坐标
flagsone 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;
	}

}

image-20220315102149884

方法二:

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);

}

第二种方法简单好用,非常友好

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
xiaoxingxing的头像xiaoxingxing管理团队
上一篇 2022年3月23日
下一篇 2022年3月23日

相关推荐