【OpenCV】选择ROI区域

问题描述:在测试目标跟踪算法时,需要选择不同区域作为目标,进行目标跟踪,测试目标跟踪的效果。

解决思路:

1.OpenCV中提供了鼠标交互控制,利用setMouseCallback()给固定的窗口设置鼠标回调函数。

2.在鼠标回调函数中,选择感兴趣区域。

代码实现如下,将感兴趣区域封装在MouseSelect类中,提供选择点和矩形框两种模式。

【OpenCV】选择ROI区域

复制代码

 1 #pragma once

 2 #ifndef __MOUSESELECT_H__

 3 #define __MOUSESELECT_H__

 4 

 5 #include <opencv2/opencv.hpp>

 6 #include <iostream>

 7 

 8 #define MAX_OBJECTS    10

 9 using namespace cv;

10 using namespace std;

11 typedef struct MouseSelectParams

12 {

13     vector<Point> pts;        //Points of selected

14     char        *win_name;

15     Mat            *image;        

16     unsigned int mode;        //1 Point,2 Rect

17     int             n;            // selected object number

18 }MouseSelectParams;

19 

20 void on_mouse(int event,int x,int y,int flags,void *param);

21 class MouseSelect

22 {

23 public:

24     MouseSelect();

25     ~MouseSelect();

26 

27     void select_rect(Mat &frame);

28     void select_point(Mat &frame);

29 

30     vector<Point> vPoints;

31     vector<Rect> vRects;

32     unsigned int obj_selected;

33 private:

34     int get_rects(Mat &frame);

35     int get_points(Mat &frame);

36 

37 };

38 #endif

复制代码

【OpenCV】选择ROI区域

复制代码

  1 #include "MouseSelect.h"

  2 

  3 MouseSelectParams *g_mousep;

  4 MouseSelect::MouseSelect() {}

  5 

  6 MouseSelect::~MouseSelect() {}

  7 

  8 void MouseSelect::select_rect(Mat &frame)

  9 {

 10     obj_selected = 0;

 11     while(0 == obj_selected)

 12     {

 13         obj_selected = get_rects(frame);

 14         if (obj_selected == 0)

 15         {

 16             cout<<"You haven't selected any rectangles. "<<endl;

 17         }

 18     }

 19 }

 20 

 21 void MouseSelect::select_point(Mat &frame)

 22 {

 23     obj_selected = 0;

 24     while(0 == obj_selected)

 25     {

 26         obj_selected = get_points(frame);

 27         if (obj_selected == 0)

 28         {

 29             cout<<"You haven't selected any points."<<endl;

 30         }

 31     }

 32 }

 33 

 34 int MouseSelect::get_rects(Mat &frame)

 35 {

 36     char *win_name = "Init Frame";

 37     MouseSelectParams params;

 38     params.win_name = win_name;

 39     params.image = &frame;

 40     params.n = 0;

 41     params.mode = 2;

 42     namedWindow(win_name,WINDOW_AUTOSIZE);

 43     imshow(win_name,frame);

 44     

 45     g_mousep = &params;

 46     setMouseCallback(win_name,on_mouse,0);

 47     waitKey(0);

 48     destroyWindow(win_name);

 49     

 50     int x1,x2,y1,y2,w,h;

 51     Rect rt;

 52     Point pt1,pt2;

 53     cout<<"Point Num: "<<params.pts.size()<<" Object Num: "<<params.n<<" Object Type: Rect."<<endl;

 54     for(int i = 0;i < params.pts.size();i += 2)

 55     {

 56         pt1 = params.pts[i];

 57         pt2 = params.pts[i + 1];

 58         x1 = min(pt1.x,pt2.x);

 59         x2 = max(pt1.x,pt2.x);

 60         y1 = min(pt1.y,pt2.y);

 61         y2 = max(pt1.y,pt2.y);

 62         w = x2 - x1;

 63         h = y2 - y1;

 64         w = (w % 2)? w:w+1;

 65         h = (h % 2)? h:h+1;

 66         rt.x = x1;

 67         rt.y = y1;

 68         rt.width = w;

 69         rt.height = h;

 70         vRects.push_back(rt);

 71     }

 72     return params.n;

 73 }

 74 

 75 int MouseSelect::get_points(Mat &frame)

 76 {

 77     char    *win_name = "Init Frame";

 78     MouseSelectParams params;

 79     params.win_name = win_name;

 80     params.image = &frame;

 81     params.n = 0;

 82     params.mode = 1;

 83 

 84     namedWindow(win_name,1);

 85     imshow(win_name,frame);

 86 

 87     g_mousep = &params;

 88     setMouseCallback(win_name,on_mouse,0);

 89     waitKey(0);

 90 

 91     destroyWindow(win_name);

 92     

 93     cout<<"Point Num: "<<params.pts.size()<<" Object Num: "<<params.n<<" Object Type: Point."<<endl;

 94     for (int i = 0;i < params.n;i++)

 95     {

 96         vPoints.push_back(params.pts[i]);

 97     }

 98     return params.n;

 99 }

