5 #include <visp3/core/vpConfig.h>
7 #if defined(HAVE_OPENCV_HIGHGUI) && defined(VISP_HAVE_X11)
10 #include <opencv2/highgui.hpp>
12 #include <visp3/core/vpArray2D.h>
13 #include <visp3/core/vpImageConvert.h>
14 #include <visp3/core/vpImageTools.h>
15 #include <visp3/core/vpIoTools.h>
16 #include <visp3/gui/vpDisplayX.h>
17 #include <visp3/io/vpImageIo.h>
18 #include <visp3/sensor/vpRealSense2.h>
20 std::vector<int> hsv_values_trackbar(6);
21 const cv::String window_detection_name =
"Object Detection";
23 void set_trackbar_H_min(
int val)
25 cv::setTrackbarPos(
"Low H", window_detection_name, val);
27 void set_trackbar_H_max(
int val)
29 cv::setTrackbarPos(
"High H", window_detection_name, val);
31 void set_trackbar_S_min(
int val)
33 cv::setTrackbarPos(
"Low S", window_detection_name, val);
35 void set_trackbar_S_max(
int val)
37 cv::setTrackbarPos(
"High S", window_detection_name, val);
39 void set_trackbar_V_min(
int val)
41 cv::setTrackbarPos(
"Low V", window_detection_name, val);
43 void set_trackbar_V_max(
int val)
45 cv::setTrackbarPos(
"High V", window_detection_name, val);
47 static void on_low_H_thresh_trackbar(
int,
void *)
49 hsv_values_trackbar[0] = std::min(hsv_values_trackbar[1]-1, hsv_values_trackbar[0]);
50 set_trackbar_H_min(hsv_values_trackbar[0]);
52 static void on_high_H_thresh_trackbar(
int,
void *)
54 hsv_values_trackbar[1] = std::max(hsv_values_trackbar[1], hsv_values_trackbar[0]+1);
55 set_trackbar_H_max(hsv_values_trackbar[1]);
57 static void on_low_S_thresh_trackbar(
int,
void *)
59 hsv_values_trackbar[2] = std::min(hsv_values_trackbar[3]-1, hsv_values_trackbar[2]);
60 set_trackbar_S_min(hsv_values_trackbar[2]);
62 static void on_high_S_thresh_trackbar(
int,
void *)
64 hsv_values_trackbar[3] = std::max(hsv_values_trackbar[3], hsv_values_trackbar[2]+1);
65 set_trackbar_S_max(hsv_values_trackbar[3]);
67 static void on_low_V_thresh_trackbar(
int,
void *)
69 hsv_values_trackbar[4] = std::min(hsv_values_trackbar[5]-1, hsv_values_trackbar[4]);
70 set_trackbar_V_min(hsv_values_trackbar[4]);
72 static void on_high_V_thresh_trackbar(
int,
void *)
74 hsv_values_trackbar[5] = std::max(hsv_values_trackbar[5], hsv_values_trackbar[4]+1);
75 set_trackbar_V_max(hsv_values_trackbar[5]);
78 int main(
int argc,
const char *argv[])
80 #ifdef ENABLE_VISP_NAMESPACE
84 bool opt_save_img =
false;
85 std::string opt_hsv_filename =
"calib/hsv-thresholds.yml";
86 std::string opt_img_filename;
87 bool show_helper =
false;
88 for (
int i = 1; i < argc; i++) {
89 if ((std::string(argv[i]) ==
"--hsv-thresholds") && ((i+1) < argc)) {
90 opt_hsv_filename = std::string(argv[++i]);
92 else if (std::string(argv[i]) ==
"--image") {
94 opt_img_filename = std::string(argv[++i]);
98 std::cout <<
"ERROR \nMissing input image name after parameter " << std::string(argv[i]) << std::endl;
101 else if (std::string(argv[i]) ==
"--save-img") {
104 if (show_helper || std::string(argv[i]) ==
"--help" || std::string(argv[i]) ==
"-h") {
105 std::cout <<
"\nSYNOPSIS " << std::endl
107 <<
" [--image <input image>]"
108 <<
" [--hsv-thresholds <output filename.yml>]"
112 std::cout <<
"\nOPTIONS " << std::endl
113 <<
" --image <input image>" << std::endl
114 <<
" Name of the input image filename." << std::endl
115 <<
" When this option is not set, we use librealsense to stream images from a Realsense camera. " << std::endl
116 <<
" Example: --image ballons.jpg" << std::endl
118 <<
" --hsv-thresholds <output filename.yml>" << std::endl
119 <<
" Name of the output filename with yaml extension that will contain HSV low/high thresholds." << std::endl
120 <<
" Default: " << opt_hsv_filename << std::endl
122 <<
" --save-img" << std::endl
123 <<
" Enable RGB, HSV and segmented image saving" << std::endl
125 <<
" --help, -h" << std::endl
126 <<
" Display this helper message." << std::endl
132 bool use_realsense =
false;
133 #if defined(VISP_HAVE_REALSENSE2)
134 use_realsense =
true;
137 if (!opt_img_filename.empty()) {
138 use_realsense =
false;
141 else if (opt_img_filename.empty()) {
142 std::cout <<
"Error: you should use --image <input image> option to specify an input image..." << std::endl;
146 int max_value_H = 255;
149 hsv_values_trackbar[0] = 0;
150 hsv_values_trackbar[1] = max_value_H;
151 hsv_values_trackbar[2] = 0;
152 hsv_values_trackbar[3] = max_value;
153 hsv_values_trackbar[4] = 0;
154 hsv_values_trackbar[5] = max_value;
159 #if defined(VISP_HAVE_REALSENSE2)
164 #if defined(VISP_HAVE_REALSENSE2)
165 width = 848; height = 480;
168 config.enable_stream(RS2_STREAM_COLOR, width, height, RS2_FORMAT_RGBA8, fps);
169 config.disable_stream(RS2_STREAM_DEPTH);
170 config.disable_stream(RS2_STREAM_INFRARED, 1);
171 config.disable_stream(RS2_STREAM_INFRARED, 2);
188 cv::namedWindow(window_detection_name);
190 vpArray2D<int> hsv_values(hsv_values_trackbar, hsv_values_trackbar.size(), 1);
193 std::cout <<
"Load hsv values from " << opt_hsv_filename <<
" previous tuning " << std::endl;
194 std::cout << hsv_values.
t() << std::endl;
195 hsv_values_prev = hsv_values;
196 for (
size_t i = 0; i < hsv_values.size(); ++i) {
197 hsv_values_trackbar[i] = hsv_values.
data[i];
202 cv::createTrackbar(
"Low H", window_detection_name, &hsv_values_trackbar[0], max_value_H, on_low_H_thresh_trackbar);
203 cv::createTrackbar(
"High H", window_detection_name, &hsv_values_trackbar[1], max_value_H, on_high_H_thresh_trackbar);
204 cv::createTrackbar(
"Low S", window_detection_name, &hsv_values_trackbar[2], max_value, on_low_S_thresh_trackbar);
205 cv::createTrackbar(
"High S", window_detection_name, &hsv_values_trackbar[3], max_value, on_high_S_thresh_trackbar);
206 cv::createTrackbar(
"Low V", window_detection_name, &hsv_values_trackbar[4], max_value, on_low_V_thresh_trackbar);
207 cv::createTrackbar(
"High V", window_detection_name, &hsv_values_trackbar[5], max_value, on_high_V_thresh_trackbar);
215 vpDisplayX d_I(I, 0, 0,
"Current frame");
216 vpDisplayX d_I_segmented(I_segmented, I.
getWidth()+75, 0,
"Segmented frame");
221 #if defined(VISP_HAVE_REALSENSE2)
229 reinterpret_cast<unsigned char *
>(H.bitmap),
230 reinterpret_cast<unsigned char *
>(S.bitmap),
231 reinterpret_cast<unsigned char *
>(V.bitmap), I.
getSize());
234 reinterpret_cast<unsigned char *
>(S.bitmap),
235 reinterpret_cast<unsigned char *
>(V.bitmap),
237 reinterpret_cast<unsigned char *
>(mask.bitmap),
254 unsigned int i = ip.
get_i();
255 unsigned int j = ip.
get_j();
256 int h =
static_cast<int>(H[i][j]);
257 int s =
static_cast<int>(S[i][j]);
258 int v =
static_cast<int>(V[i][j]);
259 std::cout <<
"RGB[" << i <<
"][" << j <<
"]: " <<
static_cast<int>(I[i][j].R) <<
" " <<
static_cast<int>(I[i][j].G)
260 <<
" " <<
static_cast<int>(I[i][j].B) <<
" -> HSV: " << h <<
" " << s <<
" " << v << std::endl;
263 unsigned int i = ip.
get_i();
264 unsigned int j = ip.
get_j();
265 int h =
static_cast<int>(H[i][j]);
266 int s =
static_cast<int>(S[i][j]);
267 int v =
static_cast<int>(V[i][j]);
269 hsv_values_trackbar[0] = std::max(0, h - offset);
270 hsv_values_trackbar[1] = std::min(max_value_H, h + offset);
271 hsv_values_trackbar[2] = std::max(0, s - offset);
272 hsv_values_trackbar[3] = std::min(max_value, s + offset);
273 hsv_values_trackbar[4] = std::max(0, v - offset);
274 hsv_values_trackbar[5] = std::min(max_value, v + offset);
275 std::cout <<
"HSV learned: " << h <<
" " << s <<
" " << v << std::endl;
276 set_trackbar_H_min(hsv_values_trackbar[0]);
277 set_trackbar_H_max(hsv_values_trackbar[1]);
278 set_trackbar_S_min(hsv_values_trackbar[2]);
279 set_trackbar_S_max(hsv_values_trackbar[3]);
280 set_trackbar_V_min(hsv_values_trackbar[4]);
281 set_trackbar_V_max(hsv_values_trackbar[5]);
287 std::cout <<
"Create directory: " << parent << std::endl;
291 vpArray2D<int> hsv_values_new(hsv_values_trackbar, hsv_values_trackbar.size(), 1);
292 if (hsv_values_new != hsv_values_prev) {
294 std::string hsv_filename_backup(opt_hsv_filename + std::string(
".previous"));
295 std::cout <<
"Create a backup of the previous calibration in " << hsv_filename_backup << std::endl;
299 std::cout <<
"Save new calibration in: " << opt_hsv_filename << std::endl;
304 std::string path_img(parent +
"/images-visp");
306 std::cout <<
"Create directory: " << path_img << std::endl;
310 std::cout <<
"Save images in path_img folder..." << std::endl;
329 #if !defined(HAVE_OPENCV_HIGHGUI)
330 std::cout <<
"This tutorial needs OpenCV highgui module as 3rd party." << std::endl;
332 #if !defined(VISP_HAVE_X11)
333 std::cout <<
"This tutorial needs X11 3rd party enabled." << std::endl;
335 std::cout <<
"Install missing 3rd parties, configure and rebuild ViSP." << std::endl;
Implementation of a generic 2D array used as base class for matrices and vectors.
Type * data
Address of the first element of the data array.
static bool saveYAML(const std::string &filename, const vpArray2D< Type > &A, const char *header="")
vpArray2D< Type > t() const
Compute the transpose of the array.
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void display(const vpImage< unsigned char > &I)
static void flush(const vpImage< unsigned char > &I)
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
error that can be emitted by ViSP classes.
const std::string & getStringMessage() const
static void merge(const vpImage< unsigned char > *R, const vpImage< unsigned char > *G, const vpImage< unsigned char > *B, const vpImage< unsigned char > *a, vpImage< vpRGBa > &RGBa)
static void RGBaToHSV(const unsigned char *rgba, double *hue, double *saturation, double *value, unsigned int size)
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
static void write(const vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
unsigned int getWidth() const
unsigned int getSize() const
Type * bitmap
points toward the bitmap
unsigned int getHeight() const
void acquire(vpImage< unsigned char > &grey, double *ts=nullptr)
bool open(const rs2::config &cfg=rs2::config())
VISP_EXPORT std::string getDateTime(const std::string &format="%Y/%m/%d %H:%M:%S")