Visual Servoing Platform  version 3.6.1 under development (2024-05-15)
tutorial-mb-generic-tracker-save.cpp
1 #include <visp3/core/vpIoTools.h>
2 #include <visp3/io/vpImageIo.h>
3 #include <visp3/mbt/vpMbGenericTracker.h>
4 #include <visp3/io/vpVideoReader.h>
5 
6 
7 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
8 namespace
9 {
10 std::vector<double> poseToVec(const vpHomogeneousMatrix &cMo)
11 {
14 
15  std::vector<double> vec { t[0], t[1], t[2], tu[0], tu[1], tu[2] };
16 
17  return vec;
18 }
19 
20 // https://en.cppreference.com/w/cpp/io/c/fprintf
21 std::string toString(const std::string &name, int val)
22 {
23  auto fmt = name.c_str();
24  int sz = std::snprintf(nullptr, 0, fmt, val);
25  std::vector<char> buf(sz + 1); // note +1 for null terminator
26  std::sprintf(buf.data(), fmt, val);
27  std::string str(buf.begin(), buf.end());
28 
29  return str;
30 }
31 }
32 
33 int main(int argc, char **argv)
34 {
35  bool opencv_backend = false;
36  std::string npz_filename = "npz_tracking_teabox.npz";
37  bool color_mode = false;
38  bool save_alpha = false;
39  bool print_cMo = false;
40 
41  for (int i = 1; i < argc; i++) {
42  if (std::string(argv[i]) == "--cv-backend") {
43  opencv_backend = true;
44  }
45  else if ((std::string(argv[i]) == "--save" || std::string(argv[i]) == "-o") && i+1 < argc) {
46  npz_filename = argv[i+1];
47  }
48  else if (std::string(argv[i]) == "--color" || std::string(argv[i]) == "-c") {
49  color_mode = true;
50  }
51  else if (std::string(argv[i]) == "--alpha" || std::string(argv[i]) == "-a") {
52  save_alpha = true;
53  }
54  else if (std::string(argv[i]) == "--print-cMo" && i+1 < argc) {
55  print_cMo = true;
56  }
57  else {
58  std::cout << "Options:" << std::endl;
59  std::cout << " --cv-backend use OpenCV if available for in-memory PNG encoding" << std::endl;
60  std::cout << " --save / -o output filename" << std::endl;
61  std::cout << " --color save RGB data" << std::endl;
62  std::cout << " --alpha if --color opton, save RGBa data" << std::endl;
63  std::cout << " --print-cMo print cMo" << std::endl;
64  return EXIT_SUCCESS;
65  }
66  }
67 
68  std::cout << "Save file: " << npz_filename << std::endl;
69  std::cout << "OpenCV backend? " << opencv_backend << std::endl;
70  std::cout << "Color image? " << color_mode << std::endl;
71  std::cout << "Save alpha channel? " << save_alpha << std::endl;
72 
73  std::string opt_videoname = "model/teabox/teabox.mp4";
74  std::string opt_modelname = "model/teabox/teabox.cao";
75 
76  std::string parentname = vpIoTools::getParent(opt_modelname);
77  std::string objectname = vpIoTools::getNameWE(opt_modelname);
78 
79  if (!parentname.empty())
80  objectname = parentname + "/" + objectname;
81 
82  std::cout << "Video name: " << opt_videoname << std::endl;
83 
85  vpImage<vpRGBa> I_color;
86 
87  vpVideoReader g;
88  g.setFileName(opt_videoname);
89  g.open(I);
90 
91  vpMbGenericTracker tracker;
93 
95  cam.initPersProjWithoutDistortion(839, 839, 325, 243);
96  tracker.setCameraParameters(cam);
97  tracker.loadModel(objectname + ".cao");
98 
100  cMo[0][0] = 0.4889237963; cMo[0][1] = 0.8664706489; cMo[0][2] = 0.1009065709; cMo[0][3] = -0.07010159786;
101  cMo[1][0] = 0.4218451176; cMo[1][1] = -0.1335995053; cMo[1][2] = -0.8967708007; cMo[1][3] = -0.08363026223;
102  cMo[2][0] = -0.7635445096; cMo[2][1] = 0.4810195286; cMo[2][2] = -0.4308363901; cMo[2][3] = 0.4510066725;
103  tracker.initFromPose(I, cMo);
104 
105  const int height = I.getRows();
106  const int width = I.getCols();
107  int channel = 1;
108  if (color_mode) {
109  channel = save_alpha ? 4 : 3;
110  }
111 
112  const vpImageIo::vpImageIoBackendType backend =
114 
115  // vector of byte data to store encoded image data using PNG format
116  std::vector<unsigned char> img_buffer;
117 
118  const std::string camera_name = "Camera";
119  std::vector<char> vec_camera_name(camera_name.begin(), camera_name.end());
120 
121  visp::cnpy::npz_save(npz_filename, "camera_name", &vec_camera_name[0], { vec_camera_name.size() }, "w"); // overwrite
122  visp::cnpy::npz_save(npz_filename, "height", &height, { 1 }, "a"); // append
123  visp::cnpy::npz_save(npz_filename, "width", &width, { 1 }, "a");
124  visp::cnpy::npz_save(npz_filename, "channel", &channel, { 1 }, "a");
125 
126  const double cam_px = cam.get_px(), cam_py = cam.get_py(), cam_u0 = cam.get_u0(), cam_v0 = cam.get_v0();
127  visp::cnpy::npz_save(npz_filename, "cam_px", &cam_px, { 1 }, "a");
128  visp::cnpy::npz_save(npz_filename, "cam_py", &cam_py, { 1 }, "a");
129  visp::cnpy::npz_save(npz_filename, "cam_u0", &cam_u0, { 1 }, "a");
130  visp::cnpy::npz_save(npz_filename, "cam_v0", &cam_v0, { 1 }, "a");
131 
132  std::vector<double> vec_poses;
133  vec_poses.reserve(g.getLastFrameIndex() * 6);
134 
135  std::vector<int> vec_img_data_size;
136  vec_img_data_size.reserve(g.getLastFrameIndex());
137  std::vector<unsigned char> vec_img_data;
138  vec_img_data.reserve(g.getLastFrameIndex() * height * width);
139 
140  std::vector<double> times;
141  size_t iter = 0;
142  while (!g.end()) {
143  g.acquire(I);
144  tracker.track(I);
145  tracker.getPose(cMo);
146  if (print_cMo) {
147  std::cout << "\ncMo:\n" << cMo << std::endl;
148  }
149 
150  vpImageConvert::convert(I, I_color);
151  double start = vpTime::measureTimeMs();
152  if (color_mode) {
153  vpImageIo::writePNGtoMem(I_color, img_buffer, backend, save_alpha);
154  }
155  else {
156  vpImageIo::writePNGtoMem(I, img_buffer, backend);
157  }
158  double end = vpTime::measureTimeMs();
159  times.push_back(end-start);
160  vec_img_data_size.push_back(static_cast<int>(img_buffer.size()));
161  vec_img_data.insert(vec_img_data.end(), img_buffer.begin(), img_buffer.end());
162 
163  std::vector<double> vec_pose = poseToVec(cMo);
164  vec_poses.insert(vec_poses.end(), vec_pose.begin(), vec_pose.end());
165 
166  std::map<std::string, std::vector<std::vector<double> > > mapOfModels;
167  std::map<std::string, unsigned int> mapOfW;
168  mapOfW[camera_name] = I.getWidth();
169  std::map<std::string, unsigned int> mapOfH;
170  mapOfH[camera_name] = I.getHeight();
171  std::map<std::string, vpHomogeneousMatrix> mapOfcMos;
172  mapOfcMos[camera_name] = cMo;
173  std::map<std::string, vpCameraParameters> mapOfCams;
174  mapOfCams[camera_name] = cam;
175  tracker.getModelForDisplay(mapOfModels, mapOfW, mapOfH, mapOfcMos, mapOfCams);
176 
177  std::vector<std::vector<double>> model = mapOfModels[camera_name];
178  const std::string model_iter = toString("model_%06zu", static_cast<int>(iter));
179  const std::string model_iter_sz = model_iter + "_sz";
180  const size_t model_size = model.size();
181  visp::cnpy::npz_save(npz_filename, model_iter_sz, &model_size, { 1 }, "a");
182 
183  for (size_t i = 0; i < model.size(); i++) {
184  char buffer[100];
185  int res = snprintf(buffer, 100, "model_%06zu_%06zu", iter, i);
186  if (res > 0 && res < 100) {
187  const std::string model_iter_data = buffer;
188  std::vector<double> &vec_line = model[i];
189  visp::cnpy::npz_save(npz_filename, model_iter_data, &vec_line[0], { vec_line.size() }, "a");
190  }
191  }
192 
193  iter++;
194  }
195 
196  std::cout << "Mean time for image encoding: " << vpMath::getMean(times) << " ms ; Median time: "
197  << vpMath::getMedian(times) << " ms ; Std: " << vpMath::getStdev(times) << " ms" << std::endl;
198 
199  visp::cnpy::npz_save(npz_filename, "vec_img_data_size", vec_img_data_size.data(), { vec_img_data_size.size() }, "a");
200  visp::cnpy::npz_save(npz_filename, "vec_img", vec_img_data.data(), { vec_img_data.size() }, "a");
201  // Show how to save a "multidimensional" array
202  assert(iter == vec_poses.size()/6);
203  visp::cnpy::npz_save(npz_filename, "vec_poses", vec_poses.data(), { static_cast<size_t>(iter), 6 }, "a");
204 
205  visp::cnpy::npz_save(npz_filename, "nb_data", &iter, { 1 }, "a");
206 
207  return EXIT_SUCCESS;
208 }
209 
210 #else
211 #include <iostream>
212 
213 int main()
214 {
215  std::cout << "This tutorial needs c++11 flags" << std::endl;
216 }
217 #endif
Generic class defining intrinsic camera parameters.
void initPersProjWithoutDistortion(double px, double py, double u0, double v0)
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpThetaUVector getThetaUVector() const
vpTranslationVector getTranslationVector() const
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
vpImageIoBackendType
Image IO backend for only jpeg and png formats image loading and saving.
Definition: vpImageIo.h:123
@ IO_STB_IMAGE_BACKEND
Use embedded stb_image library.
Definition: vpImageIo.h:128
@ IO_OPENCV_BACKEND
Use OpenCV imgcodecs module.
Definition: vpImageIo.h:126
static void writePNGtoMem(const vpImage< unsigned char > &I, std::vector< unsigned char > &buffer, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:1520
unsigned int getWidth() const
Definition: vpImage.h:245
unsigned int getCols() const
Definition: vpImage.h:175
unsigned int getHeight() const
Definition: vpImage.h:184
unsigned int getRows() const
Definition: vpImage.h:215
static std::string getNameWE(const std::string &pathname)
Definition: vpIoTools.cpp:2005
static std::string getParent(const std::string &pathname)
Definition: vpIoTools.cpp:2088
static double getMedian(const std::vector< double > &v)
Definition: vpMath.cpp:323
static double getStdev(const std::vector< double > &v, bool useBesselCorrection=false)
Definition: vpMath.cpp:354
static double getMean(const std::vector< double > &v)
Definition: vpMath.cpp:303
Real-time 6D object pose tracking using its CAD model.
virtual void initFromPose(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo) vp_override
virtual void getPose(vpHomogeneousMatrix &cMo) const vp_override
virtual std::vector< std::vector< double > > getModelForDisplay(unsigned int width, unsigned int height, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, bool displayFullModel=false) vp_override
virtual void loadModel(const std::string &modelFile, bool verbose=false, const vpHomogeneousMatrix &T=vpHomogeneousMatrix()) vp_override
virtual void setCameraParameters(const vpCameraParameters &camera) vp_override
virtual void setTrackerType(int type)
virtual void track(const vpImage< unsigned char > &I) vp_override
Implementation of a rotation vector as axis-angle minimal representation.
Class that consider the case of a translation vector.
Class that enables to manipulate easily a video file or a sequence of images. As it inherits from the...
void acquire(vpImage< vpRGBa > &I)
long getLastFrameIndex()
void open(vpImage< vpRGBa > &I)
void setFileName(const std::string &filename)
void npz_save(std::string zipname, std::string fname, const T *data, const std::vector< size_t > &shape, std::string mode="w")
Definition: vpIoTools.h:233
VISP_EXPORT double measureTimeMs()