6 int viewers_count_ = 0;
8 void slider_callback_(
int,
void* userdata) {
9 viewer& vw = *
static_cast<viewer*
>(userdata);
13 void mouse_callback_(
int event,
int x,
int y,
int,
void* userdata) {
14 viewer& vw = *
static_cast<viewer*
>(userdata);
16 vw.mouse_callback(event, x, y);
21 std::string viewer::get_window_name_(
const std::string& req_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) +
")";
31 window_name_(get_window_name_(title)),
35 cv::namedWindow(window_name_, CV_WINDOW_NORMAL | CV_WINDOW_KEEPRATIO | CV_GUI_EXPANDED);
36 cv::resizeWindow(window_name_, w, h);
38 cv::namedWindow(window_name_, CV_WINDOW_AUTOSIZE | CV_GUI_EXPANDED);
41 cv::setMouseCallback(window_name_, mouse_callback_,
this);
46 viewer(
"", w, h, resizeable) { }
50 window_name_(get_window_name_(title))
53 cv::namedWindow(window_name_, CV_WINDOW_NORMAL | CV_WINDOW_KEEPRATIO | CV_GUI_EXPANDED);
55 cv::namedWindow(window_name_, CV_WINDOW_AUTOSIZE | CV_GUI_EXPANDED);
57 cv::setMouseCallback(window_name_, mouse_callback_,
this);
62 cv::destroyWindow(window_name_);
67 return shown_image_.cols;
72 return shown_image_.rows;
77 if(width != shown_image_.cols || height != shown_image_.rows) {
79 cv::resizeWindow(window_name_, width, height);
86 clear(sz.width, sz.height);
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;
108 float alpha = 255.0f / (max_ir - min_ir);
109 float beta = -alpha * min_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));
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));
144 cv::Mat underlying_image(shown_image_, rect);
146 cv::addWeighted(resized_img, blend, underlying_image, 1.0-blend, 0.0, sum);
147 sum.copyTo(cv::Mat(shown_image_, rect));
149 resized_img.copyTo(cv::Mat(shown_image_, rect));
155 cv::Mat_<cv::Vec3b> conv_img;
156 cv::cvtColor(img, conv_img, CV_GRAY2BGR);
157 draw(rect, conv_img, blend);
162 cv::Mat_<uchar> viz_depth_img =
visualize_depth(depth_img, min_d, max_d);
163 draw(rect, viz_depth_img, blend);
168 int font = cv::FONT_HERSHEY_COMPLEX_SMALL;
169 double fontscale = 0.8;
172 cv::Size sz = cv::getTextSize(text, font, fontscale, thickness,
nullptr);
174 int y = rect.y + sz.height + (rect.height/2 - sz.height/2);
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;
180 cv::putText(shown_image_, text, cv::Point(x, y), font, fontscale, cv::Scalar(color), thickness);
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);
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);
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) });
201 cv::polylines(shown_image_, polylines,
false, cv::Scalar(
white), 5);
202 cv::polylines(shown_image_, polylines,
false, cv::Scalar(
indicator_color), 3);
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);
210 cv::Point pt1(rect.x, rect.y+rect.height);
211 cv::Point pt2(indicator_x, indicator_y);
219 cv::imshow(window_name_, shown_image_);
220 keycode = cv::waitKey(1);
231 running_modal_ =
true;
234 while(running_modal_) {
236 keycode = cv::waitKey(0);
241 void* handle = cvGetWindowHandle(window_name_.c_str());
242 if(handle ==
nullptr) running_modal_ =
false;
245 running_modal_ =
false;
252 if(! running_modal_)
return;
254 cv::imshow(window_name_, shown_image_);
259 running_modal_ =
false;
264 auto slid_ptr = std::make_unique<int_slider>(default_val, min_val, max_val, step);
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);
274 auto slid_ptr = std::make_unique<real_slider>(default_val, min_val, max_val, steps);
276 sliders_.emplace_back(std::move(slid_ptr));
277 cv::createTrackbar(caption, window_name_, &slid.raw_value, slid.slider_max(), &slider_callback_,
this);
288 min(min_), max(max_), step(step_) {
set_value(value_); }
real_slider & add_real_slider(const std::string &caption, real default_val, real min_val, real max_val, int steps=100)
std::function< void(int keycode)> key_callback
static cv::Mat_< uchar > visualize_depth(const cv::Mat &, float min_d, float max_d)
void draw_2d_cross_indicator(cv::Rect rect, real value_x, real value_y, real max_abs_value)
void draw(const cv::Mat_< cv::Vec3b > &, real blend=1.0)
cv::Vec3b indicator_color
cv::Vec3b background_color
int_slider(int value_, int min_, int max_, int step_)
constexpr int escape_keycode
void draw_depth(cv::Rect rect, const cv::Mat_< float > &depth_img, float min_d, float max_d, real blend=1.0)
void draw_2d_arrow_indicator(cv::Rect rect, real value_x, real value_y, real max_value)
viewer(const std::string &title, int width, int height, bool resizeable=false)
std::string to_string(const T &)
void draw_text(cv::Rect rect, const std::string &text, text_alignment=left)
int_slider & add_int_slider(const std::string &caption, int default_val, int min_val, int max_val, int step=1)
static cv::Mat_< uchar > visualize_ir(const cv::Mat &, float min_ir, float max_ir)
real_slider(real value_, real min_, real max_, int steps_)
std::function< void()> update_callback