licornea_tools
viewer.cc
Go to the documentation of this file.
1 #include "viewer.h"
2 
3 namespace tlz {
4 
5 namespace {
6  int viewers_count_ = 0;
7 
8  void slider_callback_(int, void* userdata) {
9  viewer& vw = *static_cast<viewer*>(userdata);
10  vw.update_modal();
11  }
12 
13  void mouse_callback_(int event, int x, int y, int, void* userdata) {
14  viewer& vw = *static_cast<viewer*>(userdata);
15  if(vw.mouse_callback)
16  vw.mouse_callback(event, x, y); // TODO window size?
17  }
18 }
19 
20 
21 std::string viewer::get_window_name_(const std::string& req_title) {
22  std::string title;
23  if(req_title.empty()) title = "Viewer";
24  else title = req_title;
25  if(viewers_count_ > 0) title += " (" + std::to_string(viewers_count_ + 1) + ")";
26  viewers_count_++;
27  return title;
28 }
29 
30 viewer::viewer(const std::string& title, int w, int h, bool resizeable) :
31  window_name_(get_window_name_(title)),
32  shown_image_(h, w)
33 {
34  if(resizeable) {
35  cv::namedWindow(window_name_, CV_WINDOW_NORMAL | CV_WINDOW_KEEPRATIO | CV_GUI_EXPANDED);
36  cv::resizeWindow(window_name_, w, h);
37  } else {
38  cv::namedWindow(window_name_, CV_WINDOW_AUTOSIZE | CV_GUI_EXPANDED);
39  }
40 
41  cv::setMouseCallback(window_name_, mouse_callback_, this);
42 }
43 
44 
45 viewer::viewer(int w, int h, bool resizeable) :
46  viewer("", w, h, resizeable) { }
47 
48 
49 viewer::viewer(const std::string& title, bool resizeable) :
50  window_name_(get_window_name_(title))
51 {
52  if(resizeable)
53  cv::namedWindow(window_name_, CV_WINDOW_NORMAL | CV_WINDOW_KEEPRATIO | CV_GUI_EXPANDED);
54  else
55  cv::namedWindow(window_name_, CV_WINDOW_AUTOSIZE | CV_GUI_EXPANDED);
56 
57  cv::setMouseCallback(window_name_, mouse_callback_, this);
58 }
59 
60 
62  cv::destroyWindow(window_name_);
63 }
64 
65 
66 int viewer::width() const {
67  return shown_image_.cols;
68 }
69 
70 
71 int viewer::height() const {
72  return shown_image_.rows;
73 }
74 
75 
76 void viewer::clear(int width, int height) {
77  if(width != shown_image_.cols || height != shown_image_.rows) {
78  shown_image_ = cv::Mat_<cv::Vec3b>(height, width, background_color);
79  cv::resizeWindow(window_name_, width, height);
80  } else {
81  shown_image_.setTo(background_color);
82  }
83 }
84 
85 void viewer::clear(cv::Size sz) {
86  clear(sz.width, sz.height);
87 }
88 
89 
90 void viewer::clear() {
91  shown_image_.setTo(background_color);
92 }
93 
94 
95 cv::Mat_<uchar> viewer::visualize_depth(const cv::Mat& depth_img, float min_d, float max_d) {
96  cv::Mat_<uchar> viz_depth_img;
97  float alpha = 255.0f / (max_d - min_d);
98  float beta = -alpha * min_d;
99  cv::convertScaleAbs(depth_img, viz_depth_img, alpha, beta);
100  viz_depth_img.setTo(0, (depth_img < min_d));
101  viz_depth_img.setTo(255, (depth_img > max_d));
102  viz_depth_img.setTo(0, (depth_img == 0));
103  return viz_depth_img;
104 }
105 
106 
107 cv::Mat_<uchar> viewer::visualize_ir(const cv::Mat& ir_orig, float min_ir, float max_ir) {
108  float alpha = 255.0f / (max_ir - min_ir);
109  float beta = -alpha * min_ir;
110  cv::Mat_<uchar> ir;
111  cv::convertScaleAbs(ir_orig, ir, alpha, beta);
112  ir.setTo(0, (ir_orig < min_ir));
113  ir.setTo(255, (ir_orig > max_ir));
114  ir.setTo(0, (ir_orig == 0));
115  return ir;
116 }
117 
118 
119 void viewer::draw(const cv::Mat_<cv::Vec3b>& img, real blend) {
120  draw(cv::Rect(0, 0, width(), height()), img, blend);
121 }
122 
123 
124 void viewer::draw(const cv::Mat_<uchar>& img, real blend) {
125  draw(cv::Rect(0, 0, width(), height()), img, blend);
126 }
127 
128 
129 
130 void viewer::draw(cv::Rect rect, const cv::Mat_<cv::Vec3b>& img, real blend) {
131  cv::Mat resized_img;
132  float ratio = (float)img.rows / img.cols;
133  float h1 = rect.width * ratio;
134  float w2 = rect.height / ratio;
135  if(h1 < rect.height) cv::resize(img, resized_img, cv::Size(rect.width, h1));
136  else cv::resize(img, resized_img, cv::Size(w2, rect.height));
137  int top = (rect.height - resized_img.rows) / 2;
138  int down = (rect.height - resized_img.rows + 1) / 2;
139  int left = (rect.width - resized_img.cols) / 2;
140  int right = (rect.width - resized_img.cols + 1) / 2;
141  cv::copyMakeBorder(resized_img, resized_img, top, down, left, right, cv::BORDER_CONSTANT, cv::Scalar(background_color));
142 
143  if(blend < 1.0) {
144  cv::Mat underlying_image(shown_image_, rect);
145  cv::Mat sum;
146  cv::addWeighted(resized_img, blend, underlying_image, 1.0-blend, 0.0, sum);
147  sum.copyTo(cv::Mat(shown_image_, rect));
148  } else {
149  resized_img.copyTo(cv::Mat(shown_image_, rect));
150  }
151 }
152 
153 
154 void viewer::draw(cv::Rect rect, const cv::Mat_<uchar>& img, real blend) {
155  cv::Mat_<cv::Vec3b> conv_img;
156  cv::cvtColor(img, conv_img, CV_GRAY2BGR);
157  draw(rect, conv_img, blend);
158 }
159 
160 
161 void viewer::draw_depth(cv::Rect rect, const cv::Mat_<float>& depth_img, float min_d, float max_d, real blend) {
162  cv::Mat_<uchar> viz_depth_img = visualize_depth(depth_img, min_d, max_d);
163  draw(rect, viz_depth_img, blend);
164 }
165 
166 
167 void viewer::draw_text(cv::Rect rect, const std::string& text, text_alignment align, cv::Vec3b color) {
168  int font = cv::FONT_HERSHEY_COMPLEX_SMALL;
169  double fontscale = 0.8;
170  int thickness = 1;
171 
172  cv::Size sz = cv::getTextSize(text, font, fontscale, thickness, nullptr);
173 
174  int y = rect.y + sz.height + (rect.height/2 - sz.height/2);
175  int x;
176  if(align == left) x = rect.x;
177  else if(align == center) x = rect.x + (rect.width/2 - sz.width/2);
178  else x = rect.x + rect.width - sz.width;
179 
180  cv::putText(shown_image_, text, cv::Point(x, y), font, fontscale, cv::Scalar(color), thickness);
181 }
182 void viewer::draw_text(cv::Rect rect, const std::string& text, text_alignment align) {
183  draw_text(rect, text, align, text_color);
184 }
185 
186 void viewer::draw_2d_cross_indicator(cv::Rect rect, real value_x, real value_y, real max_abs_value) {
187  std::vector<std::vector<cv::Point>> polylines;
188  polylines.push_back({ cv::Point(rect.x+rect.width/2, rect.y), cv::Point(rect.x+rect.width/2, rect.y+rect.height) });
189  polylines.push_back({ cv::Point(rect.x, rect.y+rect.height/2), cv::Point(rect.x+rect.width, rect.y+rect.height/2) });
190  cv::polylines(shown_image_, polylines, false, cv::Scalar(black), 3);
191  cv::polylines(shown_image_, polylines, false, cv::Scalar(white), 1);
192 
193 
194  const int indicator_rad = 20;
195  int indicator_x = (rect.x+rect.width/2) + value_x * 0.5 * (rect.width / max_abs_value);
196  int indicator_y = (rect.y+rect.height/2) + value_y * 0.5 * (rect.height / max_abs_value);
197  polylines.clear();
198  polylines.push_back({ cv::Point(indicator_x-indicator_rad, indicator_y), cv::Point(indicator_x+indicator_rad, indicator_y) });
199  polylines.push_back({ cv::Point(indicator_x, indicator_y-indicator_rad), cv::Point(indicator_x, indicator_y+indicator_rad) });
200 
201  cv::polylines(shown_image_, polylines, false, cv::Scalar(white), 5);
202  cv::polylines(shown_image_, polylines, false, cv::Scalar(indicator_color), 3);
203 }
204 
205 
206 void viewer::draw_2d_arrow_indicator(cv::Rect rect, real value_x, real value_y, real max_value) {
207  int indicator_x = (rect.x) + value_x * (rect.width / max_value);
208  int indicator_y = (rect.y+rect.height) - value_y * (rect.height / max_value);
209 
210  cv::Point pt1(rect.x, rect.y+rect.height);
211  cv::Point pt2(indicator_x, indicator_y);
212  cv::line(shown_image_, pt1, pt2, cv::Scalar(indicator_color), 3);
213  cv::circle(shown_image_, pt2, 4, cv::Scalar(indicator_color), -1);
214 }
215 
216 
217 
218 bool viewer::show(int& keycode) {
219  cv::imshow(window_name_, shown_image_);
220  keycode = cv::waitKey(1);
221  if(keycode == escape_keycode) return false;
222  else return true;
223 }
224 bool viewer::show() {
225  int unused;
226  return show(unused);
227 }
228 
229 
231  running_modal_ = true;
232  try {
233  int keycode = 0;
234  while(running_modal_) {
235  update_modal();
236  keycode = cv::waitKey(0);
237 
238  if(keycode == escape_keycode) running_modal_ = false;
239  else if(keycode > 0 && key_callback) key_callback(keycode);
240 
241  void* handle = cvGetWindowHandle(window_name_.c_str());
242  if(handle == nullptr) running_modal_ = false;
243  }
244  } catch(...) {
245  running_modal_ = false;
246  throw;
247  }
248 }
249 
250 
252  if(! running_modal_) return;
254  cv::imshow(window_name_, shown_image_);
255 }
256 
257 
259  running_modal_ = false;
260 }
261 
262 
263 viewer::int_slider& viewer::add_int_slider(const std::string& caption, int default_val, int min_val, int max_val, int step) {
264  auto slid_ptr = std::make_unique<int_slider>(default_val, min_val, max_val, step);
265  int_slider& slid = *slid_ptr;
266  sliders_.emplace_back(std::move(slid_ptr));
267  bool no_slider = (min_val == max_val);
268  if(! no_slider) cv::createTrackbar(caption, window_name_, &slid.raw_value, slid.slider_max(), &slider_callback_, this);
269  return slid;
270 }
271 
272 
273 viewer::real_slider& viewer::add_real_slider(const std::string& caption, real default_val, real min_val, real max_val, int steps) {
274  auto slid_ptr = std::make_unique<real_slider>(default_val, min_val, max_val, steps);
275  real_slider& slid = *slid_ptr;
276  sliders_.emplace_back(std::move(slid_ptr));
277  cv::createTrackbar(caption, window_name_, &slid.raw_value, slid.slider_max(), &slider_callback_, this);
278  return slid;
279 }
280 
281 
282 
283 
285 
286 
287 viewer::int_slider::int_slider(int value_, int min_, int max_, int step_) :
288  min(min_), max(max_), step(step_) { set_value(value_); }
289 
291  return (max - min) / step;
292 }
293 
295  return min + step*raw_value;
296 }
297 
299  raw_value = (val - min)/step;
300 }
301 
302 
303 
304 viewer::real_slider::real_slider(real value_, real min_, real max_, int steps_) :
305  min(min_), max(max_), steps(steps_) { set_value(value_); }
306 
308  return steps;
309 }
310 
312  real range = max - min;
313  return min + raw_value*range/steps;
314 }
315 
317  real range = max - min;
318  raw_value = steps * (val - min)/range;
319 }
320 
321 
322 
323 }
real_slider & add_real_slider(const std::string &caption, real default_val, real min_val, real max_val, int steps=100)
Definition: viewer.cc:273
std::function< void(int keycode)> key_callback
Definition: viewer.h:41
void close_modal()
Definition: viewer.cc:258
cv::Vec3b white
Definition: viewer.h:35
static cv::Mat_< uchar > visualize_depth(const cv::Mat &, float min_d, float max_d)
Definition: viewer.cc:95
int slider_max() const
Definition: viewer.cc:307
void draw_2d_cross_indicator(cv::Rect rect, real value_x, real value_y, real max_abs_value)
Definition: viewer.cc:186
void draw(const cv::Mat_< cv::Vec3b > &, real blend=1.0)
Definition: viewer.cc:119
void show_modal()
Definition: viewer.cc:230
text_alignment
Definition: viewer.h:19
real value() const
Definition: viewer.cc:311
cv::Vec3b indicator_color
Definition: viewer.h:36
cv::Vec3b background_color
Definition: viewer.h:37
int_slider(int value_, int min_, int max_, int step_)
Definition: viewer.cc:287
cv::Vec3b black
Definition: viewer.h:34
bool show()
Definition: viewer.cc:224
constexpr int escape_keycode
Definition: common.h:74
double real
Definition: common.h:16
void clear()
Definition: viewer.cc:90
void draw_depth(cv::Rect rect, const cv::Mat_< float > &depth_img, float min_d, float max_d, real blend=1.0)
Definition: viewer.cc:161
int height() const
Definition: viewer.cc:71
cv::Vec3b text_color
Definition: viewer.h:38
void set_value(real val)
Definition: viewer.cc:316
void draw_2d_arrow_indicator(cv::Rect rect, real value_x, real value_y, real max_value)
Definition: viewer.cc:206
viewer(const std::string &title, int width, int height, bool resizeable=false)
Definition: viewer.cc:30
void update_modal()
Definition: viewer.cc:251
std::string to_string(const T &)
void set_value(int val)
Definition: viewer.cc:298
void draw_text(cv::Rect rect, const std::string &text, text_alignment=left)
Definition: viewer.cc:182
int_slider & add_int_slider(const std::string &caption, int default_val, int min_val, int max_val, int step=1)
Definition: viewer.cc:263
int value() const
Definition: viewer.cc:294
static cv::Mat_< uchar > visualize_ir(const cv::Mat &, float min_ir, float max_ir)
Definition: viewer.cc:107
real_slider(real value_, real min_, real max_, int steps_)
Definition: viewer.cc:304
int width() const
Definition: viewer.cc:66
std::function< void()> update_callback
Definition: viewer.h:40
int slider_max() const
Definition: viewer.cc:290