100 

101 void on_mouse(int event,int x,int y,int flags,void *param)

102 {

103     int        n;

104     static bool pressed = false;

105     static Point cur_pt;

106     static Point prev_pt;

107     /* on left button press, remember first corner of rectangle around object */

108     if (event == CV_EVENT_LBUTTONDOWN)

109     {

110         n = g_mousep->n;

111         if (n == MAX_OBJECTS)

112         {

113             return;

114         }

115         prev_pt.x = x;

116         prev_pt.y = y;

117         //cout<<prev_pt.x <<","<<prev_pt.y<<" "<<cur_pt.x<<","<<cur_pt.y<<endl;

118         pressed = true;

119     }

120     /* on left button up, finalise the rectangle and draw it in black */

121     else if(event == CV_EVENT_LBUTTONUP && pressed)

122     {

123         /* 1 == mode for selecting points */

124         if (1 == g_mousep->mode)

125         {

126             n = g_mousep->n;

127             if (n == MAX_OBJECTS)

128             {

129                 return;

130             }

131             cur_pt.x = x;

132             cur_pt.y = y;

133             g_mousep->pts.push_back(cur_pt);

134             int radius = 3;

135             circle(*g_mousep->image,cur_pt,radius,CV_RGB(255,0,0));

136             imshow(g_mousep->win_name,*g_mousep->image);

137             pressed = false;

138             g_mousep->n++;

139         }

140         /* 2 == mode for selecting rectangles */

141         else if (2 == g_mousep->mode)

142         {

143             n = g_mousep->n;

144             if (n == MAX_OBJECTS)

145             {

146                 return;

147             }

148             cur_pt.x = x;

149             cur_pt.y = y;

150             g_mousep->pts.push_back(prev_pt);

151             g_mousep->pts.push_back(cur_pt);

152         //    cout<<prev_pt.x <<","<<prev_pt.y<<" "<<cur_pt.x<<","<<cur_pt.y<<endl;

153             rectangle(*g_mousep->image,prev_pt,cur_pt,CV_RGB(0,0,255));

154             imshow(g_mousep->win_name,*g_mousep->image);

155             pressed = false;

156             g_mousep->n++;

157         }

158         else if (3 == g_mousep->mode)

159         {

160             n = g_mousep->n;

161 

162         }

163     }

164     else if (event == CV_EVENT_MOUSEMOVE && pressed && CV_EVENT_FLAG_LBUTTON)

165     {

166         if (2 == g_mousep->mode)

167         {

168             n = g_mousep->n;

169             if (n == MAX_OBJECTS)

170             {

171                 return;

172             }

173             cur_pt.x = x;

174             cur_pt.y = y;

175             Mat tmp = (*g_mousep->image).clone();

176             //cout<<prev_pt.x <<","<<prev_pt.y<<" "<<cur_pt.x<<","<<cur_pt.y<<endl;

177             rectangle(tmp,prev_pt,cur_pt,CV_RGB(0,255,0));

178             imshow(g_mousep->win_name,tmp);

179         }

180     }

181 }

复制代码

代码分析:

on_mouse()回调函数,对应于一个显示窗口。

在回调函数处理鼠标事件,要理解一个鼠标点击过程,会产生多个事件。

例如:鼠标左击,对应着CV_EVENT_LBUTTONDOWN和CV_EVENT_LBUTTONUP。 

在选择矩形框区域时,CV_EVENT_LBUTTONDOWN记录一个对角点;CV_EVENT_MOUSEMOVE记录选对矩形框的中间过程,并显示出来,便于用户调整选择的区域;CV_EVENT_LBUTTONUP记录另一个对角点,CV_EVENT_LBUTTONUP响应后,完成一个矩形框的选择。

在选择点时,只需记录CV_EVENT_LBUTTONUP事件响应的坐标。

你可能感兴趣的:(opencv)