38 #include <MultiSense/MultiSenseChannel.hh>
41 #ifndef WIN32_LEAN_AND_MEAN
42 #define WIN32_LEAN_AND_MEAN 1
49 #include <arpa/inet.h>
72 volatile bool doneG =
false;
74 void usage(
const char *programNameP)
76 std::cerr <<
"USAGE: " << programNameP <<
" [<options>]" << std::endl;
77 std::cerr <<
"Where <options> are:" << std::endl;
78 std::cerr <<
"\t-a <current_address> : CURRENT IPV4 address (default=10.66.171.21)" << std::endl;
79 std::cerr <<
"\t-m <mtu> : CURRENT MTU (default=1500)" << std::endl;
80 std::cerr <<
"\t-c : Save color images and depth in the color image frame" << std::endl;
86 BOOL WINAPI signalHandler(DWORD dwCtrlType)
93 void signalHandler(
int sig)
103 std::shared_ptr<const ImageBufferWrapper> auxLumaRectified =
nullptr;
104 std::shared_ptr<const ImageBufferWrapper> auxChromaRectified =
nullptr;
110 std::vector<uint16_t> createDepthImage(
const image::Header &disparity,
115 const size_t width = disparity.
width;
116 const size_t height = disparity.
height;
122 const double xScale = 1.0 / ((
static_cast<double>(deviceInfo.
imagerWidth) /
123 static_cast<double>(width)));
125 const double yScale = 1.0 / ((
static_cast<double>(deviceInfo.
imagerHeight) /
126 static_cast<double>(height)));
136 const double fx = calibration.
left.
P[0][0] * xScale;
137 const double fy = calibration.
left.
P[1][1] * yScale;
138 const double cx = calibration.
left.
P[0][2] * xScale;
139 const double cy = calibration.
left.
P[1][2] * yScale;
140 const double tx = calibration.
right.
P[0][3] / calibration.
right.
P[0][0];
141 const double cxRight = calibration.
right.
P[0][2] * xScale;
143 const double auxFx = calibration.
aux.
P[0][0] * xScale;
144 const double auxFy = calibration.
aux.
P[1][1] * yScale;
145 const double auxCx = calibration.
aux.
P[0][2] * xScale;
146 const double auxCy = calibration.
aux.
P[1][2] * yScale;
147 const double auxFxTx = calibration.
aux.
P[0][3] * xScale;
148 const double auxFyTy = calibration.
aux.
P[1][3] * yScale;
149 const double auxTz = calibration.
aux.
P[2][3];
152 const uint16_t *disparityP =
reinterpret_cast<const uint16_t*
>(disparity.
imageDataP);
154 std::vector<uint16_t> pixels(height * width, 0);
156 const double max_ni_depth = std::numeric_limits<uint16_t>::max();
158 for (
size_t h = 0 ; h < height ; ++h) {
159 for (
size_t w = 0 ; w < width ; ++w) {
161 const size_t index = h * width + w;
167 const double d =
static_cast<double>(disparityP[index]) / 16.0;
182 const double xB = ((fy * tx) * w) + (-fy * cx * tx);
183 const double yB = ((fx * tx) * h) + (-fx * cy * tx);
184 const double zB = (fx * fy * tx);
185 const double invB = 1. / (-fy *
d) + (fy * (cx - cxRight));
188 size_t depthIndex = 0;
199 const double x = xB * invB;
200 const double y = yB * invB;
201 const double z = zB * invB;
203 depth =
static_cast<uint16_t
>(std::min(max_ni_depth, std::max(0.0, (z + auxTz) * 1000)));
205 const double u = ((auxFx * x) + (auxCx * z) + auxFxTx) / (z + auxTz);
206 const double v = ((auxFy * y) + (auxCy * z) + auxFyTy) / (z + auxTz);
208 depthIndex =
static_cast<int>(v) * width +
static_cast<int>(u);
210 if (u < 0 || v < 0 || u >= width || v >= height || depthIndex >= (width * height)) {
217 depth =
static_cast<uint16_t
>(std::min(max_ni_depth, std::max(0.0, (zB * invB) * 1000)));
222 pixels[depthIndex] = depth;
229 bool saveColor(
const std::string& fileName,
230 std::shared_ptr<const ImageBufferWrapper> leftRect,
231 std::shared_ptr<const ImageBufferWrapper> leftChromaRect)
233 std::vector<uint8_t> output(leftRect->data().width * leftRect->data().height * 3);
234 ycbcrToBgr(leftRect->data(), leftChromaRect->data(), output.data());
236 io::savePpm(fileName, leftRect->data().width, leftRect->data().height, output.data());
243 UserData *userData =
reinterpret_cast<UserData*
>(userDataP);
245 if (!userData->driver) {
246 std::cerr <<
"Invalid MultiSense channel" << std::endl;
263 if (
header.bitsPerPixel != 16) {
264 std::cerr <<
"Unsupported disparity pixel depth" << std::endl;
276 createDepthImage(header, userData->calibration, userData->deviceInfo, userData->hasAux).data());
282 userData->auxChromaRectified = std::make_shared<ImageBufferWrapper>(userData->driver, header);
284 if (userData->auxLumaRectified && userData->auxLumaRectified->data().frameId ==
header.frameId) {
286 userData->auxLumaRectified,
287 userData->auxChromaRectified);
293 userData->auxLumaRectified = std::make_shared<ImageBufferWrapper>(userData->driver, header);
295 if (userData->auxChromaRectified && userData->auxChromaRectified->data().frameId ==
header.frameId) {
297 userData->auxLumaRectified,
298 userData->auxChromaRectified);
304 std::cerr <<
"Unknown image source: " <<
header.source << std::endl;
315 std::string currentAddress =
"10.66.171.21";
317 bool useColor =
false;
320 SetConsoleCtrlHandler (signalHandler, TRUE);
322 signal(SIGINT, signalHandler);
330 while(-1 != (c =
getopt(argc, argvPP,
"a:m:c")))
332 case 'a': currentAddress = std::string(
optarg);
break;
333 case 'm': mtu = atoi(
optarg);
break;
334 case 'c': useColor =
true;
break;
335 default:
usage(*argvPP);
break;
343 auto channelP = std::make_unique<ChannelWrapper>(currentAddress);
344 if (
nullptr == channelP ||
nullptr == channelP->ptr()) {
345 std::cerr <<
"Failed to establish communications with \"" << currentAddress <<
"\"" << std::endl;
353 status = channelP->ptr()->setMtu(mtu);
355 status = channelP->ptr()->setBestMtu();
364 status = channelP->ptr()->getImageCalibration(calibration);
374 status = channelP->ptr()->getDeviceInfo(deviceInfo);
385 status = channelP->ptr()->getImageConfig(cfg);
393 status = channelP->ptr()->setImageConfig(cfg);
419 UserData userData{channelP->ptr(),
nullptr,
nullptr, calibration, deviceInfo, hasAux};
424 channelP->ptr()->addIsolatedCallback(imageCallback,
435 status = channelP->ptr()->startStreams(streams);
445 status = channelP->ptr()->stopStreams(
Source_All);