41 #ifdef RTABMAP_DEPTHAI
49 const std::string & mxidOrName,
53 Camera(imageRate, localTransform)
54 #ifdef RTABMAP_DEPTHAI
56 mxidOrName_(mxidOrName),
60 resolution_(resolution),
61 extendedDisparity_(
false),
62 subpixelFractionalBits_(0),
64 useSpecTranslation_(
false),
67 publishInterIMU_(
false),
71 useHarrisDetector_(
false),
73 numTargetFeatures_(1000),
79 #ifdef RTABMAP_DEPTHAI
80 UASSERT(resolution_>=(
int)dai::MonoCameraProperties::SensorResolution::THE_720_P && resolution_<=(
int)dai::MonoCameraProperties::SensorResolution::THE_1200_P);
86 #ifdef RTABMAP_DEPTHAI
96 #ifdef RTABMAP_DEPTHAI
97 outputMode_ = outputMode;
99 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
105 #ifdef RTABMAP_DEPTHAI
106 confThreshold_ = confThreshold;
107 lrcThreshold_ = lrcThreshold;
109 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
115 #ifdef RTABMAP_DEPTHAI
116 extendedDisparity_ = extendedDisparity;
117 if(extendedDisparity_)
119 if(subpixelFractionalBits_>0)
121 UWARN(
"Extended disparity has been enabled while subpixel being also enabled, disabling subpixel...");
122 subpixelFractionalBits_ = 0;
124 if(compandingWidth_>0)
126 UWARN(
"Extended disparity has been enabled while companding being also enabled, disabling companding...");
127 compandingWidth_ = 0;
131 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
137 #ifdef RTABMAP_DEPTHAI
138 UASSERT(fractionalBits>=3 && fractionalBits<=5);
139 subpixelFractionalBits_ = enabled?fractionalBits:0;
140 if(subpixelFractionalBits_ != 0 && extendedDisparity_)
142 UWARN(
"Subpixel has been enabled while extended disparity being also enabled, disabling extended disparity...");
143 extendedDisparity_ =
false;
146 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
152 #ifdef RTABMAP_DEPTHAI
153 UASSERT(width == 64 || width == 96);
154 compandingWidth_ = enabled?width:0;
155 if(compandingWidth_ != 0 && extendedDisparity_)
157 UWARN(
"Companding has been enabled while extended disparity being also enabled, disabling extended disparity...");
158 extendedDisparity_ =
false;
161 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
167 #ifdef RTABMAP_DEPTHAI
168 useSpecTranslation_ = useSpecTranslation;
169 alphaScaling_ = alphaScaling;
170 imagesRectified_ = enabled;
172 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
178 #ifdef RTABMAP_DEPTHAI
179 imuPublished_ = imuPublished;
182 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
188 #ifdef RTABMAP_DEPTHAI
189 dotIntensity_ = dotIntensity;
190 floodIntensity_ = floodIntensity;
192 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
198 #ifdef RTABMAP_DEPTHAI
199 detectFeatures_ = detectFeatures;
201 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
207 #ifdef RTABMAP_DEPTHAI
208 blobPath_ = blobPath;
210 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
216 #ifdef RTABMAP_DEPTHAI
217 useHarrisDetector_ = useHarrisDetector;
218 minDistance_ = minDistance;
219 numTargetFeatures_ = numTargetFeatures;
221 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
227 #ifdef RTABMAP_DEPTHAI
230 nmsRadius_ = nmsRadius;
232 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
239 #ifdef RTABMAP_DEPTHAI
241 std::vector<dai::DeviceInfo> devices = dai::Device::getAllAvailableDevices();
242 if(devices.empty() && mxidOrName_.empty())
244 UERROR(
"No DepthAI device found or specified");
254 bool deviceFound =
false;
255 dai::DeviceInfo deviceToUse(mxidOrName_);
256 if(mxidOrName_.empty())
257 std::tie(deviceFound, deviceToUse) = dai::Device::getFirstAvailableDevice();
258 else if(!deviceToUse.mxid.empty())
259 std::tie(deviceFound, deviceToUse) = dai::Device::getDeviceByMxId(deviceToUse.mxid);
265 UERROR(
"Could not find DepthAI device with MXID or IP/USB name \"%s\", found devices:", mxidOrName_.c_str());
266 for(
auto&
device : devices)
273 targetSize_ = cv::Size(resolution_<2?1280:resolution_==4?1920:640, resolution_==0?720:resolution_==1?800:resolution_==2?400:resolution_==3?480:1200);
276 auto monoLeft =
p.create<dai::node::MonoCamera>();
277 auto monoRight =
p.create<dai::node::MonoCamera>();
278 std::shared_ptr<dai::node::StereoDepth> stereo;
280 stereo =
p.create<dai::node::StereoDepth>();
281 std::shared_ptr<dai::node::Camera> colorCam;
284 colorCam =
p.create<dai::node::Camera>();
285 if(!imagesRectified_)
286 colorCam->setMeshSource(dai::CameraProperties::WarpMeshSource::NONE);
289 UWARN(
"On-device feature detectors cannot be enabled on color camera input!");
293 std::shared_ptr<dai::node::IMU> imu;
295 imu =
p.create<dai::node::IMU>();
296 std::shared_ptr<dai::node::FeatureTracker> gfttDetector;
297 std::shared_ptr<dai::node::ImageManip> manip;
298 std::shared_ptr<dai::node::NeuralNetwork> neuralNetwork;
299 if(detectFeatures_ == 1)
301 gfttDetector =
p.create<dai::node::FeatureTracker>();
303 else if(detectFeatures_ >= 2)
305 if(!blobPath_.empty())
307 manip =
p.create<dai::node::ImageManip>();
308 neuralNetwork =
p.create<dai::node::NeuralNetwork>();
312 UWARN(
"Missing MyriadX blob file!");
317 auto sync =
p.create<dai::node::Sync>();
318 auto xoutCamera =
p.create<dai::node::XLinkOut>();
319 std::shared_ptr<dai::node::XLinkOut> xoutIMU;
321 xoutIMU =
p.create<dai::node::XLinkOut>();
324 xoutCamera->setStreamName(
"camera");
326 xoutIMU->setStreamName(
"imu");
328 monoLeft->setResolution((dai::MonoCameraProperties::SensorResolution)resolution_);
329 monoRight->setResolution((dai::MonoCameraProperties::SensorResolution)resolution_);
330 monoLeft->setCamera(
"left");
331 monoRight->setCamera(
"right");
332 if(detectFeatures_ >= 2)
336 UWARN(
"On-device SuperPoint or HF-Net enabled, image rate is limited to 15 FPS!");
337 monoLeft->setFps(15);
338 monoRight->setFps(15);
351 stereo->setDepthAlign(dai::CameraBoardSocket::CAM_A);
353 stereo->setDepthAlign(dai::StereoDepthProperties::DepthAlign::RECTIFIED_LEFT);
354 stereo->setExtendedDisparity(extendedDisparity_);
355 stereo->setRectifyEdgeFillColor(0);
356 stereo->enableDistortionCorrection(
true);
357 stereo->setDisparityToDepthUseSpecTranslation(useSpecTranslation_);
358 stereo->setDepthAlignmentUseSpecTranslation(useSpecTranslation_);
359 if(alphaScaling_ > -1.0
f)
360 stereo->setAlphaScaling(alphaScaling_);
361 stereo->initialConfig.setConfidenceThreshold(confThreshold_);
362 stereo->initialConfig.setLeftRightCheck(lrcThreshold_>=0);
364 stereo->initialConfig.setLeftRightCheckThreshold(lrcThreshold_);
365 stereo->initialConfig.setMedianFilter(dai::MedianFilter::KERNEL_7x7);
366 auto config = stereo->initialConfig.get();
367 config.censusTransform.kernelSize = dai::StereoDepthConfig::CensusTransform::KernelSize::KERNEL_7x9;
368 config.censusTransform.kernelMask = 0X2AA00AA805540155;
369 config.postProcessing.brightnessFilter.maxBrightness = 255;
370 stereo->initialConfig.set(
config);
373 monoLeft->out.link(stereo->left);
374 monoRight->out.link(stereo->right);
379 colorCam->setBoardSocket(dai::CameraBoardSocket::CAM_A);
380 colorCam->setSize(targetSize_.width, targetSize_.height);
383 if(alphaScaling_ > -1.0
f)
384 colorCam->setCalibrationAlpha(alphaScaling_);
389 if(deviceToUse.protocol == X_LINK_TCP_IP || mxidOrName_.find(
".") != std::string::npos)
391 auto leftOrColorEnc =
p.create<dai::node::VideoEncoder>();
392 auto depthOrRightEnc =
p.create<dai::node::VideoEncoder>();
393 leftOrColorEnc->setDefaultProfilePreset(monoLeft->getFps(), dai::VideoEncoderProperties::Profile::MJPEG);
394 depthOrRightEnc->setDefaultProfilePreset(monoRight->getFps(), dai::VideoEncoderProperties::Profile::MJPEG);
397 if(imagesRectified_) {
398 stereo->rectifiedLeft.link(leftOrColorEnc->input);
401 monoLeft->out.link(leftOrColorEnc->input);
403 leftOrColorEnc->bitstream.link(sync->inputs[
"left"]);
407 colorCam->video.link(leftOrColorEnc->input);
408 leftOrColorEnc->bitstream.link(sync->inputs[
"color"]);
410 if(imagesRectified_ && outputMode_)
412 depthOrRightEnc->setQuality(100);
413 stereo->disparity.link(depthOrRightEnc->input);
414 depthOrRightEnc->bitstream.link(sync->inputs[
"depth"]);
418 if(imagesRectified_) {
419 stereo->rectifiedRight.link(depthOrRightEnc->input);
422 monoRight->out.link(depthOrRightEnc->input);
424 depthOrRightEnc->bitstream.link(sync->inputs[
"right"]);
430 stereo->setSubpixel(subpixelFractionalBits_>=3 && subpixelFractionalBits_<=5);
431 if(subpixelFractionalBits_>=3 && subpixelFractionalBits_<=5)
432 stereo->setSubpixelFractionalBits(subpixelFractionalBits_);
433 auto config = stereo->initialConfig.get();
434 config.costMatching.enableCompanding = compandingWidth_>0;
435 if(compandingWidth_>0)
436 config.costMatching.disparityWidth = compandingWidth_==64?dai::StereoDepthConfig::CostMatching::DisparityWidth::DISPARITY_64:dai::StereoDepthConfig::CostMatching::DisparityWidth::DISPARITY_96;
437 stereo->initialConfig.set(
config);
442 stereo->rectifiedLeft.link(sync->inputs[
"left"]);
444 monoLeft->out.link(sync->inputs[
"left"]);
448 monoLeft->setResolution(dai::MonoCameraProperties::SensorResolution::THE_400_P);
449 monoRight->setResolution(dai::MonoCameraProperties::SensorResolution::THE_400_P);
450 colorCam->video.link(sync->inputs[
"color"]);
452 if(imagesRectified_) {
454 stereo->depth.link(sync->inputs[
"depth"]);
456 stereo->rectifiedRight.link(sync->inputs[
"right"]);
459 monoRight->out.link(sync->inputs[
"right"]);
463 sync->setSyncThreshold(std::chrono::milliseconds(
int(500 / monoLeft->getFps())));
464 sync->out.link(xoutCamera->input);
469 imu->enableIMUSensor({dai::IMUSensor::ACCELEROMETER_RAW, dai::IMUSensor::GYROSCOPE_RAW}, 200);
471 imu->setBatchReportThreshold(1);
475 imu->setMaxBatchReports(10);
478 imu->out.link(xoutIMU->input);
481 if(detectFeatures_ == 1)
483 gfttDetector->setHardwareResources(1, 2);
484 gfttDetector->initialConfig.setCornerDetector(
485 useHarrisDetector_?dai::FeatureTrackerConfig::CornerDetector::Type::HARRIS:dai::FeatureTrackerConfig::CornerDetector::Type::SHI_THOMASI);
486 gfttDetector->initialConfig.setNumTargetFeatures(numTargetFeatures_);
487 gfttDetector->initialConfig.setMotionEstimator(
false);
488 auto cfg = gfttDetector->initialConfig.get();
489 cfg.featureMaintainer.minimumDistanceBetweenFeatures = minDistance_ * minDistance_;
490 gfttDetector->initialConfig.set(cfg);
492 stereo->rectifiedLeft.link(gfttDetector->inputImage);
494 monoLeft->out.link(gfttDetector->inputImage);
495 gfttDetector->outputFeatures.link(sync->inputs[
"feat"]);
497 else if(detectFeatures_ >= 2)
499 manip->setKeepAspectRatio(
false);
500 manip->setMaxOutputFrameSize(320 * 200);
501 manip->initialConfig.setResize(320, 200);
502 neuralNetwork->setBlobPath(blobPath_);
503 neuralNetwork->setNumInferenceThreads(2);
504 neuralNetwork->setNumNCEPerInferenceThread(1);
505 neuralNetwork->input.setBlocking(
false);
507 stereo->rectifiedLeft.link(manip->inputImage);
509 monoLeft->out.link(manip->inputImage);
510 manip->out.link(neuralNetwork->input);
511 neuralNetwork->out.link(sync->inputs[
"feat"]);
514 device_.reset(
new dai::Device(
p, deviceToUse));
516 UINFO(
"Device serial: %s", device_->getMxId().c_str());
517 UINFO(
"Available camera sensors: ");
518 for(
auto& sensor : device_->getCameraSensorNames()) {
519 UINFO(
"Socket: CAM_%c - %s",
'A'+(
unsigned char)sensor.first, sensor.second.c_str());
522 UINFO(
"Loading eeprom calibration data");
523 dai::CalibrationHandler calibHandler = device_->readCalibration();
525 if(!calibrationFolder.empty() && !cameraName.empty() && imagesRectified_)
527 UINFO(
"Flashing camera...");
530 stereoModel_.setName(cameraName,
"rgb",
"depth");
532 if(stereoModel_.load(calibrationFolder, cameraName,
false))
534 std::vector<std::vector<float> > intrinsicsLeft(3);
535 std::vector<std::vector<float> > intrinsicsRight(3);
538 intrinsicsLeft[
row].resize(3);
539 intrinsicsRight[
row].resize(3);
542 intrinsicsLeft[
row][
col] = stereoModel_.left().K_raw().at<
double>(
row,
col);
543 intrinsicsRight[
row][
col] = stereoModel_.right().K_raw().at<
double>(
row,
col);
547 std::vector<float> distortionsLeft = stereoModel_.left().D_raw();
548 std::vector<float> distortionsRight = stereoModel_.right().D_raw();
549 std::vector<std::vector<float> > rotationMatrix(3);
552 rotationMatrix[
row].resize(3);
555 rotationMatrix[
row][
col] = stereoModel_.stereoTransform()(
row,
col);
560 translation[0] = stereoModel_.stereoTransform().x()*100.0f;
561 translation[1] = stereoModel_.stereoTransform().y()*100.0f;
562 translation[2] = stereoModel_.stereoTransform().z()*100.0f;
567 calibHandler.setCameraIntrinsics(dai::CameraBoardSocket::CAM_A, intrinsicsLeft, stereoModel_.left().imageWidth(), stereoModel_.left().imageHeight());
568 calibHandler.setDistortionCoefficients(dai::CameraBoardSocket::CAM_A, distortionsLeft);
569 std::vector<float> specTranslation = calibHandler.getCameraTranslationVector(dai::CameraBoardSocket::CAM_A, dai::CameraBoardSocket::CAM_C,
true);
570 calibHandler.setCameraExtrinsics(dai::CameraBoardSocket::CAM_A, dai::CameraBoardSocket::CAM_C, rotationMatrix,
translation, specTranslation);
574 calibHandler.setCameraIntrinsics(dai::CameraBoardSocket::CAM_B, intrinsicsLeft, stereoModel_.left().imageWidth(), stereoModel_.left().imageHeight());
575 calibHandler.setDistortionCoefficients(dai::CameraBoardSocket::CAM_B, distortionsLeft);
576 calibHandler.setCameraIntrinsics(dai::CameraBoardSocket::CAM_C, intrinsicsRight, stereoModel_.right().imageWidth(), stereoModel_.right().imageHeight());
577 calibHandler.setDistortionCoefficients(dai::CameraBoardSocket::CAM_C, distortionsRight);
578 std::vector<float> specTranslation = calibHandler.getCameraTranslationVector(dai::CameraBoardSocket::CAM_B, dai::CameraBoardSocket::CAM_C,
true);
579 calibHandler.setCameraExtrinsics(dai::CameraBoardSocket::CAM_B, dai::CameraBoardSocket::CAM_C, rotationMatrix,
translation, specTranslation);
583 UINFO(
"Flashing camera with calibration from %s with camera name %s", calibrationFolder.c_str(), cameraName.c_str());
586 std::cout <<
"K left: " << stereoModel_.left().K_raw() << std::endl;
587 std::cout <<
"K right: " << stereoModel_.right().K_raw() << std::endl;
588 std::cout <<
"D left: " << stereoModel_.left().D_raw() << std::endl;
589 std::cout <<
"D right: " << stereoModel_.right().D_raw() << std::endl;
590 std::cout <<
"Extrinsics: " << stereoModel_.stereoTransform() << std::endl;
591 std::cout <<
"Expected K with rectification_alpha=0: " << stereoModel_.left().K()*(double(targetSize_.width)/double(stereoModel_.left().imageWidth())) << std::endl;
593 device_->flashCalibration2(calibHandler);
594 UINFO(
"Closing device...");
596 UINFO(
"Restarting pipeline...");
597 device_.reset(
new dai::Device(
p, deviceToUse));
599 catch(
const std::runtime_error &
e) {
600 UERROR(
"Failed flashing calibration: %s",
e.what());
605 UERROR(
"Failed loading calibration from %s with camera name %s", calibrationFolder.c_str(), cameraName.c_str());
609 calibHandler = device_->readCalibration();
612 auto eeprom = calibHandler.getEepromData();
613 UINFO(
"Product name: %s, board name: %s", eeprom.productName.c_str(), eeprom.boardName.c_str());
615 auto cameraId = outputMode_<2?dai::CameraBoardSocket::CAM_B:dai::CameraBoardSocket::CAM_A;
616 cv::Mat cameraMatrix, distCoeffs, newCameraMatrix;
618 std::vector<std::vector<float> >
matrix = calibHandler.getCameraIntrinsics(cameraId, targetSize_.width, targetSize_.height);
619 cameraMatrix = (cv::Mat_<double>(3,3) <<
624 std::vector<float> coeffs = calibHandler.getDistortionCoefficients(cameraId);
625 if(calibHandler.getDistortionModel(cameraId) == dai::CameraModel::Perspective)
626 distCoeffs = (cv::Mat_<double>(1,8) << coeffs[0], coeffs[1], coeffs[2], coeffs[3], coeffs[4], coeffs[5], coeffs[6], coeffs[7]);
628 if(alphaScaling_>-1.0
f)
629 newCameraMatrix = cv::getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, targetSize_, alphaScaling_);
631 newCameraMatrix = cameraMatrix;
633 double fx = newCameraMatrix.at<
double>(0, 0);
634 double fy = newCameraMatrix.at<
double>(1, 1);
635 double cx = newCameraMatrix.at<
double>(0, 2);
636 double cy = newCameraMatrix.at<
double>(1, 2);
637 UINFO(
"fx=%f fy=%f cx=%f cy=%f (target size = %dx%d)",
fx,
fy,
cx,
cy, targetSize_.width, targetSize_.height);
638 if(outputMode_ == 2) {
642 double baseline = calibHandler.getBaselineDistance(dai::CameraBoardSocket::CAM_C, dai::CameraBoardSocket::CAM_B,
false)/100.0;
644 stereoModel_ =
StereoCameraModel(device_->getDeviceName(),
fx,
fy,
cx,
cy, outputMode_==0?
baseline:0,
this->getLocalTransform()*
Transform(-calibHandler.getBaselineDistance(dai::CameraBoardSocket::CAM_A)/100.0, 0, 0), targetSize_);
656 if(eeprom.boardName ==
"OAK-D" ||
657 eeprom.boardName ==
"BW1098OBC")
664 else if(eeprom.boardName ==
"DM9098")
671 else if(eeprom.boardName ==
"NG2094")
678 else if(eeprom.boardName ==
"NG9097")
687 UWARN(
"Unknown boardName (%s)! Disabling IMU!", eeprom.boardName.c_str());
688 imuPublished_ =
false;
693 UINFO(
"IMU disabled");
696 cameraQueue_ = device_->getOutputQueue(
"camera", 8,
false);
700 UINFO(
"IMU local transform = %s", imuLocalTransform_.prettyPrint().c_str());
701 device_->getOutputQueue(
"imu", 50,
false)->addCallback([
this](
const std::shared_ptr<dai::ADatatype>
data) {
702 auto imuData = std::dynamic_pointer_cast<dai::IMUData>(
data);
703 auto imuPackets = imuData->packets;
705 for(
auto& imuPacket : imuPackets)
707 auto& acceleroValues = imuPacket.acceleroMeter;
708 auto& gyroValues = imuPacket.gyroscope;
709 double accStamp = std::chrono::duration<double>(acceleroValues.getTimestampDevice().time_since_epoch()).count();
710 double gyroStamp = std::chrono::duration<double>(gyroValues.getTimestampDevice().time_since_epoch()).count();
714 IMU imu(cv::Vec3f(gyroValues.x, gyroValues.y, gyroValues.z), cv::Mat::eye(3,3,CV_64FC1),
715 cv::Vec3f(acceleroValues.x, acceleroValues.y, acceleroValues.z), cv::Mat::eye(3,3,CV_64FC1),
722 accBuffer_.emplace_hint(accBuffer_.end(), accStamp, cv::Vec3f(acceleroValues.x, acceleroValues.y, acceleroValues.z));
723 gyroBuffer_.emplace_hint(gyroBuffer_.end(), gyroStamp, cv::Vec3f(gyroValues.x, gyroValues.y, gyroValues.z));
729 if(!device_->getIrDrivers().empty())
731 UINFO(
"Setting IR intensity");
732 device_->setIrLaserDotProjectorIntensity(dotIntensity_);
733 device_->setIrFloodLightIntensity(floodIntensity_);
735 else if(dotIntensity_ > 0 || floodIntensity_ > 0)
737 UWARN(
"No IR drivers were detected! IR intensity cannot be set.");
744 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
751 #ifdef RTABMAP_DEPTHAI
752 return outputMode_ == 0?stereoModel_.isValidForProjection():stereoModel_.left().isValidForProjection();
760 #ifdef RTABMAP_DEPTHAI
761 return device_->getMxId();
769 #ifdef RTABMAP_DEPTHAI
771 auto messageGroup = cameraQueue_->get<dai::MessageGroup>();
772 auto rectifLeftOrColor = messageGroup->get<dai::ImgFrame>(outputMode_<2?
"left":
"color");
773 auto rectifRightOrDepth = messageGroup->get<dai::ImgFrame>(imagesRectified_ && outputMode_?
"depth":
"right");
775 cv::Mat leftOrColor, depthOrRight;
776 if(device_->getDeviceInfo().protocol == X_LINK_TCP_IP || mxidOrName_.find(
".") != std::string::npos)
778 leftOrColor = cv::imdecode(rectifLeftOrColor->getData(), cv::IMREAD_ANYCOLOR);
779 depthOrRight = cv::imdecode(rectifRightOrDepth->getData(), cv::IMREAD_GRAYSCALE);
780 if(imagesRectified_ && outputMode_)
783 depthOrRight.convertTo(disp, CV_16UC1);
784 cv::divide(-stereoModel_.right().Tx() * 1000, disp, depthOrRight);
789 leftOrColor = rectifLeftOrColor->getCvFrame();
790 depthOrRight = rectifRightOrDepth->getCvFrame();
793 double stamp = std::chrono::duration<double>(rectifLeftOrColor->getTimestampDevice(dai::CameraExposureOffset::MIDDLE).time_since_epoch()).count();
794 if(imagesRectified_ && outputMode_)
795 data =
SensorData(leftOrColor, depthOrRight, stereoModel_.left(),
this->getNextSeqID(), stamp);
802 std::map<double, cv::Vec3f>::const_iterator iterA, iterB;
805 while(accBuffer_.empty() || gyroBuffer_.empty() || accBuffer_.rbegin()->first < stamp || gyroBuffer_.rbegin()->first < stamp)
813 iterB = accBuffer_.lower_bound(stamp);
815 if(iterA != accBuffer_.begin())
817 if(iterA == iterB || stamp == iterB->first)
821 else if(stamp > iterA->first && stamp < iterB->
first)
823 float t = (stamp-iterA->first) / (iterB->first-iterA->first);
824 acc = iterA->second +
t*(iterB->second - iterA->second);
826 accBuffer_.erase(accBuffer_.begin(), iterB);
829 iterB = gyroBuffer_.lower_bound(stamp);
831 if(iterA != gyroBuffer_.begin())
833 if(iterA == iterB || stamp == iterB->first)
835 gyro = iterB->second;
837 else if(stamp > iterA->first && stamp < iterB->
first)
839 float t = (stamp-iterA->first) / (iterB->first-iterA->first);
840 gyro = iterA->second +
t*(iterB->second - iterA->second);
842 gyroBuffer_.erase(gyroBuffer_.begin(), iterB);
845 data.setIMU(
IMU(gyro, cv::Mat::eye(3, 3, CV_64FC1), acc, cv::Mat::eye(3, 3, CV_64FC1), imuLocalTransform_));
848 if(detectFeatures_ == 1)
850 auto features = messageGroup->get<dai::TrackedFeatures>(
"feat")->trackedFeatures;
851 std::vector<cv::KeyPoint> keypoints;
852 for(
auto& feature : features)
853 keypoints.emplace_back(cv::KeyPoint(feature.position.x, feature.position.y, 3));
854 data.setFeatures(keypoints, std::vector<cv::Point3f>(), cv::Mat());
856 else if(detectFeatures_ >= 2)
858 auto features = messageGroup->get<dai::NNData>(
"feat");
859 std::vector<float> scores_dense, local_descriptor_map, global_descriptor;
860 if(detectFeatures_ == 2)
862 scores_dense = features->getLayerFp16(
"heatmap");
863 local_descriptor_map = features->getLayerFp16(
"desc");
865 else if(detectFeatures_ == 3)
867 scores_dense = features->getLayerFp16(
"pred/local_head/detector/Squeeze");
868 local_descriptor_map = features->getLayerFp16(
"pred/local_head/descriptor/transpose");
869 global_descriptor = features->getLayerFp16(
"pred/global_head/l2_normalize_1");
872 cv::Mat scores(200, 320, CV_32FC1, scores_dense.data());
873 cv::resize(scores, scores, targetSize_, 0, 0, cv::INTER_CUBIC);
876 cv::Mat dilated_scores(targetSize_, CV_32FC1);
877 cv::dilate(scores, dilated_scores, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(nmsRadius_*2+1, nmsRadius_*2+1)));
878 cv::Mat max_mask = scores == dilated_scores;
879 cv::dilate(scores, dilated_scores, cv::Mat());
880 cv::Mat max_mask_r1 = scores == dilated_scores;
881 cv::Mat supp_mask(targetSize_, CV_8UC1);
882 for(
size_t i=0;
i<2;
i++)
884 cv::dilate(max_mask, supp_mask, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(nmsRadius_*2+1, nmsRadius_*2+1)));
885 cv::Mat supp_scores = scores.clone();
886 supp_scores.setTo(0, supp_mask);
887 cv::dilate(supp_scores, dilated_scores, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(nmsRadius_*2+1, nmsRadius_*2+1)));
888 cv::Mat new_max_mask = cv::Mat::zeros(targetSize_, CV_8UC1);
889 cv::bitwise_not(supp_mask, supp_mask);
890 cv::bitwise_and(supp_scores == dilated_scores, supp_mask, new_max_mask, max_mask_r1);
891 cv::bitwise_or(max_mask, new_max_mask, max_mask);
893 cv::bitwise_not(max_mask, supp_mask);
894 scores.setTo(0, supp_mask);
897 std::vector<cv::Point> kpts;
899 std::vector<cv::KeyPoint> keypoints;
900 for(
auto& kpt : kpts)
902 float response = scores.at<
float>(kpt);
903 keypoints.emplace_back(cv::KeyPoint(kpt, 8, -1, response));
906 cv::Mat coarse_desc(25, 40, CV_32FC(256), local_descriptor_map.data());
907 if(detectFeatures_ == 2)
908 coarse_desc.forEach<cv::Vec<float, 256>>([&](cv::Vec<float, 256>&
descriptor,
const int position[]) ->
void {
911 cv::Mat mapX(keypoints.size(), 1, CV_32FC1);
912 cv::Mat mapY(keypoints.size(), 1, CV_32FC1);
913 for(
size_t i=0;
i<keypoints.size(); ++
i)
915 mapX.at<
float>(
i) = (keypoints[
i].pt.x - (targetSize_.width-1)/2) * 40/targetSize_.width + (40-1)/2;
916 mapY.at<
float>(
i) = (keypoints[
i].pt.y - (targetSize_.height-1)/2) * 25/targetSize_.height + (25-1)/2;
918 cv::Mat map1, map2, descriptors;
919 cv::convertMaps(mapX, mapY, map1, map2, CV_16SC2);
920 cv::remap(coarse_desc, descriptors, map1, map2, cv::INTER_LINEAR);
921 descriptors.forEach<cv::Vec<float, 256>>([&](cv::Vec<float, 256>&
descriptor,
const int position[]) ->
void {
924 descriptors = descriptors.reshape(1);
926 data.setFeatures(keypoints, std::vector<cv::Point3f>(), descriptors);
927 if(detectFeatures_ == 3)
928 data.addGlobalDescriptor(
GlobalDescriptor(1, cv::Mat(1, global_descriptor.size(), CV_32FC1, global_descriptor.data()).clone()));
932 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");