4#include <visp3/core/vpColorDepthConversion.h>
5#include <visp3/core/vpConfig.h>
6#include <visp3/core/vpIoTools.h>
7#include <visp3/core/vpMeterPixelConversion.h>
8#include <visp3/core/vpXmlParserCamera.h>
11#include <visp3/vision/vpPlaneEstimation.h>
12#include <visp3/vision/vpPose.h>
15#include <visp3/io/vpImageIo.h>
18#include <visp3/gui/vpDisplayD3D.h>
19#include <visp3/gui/vpDisplayGDI.h>
20#include <visp3/gui/vpDisplayGTK.h>
21#include <visp3/gui/vpDisplayOpenCV.h>
22#include <visp3/gui/vpDisplayX.h>
25#if ((__cplusplus >= 201703L) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L))) && defined(VISP_HAVE_DISPLAY) && defined(VISP_HAVE_PUGIXML)
27#ifdef ENABLE_VISP_NAMESPACE
35#if defined(VISP_HAVE_X11)
37#elif defined(VISP_HAVE_GDI)
39#elif defined(VISP_HAVE_OPENCV)
41#elif defined(VISP_HAVE_GTK)
43#elif defined(VISP_HAVE_D3D9)
50constexpr auto ModelCommentHeader {
"#" };
51constexpr auto ModelKeypointsHeader {
"Keypoints" };
52constexpr auto ModelBoundsHeader {
"Bounds" };
53constexpr auto ModelDataHeader {
"data:" };
56constexpr auto DepthScale { 0.001 };
59#ifndef DOXYGEN_SHOULD_SKIP_THIS
65 Model(
const Model &) =
default;
66 Model(Model &&) =
default;
67 Model &operator=(
const Model &) =
default;
68 Model &operator=(Model &&) =
default;
70 explicit Model(
const std::string &model_filename);
73 using Id =
unsigned long int;
74 static inline std::string to_string(
const Id &
id) {
return std::to_string(
id); };
76 std::map<Id, vpPoint> keypoints(
const vpHomogeneousMatrix &cMo = {})
const;
77 std::map<Id, vpPoint> bounds(
const vpHomogeneousMatrix &cMo = {})
const;
80 std::map<Id, vpPoint> m_keypoints {};
81 std::map<Id, vpPoint> m_bounds {};
84inline Model::Model(
const std::string &model_filename)
87 file.open(model_filename.c_str(), std::fstream::in);
89 std::string line {}, subs {};
90 bool in_model_bounds {
false };
91 bool in_model_keypoints {
false };
92 unsigned int data_curr_line { 0 };
93 unsigned int data_line_start_pos { 0 };
96 in_model_bounds =
false;
97 in_model_keypoints =
false;
99 data_line_start_pos = 0;
102 while (getline(file, line)) {
103 if (line.substr(0, std::string(ModelCommentHeader).size()) == ModelCommentHeader || line == ModelDataHeader) {
106 else if (line == ModelBoundsHeader) {
108 in_model_bounds =
true;
111 else if (line == ModelKeypointsHeader) {
113 in_model_keypoints =
true;
117 if (data_curr_line == 0) {
119 data_line_start_pos =
static_cast<unsigned int>(line.find(
"[")) + 1;
123 std::stringstream ss(line.substr(data_line_start_pos, line.find(
"]") - data_line_start_pos));
124 unsigned int data_on_curr_line = 0;
126 while (getline(ss, subs,
',')) {
127 oXYZ[data_on_curr_line++] = std::atof(subs.c_str());
129 if (in_model_bounds) {
130 m_bounds.try_emplace(data_curr_line, oXYZ[0], oXYZ[1], oXYZ[2]);
132 else if (in_model_keypoints) {
133 m_keypoints.try_emplace(data_curr_line, oXYZ[0], oXYZ[1], oXYZ[2]);
147 auto bounds = m_bounds;
148 std::for_each(begin(bounds), end(bounds), [&cMo](
auto &bound) { bound.second.project(cMo); });
155 auto keypoints = m_keypoints;
156 std::for_each(begin(keypoints), end(keypoints), [&cMo](
auto &keypoint) { keypoint.second.project(cMo); });
161std::ostream &operator<<(std::ostream &os,
const Model &model)
163 os <<
"-Bounds:" << std::endl;
164 for (
const auto &[
id, bound] : model.bounds()) {
166 os << std::setw(4) << std::setfill(
' ') <<
id <<
": "
167 << std::setw(6) << std::setfill(
' ') << bound.get_X() <<
", "
168 << std::setw(6) << std::setfill(
' ') << bound.get_Y() <<
", "
169 << std::setw(6) << std::setfill(
' ') << bound.get_Z() << std::endl;
173 os <<
"-Keypoints:" << std::endl;
174 for (
const auto &[
id, keypoint] : model.keypoints()) {
176 os << std::setw(4) << std::setfill(
' ') <<
id <<
": "
177 << std::setw(6) << std::setfill(
' ') << keypoint.get_X() <<
", "
178 << std::setw(6) << std::setfill(
' ') << keypoint.get_Y() <<
", "
179 << std::setw(6) << std::setfill(
' ') << keypoint.get_Z() << std::endl;
187readData(
const std::string &input_directory,
const unsigned int cpt = 0)
198 std::ifstream file_depth(filename_depth.c_str(), std::ios::in | std::ios::binary);
199 if (file_depth.is_open()) {
203 I_depth_raw.
resize(height, width);
205 for (
auto i = 0u;
i <
height;
i++) {
206 for (
auto j = 0u;
j <
width;
j++) {
213 std::stringstream ss;
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);
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);
243 auto disp_lane { 0 };
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)));
283std::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.jpg");
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);
312 auto disp_lane { 0 };
319 for (
const auto &[
id, keypoint] : keypoints) {
323 disp_color.flush(color_img);
328 keypoints.try_emplace(
id, ip);
336int main(
int,
char *argv[])
338#if ((__cplusplus >= 201703L) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L)))
340#if defined(VISP_HAVE_DISPLAY) && defined(VISP_HAVE_PUGIXML)
344 auto [color_img, depth_raw, color_param, depth_param,
depth_M_color] =
349 std::cout <<
"color_param:" << std::endl << color_param << std::endl;
350 std::cout <<
"depth_param:" << std::endl << depth_param << std::endl;
351 std::cout <<
"depth_M_color:" << std::endl <<
depth_M_color << std::endl;
352 std::cout << std::endl <<
"Model:" << std::endl << model << std::endl;
355 Display display_color(color_img, 0, 0,
"Color", DispScaleType);
356 display_color.display(color_img);
357 display_color.flush(color_img);
361 Display display_depth(depth_img, display_color.getWindowXPosition() + display_color.getWidth(), 0,
"Depth",
363 display_depth.display(depth_img);
364 display_depth.flush(depth_img);
369 roi_color_img.
buildFrom(getRoiFromUser(color_img),
true);
371 std::vector<vpImagePoint> roi_corners_depth_img {};
373 cbegin(roi_color_img.
getCorners()), cend(roi_color_img.
getCorners()), std::back_inserter(roi_corners_depth_img),
378 depth_raw, DepthScale, 0.1, 0.6, depth_param, color_param,
depth_M_color.inverse(), depth_M_color,
379 std::placeholders::_1));
380 const vpPolygon roi_depth_img { roi_corners_depth_img };
384 display_depth.flush(depth_img);
389 const auto obj_plane_in_depth =
391 if (!obj_plane_in_depth) {
396 auto obj_plane_in_color = *obj_plane_in_depth;
400 Display display_heat_map(heat_map, display_depth.getWindowXPosition(),
401 display_depth.getWindowYPosition() + display_depth.getHeight(),
"Plane Estimation Heat map",
403 display_heat_map.display(heat_map);
404 display_heat_map.flush(heat_map);
407 const auto keypoint_color_img = getKeypointsFromUser(color_img, model,
vpIoTools::getParent(argv[0]));
411 keypoint_color_img, color_param);
418 std::vector<vpImagePoint> d435_box_bound {};
429 for (
const auto &[id_unused, bound] : model.bounds(*cMo)) {
433 d435_box_bound.push_back(ip);
437 for (
const auto &[
id, keypoint] : model.keypoints(*cMo)) {
449 auto disp_lane { 0 };
459 std::cout <<
"There is no display and pugixml available to run this tutorial." << std::endl;
463 std::cout <<
"c++17 should be enabled to run this tutorial." << std::endl;
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, const double &depth_scale, const double &depth_min, const 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.
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
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
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.
vpPolygon & buildFrom(const std::vector< vpImagePoint > &corners, const bool &create_convex_hull=false)
const std::vector< vpImagePoint > & getCorners() const
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.