LibMultiSense/SaveImageUtility/SaveImageUtility.cc
Go to the documentation of this file.
1 
37 #ifdef WIN32
38 #ifndef WIN32_LEAN_AND_MEAN
39 #define WIN32_LEAN_AND_MEAN 1
40 #endif
41 
42 #include <windows.h>
43 #include <winsock2.h>
44 #else
45 #include <unistd.h>
46 #endif
47 
48 #include <csignal>
49 #include <iostream>
50 #include <thread>
51 
52 #include <MultiSense/MultiSenseChannel.hh>
54 
55 #include "getopt/getopt.h"
56 
57 
58 namespace lms = multisense;
59 
60 namespace
61 {
62 
63 volatile bool done = false;
64 
65 void usage(const char *name)
66 {
67  std::cerr << "USAGE: " << name << " [<options>]" << std::endl;
68  std::cerr << "Where <options> are:" << std::endl;
69  std::cerr << "\t-a <current-address> : CURRENT IPV4 address (default=10.66.171.21)" << std::endl;
70  std::cerr << "\t-m <mtu> : MTU to use to communicate with the camera (default=1500)" << std::endl;
71  std::cerr << "\t-n <number-of-images> : Number of images to save (default=1)" << std::endl;
72  std::cerr << "\t-d : Save depth images" << std::endl;
73  std::cerr << "\t-l : Save left rectified images" << std::endl;
74  std::cerr << "\t-c : Save color images" << std::endl;
75  exit(1);
76 }
77 
78 void save_image(const lms::ImageFrame &frame, const lms::DataSource &source)
79 {
80  const auto base_path = std::to_string(frame.frame_id) + "_" +
81  std::to_string(static_cast<int>(source));
82  switch (source)
83  {
84  case lms::DataSource::LEFT_DISPARITY_RAW:
85  {
86  if (const auto depth_image = lms::create_depth_image(frame,
87  lms::Image::PixelFormat::MONO16,
88  source,
89  65535); depth_image)
90  {
91  lms::write_image(depth_image.value(), base_path + ".pgm");
92  }
93  break;
94  }
95  case lms::DataSource::LEFT_RECTIFIED_RAW:
96  {
97  lms::write_image(frame.get_image(source), base_path + ".pgm");
98  break;
99  }
100  case lms::DataSource::AUX_RAW:
101  {
102  if (const auto bgr = create_bgr_image(frame, source); bgr)
103  {
104  lms::write_image(bgr.value(), base_path+".ppm");
105  }
106  break;
107  }
108  default: return;
109  }
110 }
111 
112 #ifdef WIN32
113 BOOL WINAPI signal_handler(DWORD dwCtrlType)
114 {
115  (void) dwCtrlType;
116  done = true;
117  return TRUE;
118 }
119 #else
120 void signal_handler(int sig)
121 {
122  (void) sig;
123  done = true;
124 }
125 #endif
126 
127 }
128 
129 int main(int argc, char** argv)
130 {
131  using namespace std::chrono_literals;
132 
133 #if WIN32
134  SetConsoleCtrlHandler (signal_handler, TRUE);
135 #else
136  signal(SIGINT, signal_handler);
137 #endif
138 
139  std::string ip_address = "10.66.171.21";
140  int16_t mtu = 1500;
141  size_t number_of_images = 1;
142  bool save_depth = false;
143  bool save_left_rect = false;
144  bool save_color = false;
145 
146  int c;
147  while(-1 != (c = getopt(argc, argv, "a:m:n:dlc")))
148  {
149  switch(c)
150  {
151  case 'a': ip_address = std::string(optarg); break;
152  case 'm': mtu = static_cast<uint16_t>(atoi(optarg)); break;
153  case 'n': number_of_images = static_cast<size_t>(atoi(optarg)); break;
154  case 'd': save_depth = true; break;
155  case 'l': save_left_rect = true; break;
156  case 'c': save_color = true; break;
157  default: usage(*argv); break;
158  }
159  }
160 
161  const auto channel = lms::Channel::create(lms::Channel::Config{ip_address, mtu});
162  if (!channel)
163  {
164  std::cerr << "Failed to create channel" << std::endl;;
165  return 1;
166  }
167 
168  //
169  // Query Static info from the camera
170  //
171  auto info = channel->get_info();
172 
173  std::cout << "Firmware build date : " << info.version.firmware_build_date << std::endl;
174  std::cout << "Firmware version : " << info.version.firmware_version.to_string() << std::endl;
175  std::cout << "Hardware version : 0x" << std::hex << info.version.hardware_version << std::endl;
176  std::cout << std::dec;
177 
178  //
179  // QuerySet dynamic config from the camera
180  //
181  auto config = channel->get_config();
182  config.frames_per_second = 9.0;
183  if (const auto status = channel->set_config(config); status != lms::Status::OK)
184  {
185  std::cerr << "Cannot set config: " << lms::to_string(status) << std::endl;
186  return 1;
187  }
188 
189  std::vector<lms::DataSource> image_streams{};
190  if (save_depth) image_streams.push_back(lms::DataSource::LEFT_DISPARITY_RAW);
191  if (save_left_rect) image_streams.push_back(lms::DataSource::LEFT_RECTIFIED_RAW);
192  if (save_color) image_streams.push_back(lms::DataSource::AUX_RAW);
193 
194  if (image_streams.empty())
195  {
196  std::cerr << "No image streams requested" << std::endl;
197  return 0;
198  }
199 
200  //
201  // Start a single image stream
202  //
203  if (const auto status = channel->start_streams(image_streams); status != lms::Status::OK)
204  {
205  std::cerr << "Cannot start streams: " << lms::to_string(status) << std::endl;
206  return 1;
207  }
208 
209  //
210  // Only save the first image
211  //
212  size_t saved_images = 0;
213 
214  while(!done)
215  {
216  if (saved_images < number_of_images)
217  {
218  if (const auto image_frame = channel->get_next_image_frame(); image_frame)
219  {
220  for (const auto &stream : image_streams)
221  {
222  save_image(image_frame.value(), stream);
223  }
224 
225  ++saved_images;
226  }
227  }
228 
229  if (const auto status = channel->get_system_status(); status)
230  {
231  if (status->time) std::cout << "Camera Time(ns): " << status->time->camera_time.count() << ", ";
232  std::cout << "System Ok: " << status->system_ok << ", ";
233  if (status->temperature) std::cout << "FPGA Temp (C): " << status->temperature->fpga_temperature << ", ";
234  if (status->temperature) std::cout << "Left Imager Temp (C): " << status->temperature->left_imager_temperature << ", ";
235  if (status->temperature) std::cout << "Right Imager Temp (C): " << status->temperature->right_imager_temperature << ", ";
236  if (status->power) std::cout << "Input Voltage (V): " << status->power->input_voltage << ", ";
237  if (status->power) std::cout << "Input Current (A): " << status->power->input_current << ", ";
238  if (status->power) std::cout << "FPGA Power (W): " << status->power->fpga_power << " , ";
239  std::cout << "Received Messages: " << status->client_network.received_messages << " , ";
240  std::cout << "Dropped Messages: " << status->client_network.dropped_messages << std::endl;
241  }
242  else
243  {
244  std::cerr << "Failed to query sensor status" << std::endl;
245  }
246 
247  std::this_thread::sleep_for(1s);
248  }
249 
250  channel->stop_streams({lms::DataSource::ALL});
251 
252  return 0;
253 }
usage
static void usage()
Definition: FirmwareUpdateUtility.cc:51
multisense::create_bgr_image
std::optional< Image > create_bgr_image(const ImageFrame &frame, const DataSource &output_source)
Convert a YCbCr420 luma + chroma image into a BGR color image.
Definition: utilities.cc:340
multisense::ImageFrame::get_image
const Image & get_image(const DataSource &source) const
Retrieve image by DataSource. Throws if not found.
Definition: LibMultiSense/include/MultiSense/MultiSenseTypes.hh:313
getopt.h
getopt
int getopt(int argc, char **argv, char *opts)
Definition: getopt.c:31
multisense::ImageFrame
A frame containing multiple images (indexed by DataSource).
Definition: LibMultiSense/include/MultiSense/MultiSenseTypes.hh:300
MultiSenseUtilities.hh
main
int main(int argc, char **argv)
Definition: LibMultiSense/SaveImageUtility/SaveImageUtility.cc:129
multisense::DataSource
DataSource
Identifies which camera or data source the image is from.
Definition: LibMultiSense/include/MultiSense/MultiSenseTypes.hh:83
multisense::create_depth_image
std::optional< Image > create_depth_image(const ImageFrame &frame, const Image::PixelFormat &depth_format, const DataSource &disparity_source, float invalid_value)
Create a depth image from a image frame.
Definition: utilities.cc:191
save_image_utility.save_image
def save_image(frame, source)
Definition: save_image_utility.py:65
multisense::ImageFrame::frame_id
int64_t frame_id
The unique monotonically increasing ID for each frame populated by the MultiSense.
Definition: LibMultiSense/include/MultiSense/MultiSenseTypes.hh:334
multisense::Channel::create
static std::unique_ptr< Channel > create(const Config &config, const ChannelImplementation &impl=ChannelImplementation::LEGACY)
Factory create function which allows for switching between different channel implementations.
Definition: factory.cc:42
multisense
Definition: factory.cc:39
signal_handler
static void signal_handler(int signal)
Definition: FirmwareUpdateUtility.cc:190
multisense::write_image
bool write_image(const Image &image, const std::filesystem::path &path)
Write a image to a specific path on disk. The type of serialization is determined by the input path.
Definition: utilities.cc:176
optarg
char * optarg
Definition: getopt.c:29
multisense::to_string
std::string to_string(const Status &status)
Convert a status object to a user readable string.
Definition: utilities.cc:137


multisense_lib
Author(s):
autogenerated on Thu Apr 17 2025 02:49:09