Visual Servoing Platform  version 3.6.1 under development (2024-11-15)
tutorial-video-manipulation.cpp
1 #include <visp3/core/vpConfig.h>
3 #include <visp3/core/vpImageConvert.h>
4 #include <visp3/core/vpTime.h>
5 #include <visp3/gui/vpDisplayD3D.h>
6 #include <visp3/gui/vpDisplayGDI.h>
7 #include <visp3/gui/vpDisplayGTK.h>
8 #include <visp3/gui/vpDisplayOpenCV.h>
9 #include <visp3/gui/vpDisplayX.h>
10 #include <visp3/io/vpVideoReader.h>
11 #include <visp3/io/vpVideoWriter.h>
12 
13 void usage(const char *argv[], int error)
14 {
15  std::cout << "Synopsis" << std::endl
16  << " " << argv[0] << " [--in <video name>]"
17  << " [--display-fps <framerate>]"
18  << " [--out <video name>]"
19  << " [--out-first-frame <index>]"
20  << " [--out-gray]"
21  << " [--out-stride <value>]"
22  << " [--verbose] [-v]"
23  << " [--help] [-h]" << std::endl
24  << std::endl;
25  std::cout << "Description" << std::endl
26  << " --in <video name> " << std::endl
27  << " Input video to manipulate. " << std::endl
28  << " Supported image formats: pgm,ppm,jpg,jpeg,png,tiff,bmp,ras,jp2" << std::endl
29  << " Example: " << std::endl
30  << " - I%03d.jpg : to read a sequence of images (I008.jpg, I009.jpg, I010.jpg) " << std::endl
31  << std::endl
32  << " --display-fps <framerate>" << std::endl
33  << " Framerate used to display the video. When set to -1 display video as fast as possible." << std::endl
34  << " Default: 30 (fps)" << std::endl
35  << std::endl
36  << " --out <video name>" << std::endl
37  << " Renamed video." << std::endl
38  << std::endl
39  << " --out-first-frame <index>" << std::endl
40  << " Renamed video first image index." << std::endl
41  << " When set to -1, use same image numbering as input video." << std::endl
42  << " Default: -1" << std::endl
43  << std::endl
44  << " --out-gray" << std::endl
45  << " Associated to --out option, convert input images to Y8 gray level image." << std::endl
46  << std::endl
47  << " --out-stride <value>" << std::endl
48  << " Associated to --out option, allows to subsample the resulting output video" << std::endl
49  << " keeping one over <value> images. For example, when set to 2, the ouput video" << std::endl
50  << " has two times less images than the input video." << std::endl
51  << " Default: 1." << std::endl
52  << std::endl
53  << " --select, -s" << std::endl
54  << " Associated to --out option, allows the user to select by mouse" << std::endl
55  << " click which images will be saved in the output video." << std::endl
56  << std::endl
57  << " --verbose, -v" << std::endl
58  << " Display extra messages." << std::endl
59  << std::endl
60  << " --help, -h" << std::endl
61  << " Print this helper message." << std::endl
62  << std::endl;
63  if (error) {
64  std::cout << "Error" << std::endl
65  << " "
66  << "Unsupported parameter " << argv[error] << std::endl;
67  }
68 }
69 
70 int main(int argc, const char *argv[])
71 {
72 #ifdef ENABLE_VISP_NAMESPACE
73  using namespace VISP_NAMESPACE_NAME;
74 #endif
75 
76  if (argc == 1) {
77  usage(argv, 0);
78  return EXIT_SUCCESS;
79  }
80 
81  std::string opt_video_in = "";
82  double opt_display_fps = 30;
83  std::string opt_video_out = "";
84  int opt_video_out_first_frame = -1;
85  bool opt_video_out_gray = false;
86  int opt_video_out_stride = 1;
87 
88  bool opt_verbose = false;
89  bool opt_select_frame = false;
90 
91  for (int i = 1; i < argc; i++) {
92  if (std::string(argv[i]) == "--in" && i + 1 < argc) {
93  opt_video_in = std::string(argv[i + 1]);
94  i++;
95  }
96  else if (std::string(argv[i]) == "--display-fps" && i + 1 < argc) {
97  opt_display_fps = std::atof(argv[i + 1]);
98  i++;
99  }
100  else if (std::string(argv[i]) == "--out" && i + 1 < argc) {
101  opt_video_out = std::string(argv[i + 1]);
102  i++;
103  }
104  else if (std::string(argv[i]) == "--out-first-frame" && i + 1 < argc) {
105  opt_video_out_first_frame = std::atoi(argv[i + 1]);
106  i++;
107  }
108  else if (std::string(argv[i]) == "--out-gray") {
109  opt_video_out_gray = true;
110  }
111  else if (std::string(argv[i]) == "--out-stride" && i + 1 < argc) {
112  opt_video_out_stride = std::atoi(argv[i + 1]);
113  i++;
114  }
115  else if (std::string(argv[i]) == "--verbose" || std::string(argv[i]) == "-v") {
116  opt_verbose = true;
117  }
118  else if (std::string(argv[i]) == "--select" || std::string(argv[i]) == "-s") {
119  opt_select_frame = true;
120  }
121  else if (std::string(argv[i]) == "--help" || std::string(argv[i]) == "-h") {
122  usage(argv, 0);
123  return EXIT_SUCCESS;
124  }
125  else {
126  usage(argv, i);
127  return EXIT_FAILURE;
128  }
129  }
130 
131  // Option ckeck
132  if (opt_video_in.empty()) {
133  usage(argv, 0);
134  std::cout << "Error: " << std::endl << " No input video set using --in <video name> option." << std::endl;
135  return EXIT_FAILURE;
136  }
137  if (opt_select_frame && opt_video_out.empty()) {
138  usage(argv, 0);
139  std::cout << "Error: " << std::endl
140  << " --select option is enabled but no output video name is specified using --out <video> option."
141  << std::endl;
142  return EXIT_FAILURE;
143  }
144  if (opt_video_out_gray && opt_video_out.empty()) {
145  usage(argv, 0);
146  std::cout << "Error: " << std::endl
147  << " --out-gray option is enabled but no output video name is specified using --out <video> option."
148  << std::endl;
149  return EXIT_FAILURE;
150  }
151  if ((opt_video_out_stride > 1) && opt_video_out.empty()) {
152  usage(argv, 0);
153  std::cout << "Error: " << std::endl
154  << " --out-stride option is enabled but no output video name is specified using --out <video> option."
155  << std::endl;
156  return EXIT_FAILURE;
157  }
158  if ((opt_video_out_stride > 1) && opt_select_frame && !opt_video_out.empty()) {
159  usage(argv, 0);
160  std::cout << "Error: " << std::endl
161  << " --out-stride option is enabled but this option doesn't make sense with --select option."
162  << std::endl;
163  return EXIT_FAILURE;
164  }
165 
166  vpImage<vpRGBa> I;
168  vpVideoReader g;
169  g.setFileName(opt_video_in);
170  g.open(I);
171  std::cout << "Input video" << std::endl;
172  std::cout << " Video name : " << opt_video_in << std::endl;
173  std::cout << " Video dimension: " << I.getWidth() << " " << I.getHeight() << std::endl;
174  std::cout << " First image : " << g.getFirstFrameIndex() << std::endl;
175  std::cout << " Last image : " << g.getLastFrameIndex() << std::endl;
176  std::cout << " Framerate (fps): " << opt_display_fps << std::endl;
177 
178  vpVideoWriter writer;
179  if (!opt_video_out.empty()) {
180  writer.setFileName(opt_video_out);
181  int first_frame =
182  (opt_video_out_first_frame < 0 ? static_cast<int>(g.getFirstFrameIndex()) : opt_video_out_first_frame);
183  writer.setFirstFrameIndex(first_frame);
184  if (opt_video_out_gray) {
185  vpImageConvert::convert(I, Igray);
186  writer.open(Igray);
187  }
188  else {
189  writer.open(I);
190  }
191  std::cout << "Output video" << std::endl;
192  std::cout << " Video name : " << opt_video_out << std::endl;
193  std::cout << " First image : " << first_frame << std::endl;
194  std::cout << " Stride : " << opt_video_out_stride << std::endl;
195  std::cout << " Y8 gray images : " << (opt_video_out_gray ? "yes" : "no (same as input)") << std::endl;
196  }
197 
198  std::cout << "Other settings" << std::endl;
199  std::cout << " Verbose : " << (opt_verbose ? "enabled" : "disabled") << std::endl;
200  std::cout << " Select frames : " << (opt_select_frame ? "enabled" : "disabled") << std::endl;
201 
202  try {
204 #if defined(VISP_HAVE_X11)
205  vpDisplayX d(I, vpDisplay::SCALE_AUTO);
206 #elif defined(VISP_HAVE_GDI)
208 #elif defined(HAVE_OPENCV_HIGHGUI)
210 #elif defined(VISP_HAVE_GTK)
212 #elif defined(VISP_HAVE_D3D9)
214 #else
215  std::cout << "No image viewer is available..." << std::endl;
216 #endif
217  int scale = vpDisplay::getDownScalingFactor(I);
218  int cpt_stride = 1;
219 
220  while (!g.end()) {
221  double t = vpTime::measureTimeMs();
222  g.acquire(I);
223 
224  std::stringstream ss;
225  ss << "Image " << g.getFrameIndex();
226  vpDisplay::setTitle(I, ss.str());
228  vpDisplay::displayText(I, 15 * scale, 15 * scale, "Right click to quit", vpColor::red);
229  if (opt_select_frame) {
230  vpDisplay::displayText(I, 30 * scale, 15 * scale, "Left click to select frame", vpColor::red);
231  }
232  vpDisplay::flush(I);
233 
234  bool selected_frame = (opt_select_frame ? false : true);
236  if (vpDisplay::getClick(I, button, false)) {
237  if (button == vpMouseButton::button1 && opt_select_frame) {
238  selected_frame = true;
239  }
240  else if (button == vpMouseButton::button3) {
241  break;
242  }
243  }
244 
245  if (!opt_video_out.empty() && selected_frame) {
246  if (cpt_stride == opt_video_out_stride) {
247  cpt_stride = 1;
248  if (opt_video_out_gray) {
249  vpImageConvert::convert(I, Igray);
250  writer.saveFrame(Igray);
251  }
252  else {
253  writer.saveFrame(I);
254  }
255  if (opt_verbose) {
256  std::cout << "Save " << writer.getFrameName() << std::endl;
257  }
258  }
259  else {
260  cpt_stride++;
261  }
262  }
263 
264  if (opt_display_fps > 0) {
265  vpTime::wait(t, 1000. / opt_display_fps);
266  }
267  }
268  }
269  catch (const vpException &e) {
270  std::cout << "Catch an exception: " << e << std::endl;
271  }
272 }
static const vpColor red
Definition: vpColor.h:217
Display for windows using Direct3D 3rd party. Thus to enable this class Direct3D should be installed....
Definition: vpDisplayD3D.h:106
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:130
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
Definition: vpDisplayGTK.h:133
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 display(const vpImage< unsigned char > &I)
static void setTitle(const vpImage< unsigned char > &I, const std::string &windowtitle)
static void flush(const vpImage< unsigned char > &I)
@ SCALE_AUTO
Definition: vpDisplay.h:184
unsigned int getDownScalingFactor()
Definition: vpDisplay.h:221
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
error that can be emitted by ViSP classes.
Definition: vpException.h:60
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
unsigned int getWidth() const
Definition: vpImage.h:242
unsigned int getHeight() const
Definition: vpImage.h:181
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)
long getFirstFrameIndex()
long getFrameIndex() const
Class that enables to write easily a video file or a sequence of images.
void saveFrame(vpImage< vpRGBa > &I)
void setFileName(const std::string &filename)
void open(vpImage< vpRGBa > &I)
void setFirstFrameIndex(int first_frame)
std::string getFrameName() const
VISP_EXPORT int wait(double t0, double t)
VISP_EXPORT double measureTimeMs()