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