Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/highgui/src/roiSelector.cpp
16337 views
1
// This file is part of OpenCV project.
2
// It is subject to the license terms in the LICENSE file found in the top-level directory
3
// of this distribution and at http://opencv.org/license.html.
4
5
#include "precomp.hpp"
6
#include <opencv2/imgproc.hpp>
7
#include <algorithm>
8
9
using namespace cv;
10
11
namespace
12
{
13
class ROISelector
14
{
15
public:
16
Rect select(const String &windowName, Mat img, bool showCrossair = true, bool fromCenter = true)
17
{
18
// show notice to user
19
printf("Select a ROI and then press SPACE or ENTER button!\n");
20
printf("Cancel the selection process by pressing c button!\n");
21
22
key = 0;
23
imageSize = img.size();
24
25
// set the drawing mode
26
selectorParams.drawFromCenter = fromCenter;
27
28
// show the image and give feedback to user
29
imshow(windowName, img);
30
31
// copy the data, rectangle should be drawn in the fresh image
32
selectorParams.image = img.clone();
33
34
// select the object
35
setMouseCallback(windowName, mouseHandler, (void*)this);
36
37
// end selection process on SPACE (32) ESC (27) or ENTER (13)
38
while (!(key == 32 || key == 27 || key == 13))
39
{
40
// draw the selected object
41
rectangle(selectorParams.image, selectorParams.box, Scalar(255, 0, 0), 2, 1);
42
43
// draw cross air in the middle of bounding box
44
if (showCrossair)
45
{
46
// horizontal line
47
line(selectorParams.image,
48
Point((int)selectorParams.box.x,
49
(int)(selectorParams.box.y + selectorParams.box.height / 2)),
50
Point((int)(selectorParams.box.x + selectorParams.box.width),
51
(int)(selectorParams.box.y + selectorParams.box.height / 2)),
52
Scalar(255, 0, 0), 2, 1);
53
54
// vertical line
55
line(selectorParams.image,
56
Point((int)(selectorParams.box.x + selectorParams.box.width / 2),
57
(int)selectorParams.box.y),
58
Point((int)(selectorParams.box.x + selectorParams.box.width / 2),
59
(int)(selectorParams.box.y + selectorParams.box.height)),
60
Scalar(255, 0, 0), 2, 1);
61
}
62
63
// show the image bounding box
64
imshow(windowName, selectorParams.image);
65
66
// reset the image
67
selectorParams.image = img.clone();
68
69
// get keyboard event
70
key = waitKey(30);
71
72
if (key == 'c' || key == 'C')//cancel selection
73
{
74
selectorParams.box = Rect();
75
break;
76
}
77
}
78
79
//cleanup callback
80
setMouseCallback(windowName, emptyMouseHandler, NULL);
81
82
return selectorParams.box;
83
}
84
85
void select(const String &windowName, Mat img, std::vector<Rect> &boundingBoxes,
86
bool showCrosshair = true, bool fromCenter = true)
87
{
88
printf("Finish the selection process by pressing ESC button!\n");
89
boundingBoxes.clear();
90
key = 0;
91
92
// while key is not ESC (27)
93
for (;;)
94
{
95
Rect temp = select(windowName, img, showCrosshair, fromCenter);
96
if (key == 27)
97
break;
98
if (temp.width > 0 && temp.height > 0)
99
boundingBoxes.push_back(temp);
100
}
101
}
102
103
struct handlerT
104
{
105
// basic parameters
106
bool isDrawing;
107
Rect2d box;
108
Mat image;
109
110
// parameters for drawing from the center
111
bool drawFromCenter;
112
Point2f center;
113
114
// initializer list
115
handlerT() : isDrawing(false), drawFromCenter(true){};
116
} selectorParams;
117
118
private:
119
static void emptyMouseHandler(int, int, int, int, void*)
120
{
121
}
122
123
static void mouseHandler(int event, int x, int y, int flags, void *param)
124
{
125
ROISelector *self = static_cast<ROISelector *>(param);
126
self->opencv_mouse_callback(event, x, y, flags);
127
}
128
129
void opencv_mouse_callback(int event, int x, int y, int)
130
{
131
switch (event)
132
{
133
// update the selected bounding box
134
case EVENT_MOUSEMOVE:
135
if (selectorParams.isDrawing)
136
{
137
if (selectorParams.drawFromCenter)
138
{
139
selectorParams.box.width = 2 * (x - selectorParams.center.x);
140
selectorParams.box.height = 2 * (y - selectorParams.center.y);
141
selectorParams.box.x = std::min(
142
std::max(selectorParams.center.x - selectorParams.box.width / 2.0, 0.), (double)imageSize.width);
143
selectorParams.box.y = std::min(
144
std::max(selectorParams.center.y - selectorParams.box.height / 2.0, 0.), (double)imageSize.height);
145
}
146
else
147
{
148
selectorParams.box.width = std::max(
149
std::min(x - selectorParams.box.x, (double)imageSize.width - selectorParams.box.x), - selectorParams.box.x);
150
selectorParams.box.height = std::max(
151
std::min(y - selectorParams.box.y, (double)imageSize.height - selectorParams.box.y), - selectorParams.box.y);
152
}
153
}
154
break;
155
156
// start to select the bounding box
157
case EVENT_LBUTTONDOWN:
158
selectorParams.isDrawing = true;
159
selectorParams.box = Rect2d(x, y, 0, 0);
160
selectorParams.center = Point2f((float)x, (float)y);
161
break;
162
163
// cleaning up the selected bounding box
164
case EVENT_LBUTTONUP:
165
selectorParams.isDrawing = false;
166
if (selectorParams.box.width < 0)
167
{
168
selectorParams.box.x += selectorParams.box.width;
169
selectorParams.box.width *= -1;
170
}
171
if (selectorParams.box.height < 0)
172
{
173
selectorParams.box.y += selectorParams.box.height;
174
selectorParams.box.height *= -1;
175
}
176
break;
177
}
178
}
179
180
// save the keypressed character
181
int key;
182
Size imageSize;
183
};
184
}
185
186
Rect cv::selectROI(InputArray img, bool showCrosshair, bool fromCenter)
187
{
188
ROISelector selector;
189
return selector.select("ROI selector", img.getMat(), showCrosshair, fromCenter);
190
}
191
192
Rect cv::selectROI(const String& windowName, InputArray img, bool showCrosshair, bool fromCenter)
193
{
194
ROISelector selector;
195
return selector.select(windowName, img.getMat(), showCrosshair, fromCenter);
196
}
197
198
void cv::selectROIs(const String& windowName, InputArray img,
199
std::vector<Rect>& boundingBox, bool showCrosshair, bool fromCenter)
200
{
201
ROISelector selector;
202
selector.select(windowName, img.getMat(), boundingBox, showCrosshair, fromCenter);
203
}
204
205