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)
36 using Display = vpDisplayX;
37 #elif defined(VISP_HAVE_GDI)
39 #elif defined(VISP_HAVE_OPENCV)
41 #elif defined(VISP_HAVE_GTK)
43 #elif defined(VISP_HAVE_D3D9)
50 constexpr
auto ModelCommentHeader {
"#" };
51 constexpr
auto ModelKeypointsHeader {
"Keypoints" };
52 constexpr
auto ModelBoundsHeader {
"Bounds" };
53 constexpr
auto ModelDataHeader {
"data:" };
56 constexpr
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); };
80 std::map<Id, vpPoint> m_keypoints {};
81 std::map<Id, vpPoint> m_bounds {};
84 inline 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 = (
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); });
161 std::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;
187 readData(
const std::string &input_directory,
const unsigned int cpt = 0)
189 char buffer[FILENAME_MAX];
190 std::stringstream ss;
191 ss << input_directory <<
"/color_image_%04d.jpg";
192 snprintf(buffer, FILENAME_MAX, ss.str().c_str(), cpt);
193 const std::string filename_color = buffer;
196 ss << input_directory <<
"/depth_image_%04d.bin";
197 snprintf(buffer, FILENAME_MAX, ss.str().c_str(), cpt);
198 const std::string filename_depth = buffer;
206 std::ifstream file_depth(filename_depth.c_str(), std::ios::in | std::ios::binary);
207 if (file_depth.is_open()) {
208 unsigned int height = 0, width = 0;
211 I_depth_raw.resize(height, width);
213 for (
auto i = 0u; i < height; i++) {
214 for (
auto j = 0u; j < width; j++) {
222 ss << input_directory <<
"/camera.xml";
231 ss << input_directory <<
"/depth_M_color.txt";
232 std::ifstream file_depth_M_color(ss.str().c_str(), std::ios::in | std::ios::binary);
235 depth_M_color.
load(file_depth_M_color);
237 return { I_color, I_depth_raw, color_param, depth_param, depth_M_color };
243 Display disp_color(color_img, 0, 0,
"Roi bounds", DispScaleType);
244 disp_color.display(color_img);
245 disp_color.flush(color_img);
247 std::vector<vpImagePoint> v_ip {};
250 disp_color.display(color_img);
251 auto disp_lane { 0 };
259 for (
auto j = 0u; j < v_ip.size(); j++) {
263 disp_color.flush(color_img);
272 if (v_ip.size() > 0) {
273 v_ip.erase(std::prev(end(v_ip)));
291 std::map<Model::Id, vpImagePoint> getKeypointsFromUser(
vpImage<vpRGBa> color_img,
const Model &model,
292 const std::string &parent_data)
295 Display disp_color(color_img, 0, 0,
"Keypoints", DispScaleType);
296 disp_color.display(color_img);
297 disp_color.flush(color_img);
300 vpImageIo::read(I_help, parent_data +
"/data/d435_box_keypoints_user_helper.png");
301 Display disp_help(I_help, disp_color.getWindowXPosition() + color_img.
getWidth(), disp_color.getWindowYPosition(),
302 "Keypoints [help]", DispScaleType);
303 disp_help.display(I_help);
304 disp_help.flush(I_help);
306 std::map<Model::Id, vpImagePoint> keypoints {};
316 for (
const auto &[
id, ip_unused] : model.keypoints()) {
319 disp_color.display(color_img);
320 auto disp_lane { 0 };
327 for (
const auto &[
id, keypoint] : keypoints) {
331 disp_color.flush(color_img);
336 keypoints.try_emplace(
id, ip);
344 int main(
int,
char *argv[])
346 #if ((__cplusplus >= 201703L) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L)))
348 #if defined(VISP_HAVE_DISPLAY) && defined(VISP_HAVE_PUGIXML)
352 auto [color_img, depth_raw, color_param, depth_param, depth_M_color] =
357 std::cout <<
"color_param:" << std::endl << color_param << std::endl;
358 std::cout <<
"depth_param:" << std::endl << depth_param << std::endl;
359 std::cout <<
"depth_M_color:" << std::endl << depth_M_color << std::endl;
360 std::cout << std::endl <<
"Model:" << std::endl << model << std::endl;
363 Display display_color(color_img, 0, 0,
"Color", DispScaleType);
364 display_color.display(color_img);
365 display_color.flush(color_img);
369 Display display_depth(depth_img, display_color.getWindowXPosition() + display_color.getWidth(), 0,
"Depth",
371 display_depth.display(depth_img);
372 display_depth.flush(depth_img);
377 roi_color_img.
buildFrom(getRoiFromUser(color_img),
true);
379 std::vector<vpImagePoint> roi_corners_depth_img {};
381 cbegin(roi_color_img.getCorners()), cend(roi_color_img.getCorners()), std::back_inserter(roi_corners_depth_img),
386 depth_raw, DepthScale, 0.1, 0.6, depth_param, color_param, depth_M_color.inverse(), depth_M_color,
387 std::placeholders::_1));
388 const vpPolygon roi_depth_img { roi_corners_depth_img };
392 display_depth.flush(depth_img);
397 const auto obj_plane_in_depth =
398 vpPlaneEstimation::estimatePlane(depth_raw, DepthScale, depth_param, roi_depth_img, 1000, heat_map);
399 if (!obj_plane_in_depth) {
404 auto obj_plane_in_color = *obj_plane_in_depth;
405 obj_plane_in_color.changeFrame(depth_M_color.inverse());
408 Display display_heat_map(heat_map, display_depth.getWindowXPosition(),
409 display_depth.getWindowYPosition() + display_depth.getHeight(),
"Plane Estimation Heat map",
411 display_heat_map.display(heat_map);
412 display_heat_map.flush(heat_map);
415 const auto keypoint_color_img = getKeypointsFromUser(color_img, model,
vpIoTools::getParent(argv[0]));
418 const auto cMo = vpPose::computePlanarObjectPoseWithAtLeast3Points(obj_plane_in_color, model.keypoints(),
419 keypoint_color_img, color_param);
426 std::vector<vpImagePoint> d435_box_bound {};
437 for (
const auto &[id_unused, bound] : model.bounds(*cMo)) {
441 d435_box_bound.push_back(ip);
445 for (
const auto &[
id, keypoint] : model.keypoints(*cMo)) {
457 auto disp_lane { 0 };
467 std::cout <<
"There is no display and pugixml available to run this tutorial." << std::endl;
471 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, 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...
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)
Defines a generic 2D polygon.
vpPolygon & buildFrom(const std::vector< vpImagePoint > &corners, const bool &create_convex_hull=false)
XML parser to load and save intrinsic camera parameters.