4 #include <visp3/core/vpColorDepthConversion.h>
5 #include <visp3/core/vpIoTools.h>
6 #include <visp3/core/vpMeterPixelConversion.h>
7 #include <visp3/core/vpXmlParserCamera.h>
10 #include <visp3/vision/vpPlaneEstimation.h>
11 #include <visp3/vision/vpPose.h>
14 #include <visp3/io/vpImageIo.h>
17 #include <visp3/gui/vpDisplayD3D.h>
18 #include <visp3/gui/vpDisplayGDI.h>
19 #include <visp3/gui/vpDisplayGTK.h>
20 #include <visp3/gui/vpDisplayOpenCV.h>
21 #include <visp3/gui/vpDisplayX.h>
23 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_17) && \
24 (!defined(_MSC_VER) || ((VISP_CXX_STANDARD >= VISP_CXX_STANDARD_17) && (_MSC_VER >= 1911))) && \
25 defined(VISP_HAVE_DISPLAY)
31 #if defined(VISP_HAVE_X11)
33 #elif defined(VISP_HAVE_GDI)
35 #elif defined(VISP_HAVE_OPENCV)
37 #elif defined(VISP_HAVE_GTK)
39 #elif defined(VISP_HAVE_D3D9)
46 constexpr
auto ModelCommentHeader{
"#"};
47 constexpr
auto ModelKeypointsHeader{
"Keypoints"};
48 constexpr
auto ModelBoundsHeader{
"Bounds"};
49 constexpr
auto ModelDataHeader{
"data:"};
52 constexpr
auto DepthScale{0.001};
55 #ifndef DOXYGEN_SHOULD_SKIP_THIS
61 Model(
const Model &) =
default;
62 Model(Model &&) =
default;
63 Model &operator=(
const Model &) =
default;
64 Model &operator=(Model &&) =
default;
66 explicit Model(
const std::string &model_filename);
69 using Id =
unsigned long int;
70 static inline std::string to_string(
const Id &
id) {
return std::to_string(
id); };
76 std::map<Id, vpPoint> m_keypoints{};
77 std::map<Id, vpPoint> m_bounds{};
80 inline Model::Model(
const std::string &model_filename)
83 file.open(model_filename.c_str(), std::fstream::in);
85 std::string line{}, subs{};
86 bool in_model_bounds{
false};
87 bool in_model_keypoints{
false};
88 unsigned int data_curr_line{0};
89 unsigned int data_line_start_pos{0};
92 in_model_bounds =
false;
93 in_model_keypoints =
false;
95 data_line_start_pos = 0;
98 while (getline(file, line)) {
99 if (line.substr(0, std::string(ModelCommentHeader).size()) == ModelCommentHeader || line == ModelDataHeader) {
101 }
else if (line == ModelBoundsHeader) {
103 in_model_bounds =
true;
105 }
else if (line == ModelKeypointsHeader) {
107 in_model_keypoints =
true;
111 if (data_curr_line == 0) {
113 data_line_start_pos = (
unsigned int)line.find(
"[") + 1;
117 std::stringstream ss(line.substr(data_line_start_pos, line.find(
"]") - data_line_start_pos));
118 unsigned int data_on_curr_line = 0;
120 while (getline(ss, subs,
',')) {
121 oXYZ[data_on_curr_line++] = std::atof(subs.c_str());
123 if (in_model_bounds) {
124 m_bounds.try_emplace(data_curr_line, oXYZ[0], oXYZ[1], oXYZ[2]);
125 }
else if (in_model_keypoints) {
126 m_keypoints.try_emplace(data_curr_line, oXYZ[0], oXYZ[1], oXYZ[2]);
139 auto bounds = m_bounds;
140 std::for_each(begin(bounds), end(bounds), [&cMo](
auto &bound) { bound.second.project(cMo); });
147 auto keypoints = m_keypoints;
148 std::for_each(begin(keypoints), end(keypoints), [&cMo](
auto &keypoint) { keypoint.second.project(cMo); });
153 std::ostream &
operator<<(std::ostream &os,
const Model &model)
155 os <<
"-Bounds:" << std::endl;
156 for (
const auto &[
id, bound] : model.bounds()) {
158 os << std::setw(4) << std::setfill(
' ') <<
id <<
": "
159 << std::setw(6) << std::setfill(
' ') << bound.get_X() <<
", "
160 << std::setw(6) << std::setfill(
' ') << bound.get_Y() <<
", "
161 << std::setw(6) << std::setfill(
' ') << bound.get_Z() << std::endl;
165 os <<
"-Keypoints:" << std::endl;
166 for (
const auto &[
id, keypoint] : model.keypoints()) {
168 os << std::setw(4) << std::setfill(
' ') <<
id <<
": "
169 << std::setw(6) << std::setfill(
' ') << keypoint.get_X() <<
", "
170 << std::setw(6) << std::setfill(
' ') << keypoint.get_Y() <<
", "
171 << std::setw(6) << std::setfill(
' ') << keypoint.get_Z() << std::endl;
179 readData(
const std::string &input_directory,
const unsigned int cpt = 0)
181 char buffer[FILENAME_MAX];
182 std::stringstream ss;
183 ss << input_directory <<
"/color_image_%04d.jpg";
184 snprintf(buffer, FILENAME_MAX, ss.str().c_str(), cpt);
185 const std::string filename_color = buffer;
188 ss << input_directory <<
"/depth_image_%04d.bin";
189 snprintf(buffer, FILENAME_MAX, ss.str().c_str(), cpt);
190 const std::string filename_depth = buffer;
198 std::ifstream file_depth(filename_depth.c_str(), std::ios::in | std::ios::binary);
199 if (file_depth.is_open()) {
200 unsigned int height = 0, width = 0;
203 I_depth_raw.resize(height, width);
205 for (
auto i = 0u; i < height; i++) {
206 for (
auto j = 0u; j < width; j++) {
214 ss << input_directory <<
"/camera.xml";
223 ss << input_directory <<
"/depth_M_color.txt";
224 std::ifstream file_depth_M_color(ss.str().c_str(), std::ios::in | std::ios::binary);
227 depth_M_color.
load(file_depth_M_color);
229 return {I_color, I_depth_raw, color_param, depth_param, depth_M_color};
235 Display disp_color(color_img, 0, 0,
"Roi bounds", DispScaleType);
236 disp_color.display(color_img);
237 disp_color.flush(color_img);
239 std::vector<vpImagePoint> v_ip{};
242 disp_color.display(color_img);
251 for (
auto j = 0u; j < v_ip.size(); j++) {
255 disp_color.flush(color_img);
264 if (v_ip.size() > 0) {
265 v_ip.erase(std::prev(end(v_ip)));
283 std::map<Model::Id, vpImagePoint> getKeypointsFromUser(
vpImage<vpRGBa> color_img,
const Model &model,
284 const std::string &parent_data)
287 Display disp_color(color_img, 0, 0,
"Keypoints", DispScaleType);
288 disp_color.display(color_img);
289 disp_color.flush(color_img);
292 vpImageIo::read(I_help, parent_data +
"/data/d435_box_keypoints_user_helper.png");
293 Display disp_help(I_help, disp_color.getWindowXPosition() + color_img.
getWidth(), disp_color.getWindowYPosition(),
294 "Keypoints [help]", DispScaleType);
295 disp_help.display(I_help);
296 disp_help.flush(I_help);
298 std::map<Model::Id, vpImagePoint> keypoints{};
308 for (
const auto &[
id, ip_unused] : model.keypoints()) {
311 disp_color.display(color_img);
319 for (
const auto &[
id, keypoint] : keypoints) {
323 disp_color.flush(color_img);
328 keypoints.try_emplace(
id, ip);
337 int main(
int,
char *argv[])
339 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_17) && \
340 (!defined(_MSC_VER) || ((VISP_CXX_STANDARD >= VISP_CXX_STANDARD_17) && (_MSC_VER >= 1911)))
342 #if defined(VISP_HAVE_DISPLAY)
346 auto [color_img, depth_raw, color_param, depth_param, depth_M_color] =
351 std::cout <<
"color_param:" << std::endl << color_param << std::endl;
352 std::cout <<
"depth_param:" << std::endl << depth_param << std::endl;
353 std::cout <<
"depth_M_color:" << std::endl << depth_M_color << std::endl;
354 std::cout << std::endl <<
"Model:" << std::endl << model << std::endl;
357 Display display_color(color_img, 0, 0,
"Color", DispScaleType);
358 display_color.display(color_img);
359 display_color.flush(color_img);
363 Display display_depth(depth_img, display_color.getWindowXPosition() + display_color.getWidth(), 0,
"Depth",
365 display_depth.display(depth_img);
366 display_depth.flush(depth_img);
371 roi_color_img.
buildFrom(getRoiFromUser(color_img),
true);
373 std::vector<vpImagePoint> roi_corners_depth_img{};
375 cbegin(roi_color_img.getCorners()), cend(roi_color_img.getCorners()), std::back_inserter(roi_corners_depth_img),
380 depth_raw, DepthScale, 0.1, 0.6, depth_param, color_param, depth_M_color.inverse(), depth_M_color,
381 std::placeholders::_1));
382 const vpPolygon roi_depth_img{roi_corners_depth_img};
386 display_depth.flush(depth_img);
391 const auto obj_plane_in_depth =
393 if (!obj_plane_in_depth) {
398 auto obj_plane_in_color = *obj_plane_in_depth;
399 obj_plane_in_color.changeFrame(depth_M_color.inverse());
402 Display display_heat_map(heat_map, display_depth.getWindowXPosition(),
403 display_depth.getWindowYPosition() + display_depth.getHeight(),
"Plane Estimation Heat map",
405 display_heat_map.display(heat_map);
406 display_heat_map.flush(heat_map);
409 const auto keypoint_color_img = getKeypointsFromUser(color_img, model,
vpIoTools::getParent(argv[0]));
413 keypoint_color_img, color_param);
420 std::vector<vpImagePoint> d435_box_bound{};
431 for (
const auto &[id_unused, bound] : model.bounds(*cMo)) {
435 d435_box_bound.push_back(ip);
439 for (
const auto &[
id, keypoint] : model.keypoints(*cMo)) {
461 std::cout <<
"There is no display available to run this tutorial." << std::endl;
465 std::cout <<
"c++17 should be enabled to run this tutorial." << std::endl;
friend std::ostream & operator<<(std::ostream &s, const vpArray2D< Type > &A)
Generic class defining intrinsic camera parameters.
@ perspectiveProjWithDistortion
Perspective projection with distortion model.
Implementation of column vector and the associated operations.
static vpImagePoint projectColorToDepth(const vpImage< uint16_t > &I_depth, double depth_scale, double depth_min, double depth_max, const vpCameraParameters &depth_intrinsics, const vpCameraParameters &color_intrinsics, const vpHomogeneousMatrix &color_M_depth, const vpHomogeneousMatrix &depth_M_color, const vpImagePoint &from_pixel)
static const vpColor none
static const vpColor orange
static const vpColor blue
static const vpColor green
Display for windows using Direct3D 3rd party. Thus to enable this class Direct3D should be installed....
Display for windows using GDI (available on any windows 32 platform).
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void displayFrame(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, double size, const vpColor &color=vpColor::none, unsigned int thickness=1, const vpImagePoint &offset=vpImagePoint(0, 0), const std::string &frameName="", const vpColor &textColor=vpColor::black, const vpImagePoint &textOffset=vpImagePoint(15, 15))
static void displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
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)
static void displayPolygon(const vpImage< unsigned char > &I, const std::vector< vpImagePoint > &vip, const vpColor &color, unsigned int thickness=1, bool closed=true)
Implementation of an homogeneous matrix and operations on such kind of matrices.
void load(std::ifstream &f)
static void createDepthHistogram(const vpImage< uint16_t > &src_depth, vpImage< vpRGBa > &dest_rgba)
static void read(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.
unsigned int getWidth() const
static void convertPoint(const vpCameraParameters &cam, const double &x, const double &y, double &u, double &v)
static std::optional< vpPlane > estimatePlane(const vpImage< uint16_t > &I_depth_raw, double depth_scale, const vpCameraParameters &depth_intrinsics, const vpPolygon &roi, const unsigned int avg_nb_of_pts_to_estimate=500, std::optional< std::reference_wrapper< vpImage< vpRGBa > > > heat_map={})
Defines a generic 2D polygon.
void buildFrom(const std::vector< vpImagePoint > &corners, const bool create_convex_hull=false)
static std::optional< vpHomogeneousMatrix > computePlanarObjectPoseWithAtLeast3Points(const vpPlane &plane_in_camera_frame, const std::map< DataId, vpPoint > &pts, const std::map< DataId, vpImagePoint > &ips, const vpCameraParameters &camera_intrinsics, std::optional< vpHomogeneousMatrix > cMo_init=std::nullopt, bool enable_vvs=true)
XML parser to load and save intrinsic camera parameters.