5#include <visp3/core/vpConfig.h>
7#if defined(HAVE_OPENCV_HIGHGUI) && defined(VISP_HAVE_DISPLAY)
10#include <opencv2/highgui/highgui.hpp>
12#include <visp3/core/vpArray2D.h>
13#include <visp3/core/vpHSV.h>
14#include <visp3/core/vpImageConvert.h>
15#include <visp3/core/vpImageTools.h>
16#include <visp3/core/vpIoTools.h>
17#include <visp3/gui/vpDisplayFactory.h>
18#include <visp3/io/vpImageIo.h>
19#include <visp3/sensor/vpRealSense2.h>
21VP_ATTRIBUTE_NO_DESTROY std::vector<int> hsv_values_trackbar(6);
22VP_ATTRIBUTE_NO_DESTROY
const cv::String window_detection_name =
"Object Detection";
24void set_trackbar_H_min(
int val)
26 cv::setTrackbarPos(
"Low H", window_detection_name, val);
28void set_trackbar_H_max(
int val)
30 cv::setTrackbarPos(
"High H", window_detection_name, val);
32void set_trackbar_S_min(
int val)
34 cv::setTrackbarPos(
"Low S", window_detection_name, val);
36void set_trackbar_S_max(
int val)
38 cv::setTrackbarPos(
"High S", window_detection_name, val);
40void set_trackbar_V_min(
int val)
42 cv::setTrackbarPos(
"Low V", window_detection_name, val);
44void set_trackbar_V_max(
int val)
46 cv::setTrackbarPos(
"High V", window_detection_name, val);
48static void on_low_H_thresh_trackbar(
int,
void *)
50 hsv_values_trackbar[0] = std::min(hsv_values_trackbar[1]-1, hsv_values_trackbar[0]);
51 set_trackbar_H_min(hsv_values_trackbar[0]);
53static void on_high_H_thresh_trackbar(
int,
void *)
55 hsv_values_trackbar[1] = std::max(hsv_values_trackbar[1], hsv_values_trackbar[0]+1);
56 set_trackbar_H_max(hsv_values_trackbar[1]);
58static void on_low_S_thresh_trackbar(
int,
void *)
60 hsv_values_trackbar[2] = std::min(hsv_values_trackbar[3]-1, hsv_values_trackbar[2]);
61 set_trackbar_S_min(hsv_values_trackbar[2]);
63static void on_high_S_thresh_trackbar(
int,
void *)
65 hsv_values_trackbar[3] = std::max(hsv_values_trackbar[3], hsv_values_trackbar[2]+1);
66 set_trackbar_S_max(hsv_values_trackbar[3]);
68static void on_low_V_thresh_trackbar(
int,
void *)
70 hsv_values_trackbar[4] = std::min(hsv_values_trackbar[5]-1, hsv_values_trackbar[4]);
71 set_trackbar_V_min(hsv_values_trackbar[4]);
73static void on_high_V_thresh_trackbar(
int,
void *)
75 hsv_values_trackbar[5] = std::max(hsv_values_trackbar[5], hsv_values_trackbar[4]+1);
76 set_trackbar_V_max(hsv_values_trackbar[5]);
79int main(
int argc,
const char *argv[])
81#ifdef ENABLE_VISP_NAMESPACE
85 bool opt_save_img =
false;
86 std::string opt_hsv_filename =
"calib/hsv-thresholds.yml";
87 std::string opt_img_filename;
88 bool show_helper =
false;
89 for (
int i = 1;
i < argc;
i++) {
90 if ((std::string(argv[i]) ==
"--hsv-thresholds") && ((i+1) < argc)) {
91 opt_hsv_filename = std::string(argv[++i]);
93 else if ((std::string(argv[i]) ==
"--image") && ((i+1) < argc)) {
94 opt_img_filename = std::string(argv[++i]);
96 else if (std::string(argv[i]) ==
"--save-img") {
99 if (show_helper || std::string(argv[i]) ==
"--help" || std::string(argv[i]) ==
"-h") {
100 std::cout <<
"\nSYNOPSIS " << std::endl
102 <<
" [--image <input image>]"
103 <<
" [--hsv-thresholds <output filename.yml>]"
107 std::cout <<
"\nOPTIONS " << std::endl
108 <<
" --image <input image>" << std::endl
109 <<
" Name of the input image filename." << std::endl
110 <<
" When this option is not set, we use librealsense to stream images from a Realsense camera. " << std::endl
111 <<
" Example: --image ballons.jpg" << std::endl
113 <<
" --hsv-thresholds <output filename.yml>" << std::endl
114 <<
" Name of the output filename with yaml extension that will contain HSV low/high thresholds." << std::endl
115 <<
" Default: " << opt_hsv_filename << std::endl
117 <<
" --save-img" << std::endl
118 <<
" Enable RGB, HSV and segmented image saving" << std::endl
120 <<
" --help, -h" << std::endl
121 <<
" Display this helper message." << std::endl
127 bool use_realsense =
false;
128#if defined(VISP_HAVE_REALSENSE2)
129 use_realsense =
true;
132 if (!opt_img_filename.empty()) {
133 use_realsense =
false;
136 else if (opt_img_filename.empty()) {
137 std::cout <<
"Error: you should use --image <input image> option to specify an input image..." << std::endl;
142 std::cout <<
"Use images from Realsense camera" << std::endl;
145 int max_value_H = 255;
148 hsv_values_trackbar[0] = 0;
149 hsv_values_trackbar[1] = max_value_H;
150 hsv_values_trackbar[2] = 0;
151 hsv_values_trackbar[3] = max_value;
152 hsv_values_trackbar[4] = 0;
153 hsv_values_trackbar[5] = max_value;
158#if defined(VISP_HAVE_REALSENSE2)
163#if defined(VISP_HAVE_REALSENSE2)
167 config.enable_stream(RS2_STREAM_COLOR, width, height, RS2_FORMAT_RGBA8, fps);
168 config.disable_stream(RS2_STREAM_DEPTH);
169 config.disable_stream(RS2_STREAM_INFRARED, 1);
170 config.disable_stream(RS2_STREAM_INFRARED, 2);
180 std::cout <<
e.getStringMessage() << std::endl;
183 width = I.getWidth();
187 cv::namedWindow(window_detection_name);
189 vpArray2D<int> hsv_values(hsv_values_trackbar,
static_cast<unsigned int>(hsv_values_trackbar.size()), 1);
192 std::cout <<
"Load hsv values from " << opt_hsv_filename <<
" previous tuning " << std::endl;
193 std::cout << hsv_values.t() << std::endl;
194 hsv_values_prev = hsv_values;
195 for (
size_t i = 0;
i < hsv_values.size(); ++
i) {
196 hsv_values_trackbar[
i] = hsv_values.data[
i];
201 cv::createTrackbar(
"Low H", window_detection_name, &hsv_values_trackbar[0], max_value_H, on_low_H_thresh_trackbar);
202 cv::createTrackbar(
"High H", window_detection_name, &hsv_values_trackbar[1], max_value_H, on_high_H_thresh_trackbar);
203 cv::createTrackbar(
"Low S", window_detection_name, &hsv_values_trackbar[2], max_value, on_low_S_thresh_trackbar);
204 cv::createTrackbar(
"High S", window_detection_name, &hsv_values_trackbar[3], max_value, on_high_S_thresh_trackbar);
205 cv::createTrackbar(
"Low V", window_detection_name, &hsv_values_trackbar[4], max_value, on_low_V_thresh_trackbar);
206 cv::createTrackbar(
"High V", window_detection_name, &hsv_values_trackbar[5], max_value, on_high_V_thresh_trackbar);
211#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
226#if defined(VISP_HAVE_REALSENSE2)
234#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
239 reinterpret_cast<unsigned char *
>(H.bitmap),
240 reinterpret_cast<unsigned char *
>(S.bitmap),
241 reinterpret_cast<unsigned char *
>(V.bitmap), I.getSize());
244 reinterpret_cast<unsigned char *
>(S.bitmap),
245 reinterpret_cast<unsigned char *
>(V.bitmap),
247 reinterpret_cast<unsigned char *
>(mask.bitmap),
265 unsigned int i =
static_cast<unsigned int>(ip.
get_i());
266 unsigned int j =
static_cast<unsigned int>(ip.
get_j());
267#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
268 int h =
static_cast<int>(Ihsv[
i][
j].H);
269 int s =
static_cast<int>(Ihsv[
i][
j].S);
270 int v =
static_cast<int>(Ihsv[
i][
j].V);
272 int h =
static_cast<int>(H[
i][
j]);
273 int s =
static_cast<int>(S[
i][
j]);
274 int v =
static_cast<int>(V[
i][
j]);
276 std::cout <<
"RGB[" <<
i <<
"][" <<
j <<
"]: " <<
static_cast<int>(I[
i][
j].R) <<
" " <<
static_cast<int>(I[i][j].G)
277 <<
" " <<
static_cast<int>(I[
i][
j].B) <<
" -> HSV: " << h <<
" " << s <<
" " << v << std::endl;
280 unsigned int i =
static_cast<unsigned int>(ip.
get_i());
281 unsigned int j =
static_cast<unsigned int>(ip.
get_j());
282#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
283 int h =
static_cast<int>(Ihsv[
i][
j].H);
284 int s =
static_cast<int>(Ihsv[
i][
j].S);
285 int v =
static_cast<int>(Ihsv[
i][
j].V);
287 int h =
static_cast<int>(H[
i][
j]);
288 int s =
static_cast<int>(S[
i][
j]);
289 int v =
static_cast<int>(V[
i][
j]);
292 hsv_values_trackbar[0] = std::max(0, h - offset);
293 hsv_values_trackbar[1] = std::min(max_value_H, h + offset);
294 hsv_values_trackbar[2] = std::max(0, s - offset);
295 hsv_values_trackbar[3] = std::min(max_value, s + offset);
296 hsv_values_trackbar[4] = std::max(0, v - offset);
297 hsv_values_trackbar[5] = std::min(max_value, v + offset);
298 std::cout <<
"HSV learned: " <<
h <<
" " <<
s <<
" " <<
v << std::endl;
299 set_trackbar_H_min(hsv_values_trackbar[0]);
300 set_trackbar_H_max(hsv_values_trackbar[1]);
301 set_trackbar_S_min(hsv_values_trackbar[2]);
302 set_trackbar_S_max(hsv_values_trackbar[3]);
303 set_trackbar_V_min(hsv_values_trackbar[4]);
304 set_trackbar_V_max(hsv_values_trackbar[5]);
310 std::cout <<
"Create directory: " << parent << std::endl;
314 vpArray2D<int> hsv_values_new(hsv_values_trackbar,
static_cast<unsigned int>(hsv_values_trackbar.size()), 1);
315 if (hsv_values_new != hsv_values_prev) {
317 std::string hsv_filename_backup(opt_hsv_filename + std::string(
".previous"));
318 std::cout <<
"Create a backup of the previous calibration in " << hsv_filename_backup << std::endl;
322 std::cout <<
"Save new calibration in: " << opt_hsv_filename << std::endl;
327 std::string path_img(parent +
"/images-visp");
329 std::cout <<
"Create directory: " << path_img << std::endl;
333 std::cout <<
"Save images in path_img folder..." << std::endl;
336#if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
348#if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
349 if (d_I !=
nullptr) {
353 if (d_I_segmented !=
nullptr) {
354 delete d_I_segmented;
363#if !defined(HAVE_OPENCV_HIGHGUI)
364 std::cout <<
"This tutorial needs OpenCV highgui module as 3rd party." << std::endl;
366#if !defined(VISP_HAVE_X11)
367 std::cout <<
"This tutorial needs X11 3rd party enabled." << std::endl;
369 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.
static bool loadYAML(const std::string &filename, vpArray2D< Type > &A, char *header=nullptr)
static bool saveYAML(const std::string &filename, const vpArray2D< Type > &A, const char *header="")
Class that defines generic functionalities for display.
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.
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 convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
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 ...
Definition of the vpImage class member functions.
void acquire(vpImage< unsigned char > &grey, double *ts=nullptr)
bool open(const rs2::config &cfg=rs2::config())
std::shared_ptr< vpDisplay > createDisplay()
Return a smart pointer vpDisplay specialization if a GUI library is available or nullptr otherwise.
vpDisplay * allocateDisplay()
Return a newly allocated vpDisplay specialization if a GUI library is available or nullptr otherwise.
VISP_EXPORT std::string getDateTime(const std::string &format="%Y/%m/%d %H:%M:%S")