41 #ifdef RTABMAP_DEPTHAI
49 const std::string & mxidOrName,
53 Camera(imageRate, localTransform)
54 #ifdef RTABMAP_DEPTHAI
56 mxidOrName_(mxidOrName),
60 imageWidth_(imageWidth),
61 extendedDisparity_(
false),
62 enableCompanding_(
false),
63 subpixelFractionalBits_(3),
66 useSpecTranslation_(
false),
68 imagesRectified_(
true),
70 publishInterIMU_(
false),
74 useHarrisDetector_(
false),
76 numTargetFeatures_(320),
82 #ifdef RTABMAP_DEPTHAI
83 UASSERT(imageWidth_ == 640 || imageWidth_ == 1280);
91 #ifdef RTABMAP_DEPTHAI
99 #ifdef RTABMAP_DEPTHAI
100 outputMode_ = outputMode;
102 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
108 #ifdef RTABMAP_DEPTHAI
109 confThreshold_ = confThreshold;
110 lrcThreshold_ = lrcThreshold;
112 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
118 #ifdef RTABMAP_DEPTHAI
119 extendedDisparity_ = extendedDisparity;
120 enableCompanding_ = enableCompanding;
121 if(extendedDisparity_ && enableCompanding_)
123 UWARN(
"Extended disparity has been enabled while companding being also enabled, disabling companding...");
124 enableCompanding_ =
false;
127 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
133 #ifdef RTABMAP_DEPTHAI
134 UASSERT(fractionalBits>=3 && fractionalBits<=5);
135 subpixelFractionalBits_ = enabled?fractionalBits:0;
137 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
143 #ifdef RTABMAP_DEPTHAI
144 UASSERT(disparityWidth == 64 || disparityWidth == 96);
145 disparityWidth_ = disparityWidth;
146 medianFilter_ = medianFilter;
147 int maxDisp = (extendedDisparity_?2:1) *
std::pow(2,subpixelFractionalBits_) * (disparityWidth_-1);
148 if(medianFilter_ && maxDisp > 1024)
150 UWARN(
"Maximum disparity value '%d' exceeds the maximum supported '1024' by median filter, disabling median filter...", maxDisp);
154 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
160 #ifdef RTABMAP_DEPTHAI
161 useSpecTranslation_ = useSpecTranslation;
162 alphaScaling_ = alphaScaling;
163 imagesRectified_ = enabled;
165 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
171 #ifdef RTABMAP_DEPTHAI
172 imuPublished_ = imuPublished;
175 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
181 #ifdef RTABMAP_DEPTHAI
182 dotIntensity_ = dotIntensity;
183 floodIntensity_ = floodIntensity;
185 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
191 #ifdef RTABMAP_DEPTHAI
192 detectFeatures_ = detectFeatures;
193 blobPath_ = blobPath;
194 if(detectFeatures_>=2 && blobPath_.empty())
196 UWARN(
"Missing MyriadX blob file, disabling on-device feature detector");
201 UWARN(
"On-device SuperPoint or HF-Net enabled, image rate is limited to 15 FPS!");
205 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
211 #ifdef RTABMAP_DEPTHAI
212 useHarrisDetector_ = useHarrisDetector;
213 minDistance_ = minDistance;
214 numTargetFeatures_ = numTargetFeatures;
216 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
222 #ifdef RTABMAP_DEPTHAI
225 nmsRadius_ = nmsRadius;
227 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
234 #ifdef RTABMAP_DEPTHAI
236 std::vector<dai::DeviceInfo> devices = dai::Device::getAllAvailableDevices();
237 if(devices.empty() && mxidOrName_.empty())
239 UERROR(
"No DepthAI device found or specified");
246 bool deviceFound =
false;
247 dai::DeviceInfo deviceToUse(mxidOrName_);
248 if(mxidOrName_.empty())
249 std::tie(deviceFound, deviceToUse) = dai::Device::getFirstAvailableDevice();
250 else if(!deviceToUse.mxid.empty())
251 std::tie(deviceFound, deviceToUse) = dai::Device::getDeviceByMxId(deviceToUse.mxid);
257 UERROR(
"Could not find DepthAI device with MXID or IP/USB name \"%s\", found devices:", mxidOrName_.c_str());
258 for(
auto&
device : devices)
263 device_ = std::make_unique<dai::Device>(deviceToUse);
264 auto deviceName = device_->getDeviceName();
265 auto imuType = device_->getConnectedIMU();
266 UINFO(
"Device Name: %s, Device Serial: %s", deviceName.c_str(), device_->getMxId().c_str());
267 UINFO(
"Available Camera Sensors: ");
268 for(
auto& sensor : device_->getCameraSensorNames()) {
269 UINFO(
"Socket: CAM_%c - %s",
'A'+(
unsigned char)sensor.first, sensor.second.c_str());
271 UINFO(
"IMU Type: %s", imuType.c_str());
273 UINFO(
"Loading eeprom calibration data");
274 auto calibHandler = device_->readCalibration();
275 auto boardName = calibHandler.getEepromData().boardName;
278 targetSize_ = cv::Size(imageWidth_, imageWidth_/640*((outputMode_==2&&boardName!=
"BC2087")?360:400));
280 if(!calibrationFolder.empty() && !cameraName.empty() && imagesRectified_)
282 UINFO(
"Flashing camera...");
285 stereoModel_.setName(cameraName,
"rgb",
"depth");
287 if(stereoModel_.load(calibrationFolder, cameraName,
false))
289 std::vector<std::vector<float> > intrinsicsLeft(3);
290 std::vector<std::vector<float> > intrinsicsRight(3);
293 intrinsicsLeft[
row].resize(3);
294 intrinsicsRight[
row].resize(3);
297 intrinsicsLeft[
row][
col] = stereoModel_.left().K_raw().at<
double>(
row,
col);
298 intrinsicsRight[
row][
col] = stereoModel_.right().K_raw().at<
double>(
row,
col);
302 std::vector<float> distortionsLeft = stereoModel_.left().D_raw();
303 std::vector<float> distortionsRight = stereoModel_.right().D_raw();
304 std::vector<std::vector<float> > rotationMatrix(3);
307 rotationMatrix[
row].resize(3);
310 rotationMatrix[
row][
col] = stereoModel_.stereoTransform()(
row,
col);
315 translation[0] = stereoModel_.stereoTransform().x()*100.0f;
316 translation[1] = stereoModel_.stereoTransform().y()*100.0f;
317 translation[2] = stereoModel_.stereoTransform().z()*100.0f;
322 calibHandler.setCameraIntrinsics(dai::CameraBoardSocket::CAM_A, intrinsicsLeft, stereoModel_.left().imageWidth(), stereoModel_.left().imageHeight());
323 calibHandler.setDistortionCoefficients(dai::CameraBoardSocket::CAM_A, distortionsLeft);
324 std::vector<float> specTranslation = calibHandler.getCameraTranslationVector(dai::CameraBoardSocket::CAM_A, dai::CameraBoardSocket::CAM_C,
true);
325 calibHandler.setCameraExtrinsics(dai::CameraBoardSocket::CAM_A, dai::CameraBoardSocket::CAM_C, rotationMatrix,
translation, specTranslation);
329 calibHandler.setCameraIntrinsics(dai::CameraBoardSocket::CAM_B, intrinsicsLeft, stereoModel_.left().imageWidth(), stereoModel_.left().imageHeight());
330 calibHandler.setDistortionCoefficients(dai::CameraBoardSocket::CAM_B, distortionsLeft);
331 calibHandler.setCameraIntrinsics(dai::CameraBoardSocket::CAM_C, intrinsicsRight, stereoModel_.right().imageWidth(), stereoModel_.right().imageHeight());
332 calibHandler.setDistortionCoefficients(dai::CameraBoardSocket::CAM_C, distortionsRight);
333 std::vector<float> specTranslation = calibHandler.getCameraTranslationVector(dai::CameraBoardSocket::CAM_B, dai::CameraBoardSocket::CAM_C,
true);
334 calibHandler.setCameraExtrinsics(dai::CameraBoardSocket::CAM_B, dai::CameraBoardSocket::CAM_C, rotationMatrix,
translation, specTranslation);
338 UINFO(
"Flashing camera with calibration from %s with camera name %s", calibrationFolder.c_str(), cameraName.c_str());
341 std::cout <<
"K left: " << stereoModel_.left().K_raw() << std::endl;
342 std::cout <<
"K right: " << stereoModel_.right().K_raw() << std::endl;
343 std::cout <<
"D left: " << stereoModel_.left().D_raw() << std::endl;
344 std::cout <<
"D right: " << stereoModel_.right().D_raw() << std::endl;
345 std::cout <<
"Extrinsics: " << stereoModel_.stereoTransform() << std::endl;
346 std::cout <<
"Expected K with rectification_alpha=0: " << stereoModel_.left().K()*(double(targetSize_.width)/double(stereoModel_.left().imageWidth())) << std::endl;
348 device_->flashCalibration2(calibHandler);
350 catch(
const std::runtime_error &
e) {
351 UERROR(
"Failed flashing calibration: %s",
e.what());
356 UERROR(
"Failed loading calibration from %s with camera name %s", calibrationFolder.c_str(), cameraName.c_str());
360 calibHandler = device_->readCalibration();
363 auto cameraId = outputMode_==2?dai::CameraBoardSocket::CAM_A:dai::CameraBoardSocket::CAM_B;
364 cv::Mat cameraMatrix, distCoeffs, newCameraMatrix;
366 std::vector<std::vector<float> >
matrix = calibHandler.getCameraIntrinsics(cameraId, targetSize_.width, targetSize_.height);
367 cameraMatrix = (cv::Mat_<double>(3,3) <<
372 std::vector<float> coeffs = calibHandler.getDistortionCoefficients(cameraId);
373 if(calibHandler.getDistortionModel(cameraId) == dai::CameraModel::Perspective)
374 distCoeffs = (cv::Mat_<double>(1,8) << coeffs[0], coeffs[1], coeffs[2], coeffs[3], coeffs[4], coeffs[5], coeffs[6], coeffs[7]);
376 if(alphaScaling_>-1.0
f)
377 newCameraMatrix = cv::getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, targetSize_, alphaScaling_);
379 newCameraMatrix = cameraMatrix;
381 double fx = newCameraMatrix.at<
double>(0, 0);
382 double fy = newCameraMatrix.at<
double>(1, 1);
383 double cx = newCameraMatrix.at<
double>(0, 2);
384 double cy = newCameraMatrix.at<
double>(1, 2);
385 UINFO(
"fx=%f fy=%f cx=%f cy=%f (target size = %dx%d)",
fx,
fy,
cx,
cy, targetSize_.width, targetSize_.height);
386 if(outputMode_ == 2) {
390 double baseline = calibHandler.getBaselineDistance(dai::CameraBoardSocket::CAM_C, dai::CameraBoardSocket::CAM_B,
false)/100.0;
395 if(imuPublished_ || imuType.empty())
404 if(deviceName ==
"OAK-D")
411 else if(boardName ==
"BC2087")
418 else if(boardName ==
"DM2080")
425 else if(boardName ==
"DM9098")
432 else if(boardName ==
"NG2094")
439 else if(boardName ==
"NG9097")
441 if(imuType ==
"BMI270")
458 UWARN(
"Unsupported boardName (%s)! Disabling IMU!", boardName.c_str());
459 imuPublished_ =
false;
464 UINFO(
"IMU disabled");
465 imuPublished_ =
false;
468 dai::Pipeline pipeline;
470 auto sync = pipeline.create<dai::node::Sync>();
471 sync->setSyncThreshold(std::chrono::milliseconds(
int(500 / this->
getImageRate())));
473 std::shared_ptr<dai::node::Camera> rgbCamera;
476 rgbCamera = pipeline.create<dai::node::Camera>();
477 rgbCamera->setCamera(
"color");
478 if(boardName ==
"BC2087")
479 rgbCamera->setSize(1920, 1200);
480 else if(boardName ==
"NG2094")
481 rgbCamera->setSize(1280, 720);
483 rgbCamera->setSize(1920, 1080);
484 rgbCamera->setVideoSize(targetSize_.width, targetSize_.height);
485 rgbCamera->setPreviewSize(targetSize_.width, targetSize_.height);
487 rgbCamera->setMeshSource(imagesRectified_?dai::CameraProperties::WarpMeshSource::CALIBRATION:dai::CameraProperties::WarpMeshSource::NONE);
488 if(imagesRectified_ && alphaScaling_>-1.0
f)
489 rgbCamera->setCalibrationAlpha(alphaScaling_);
490 rgbCamera->properties.ispScale.horizNumerator = rgbCamera->properties.ispScale.vertNumerator = imageWidth_/640;
491 rgbCamera->properties.ispScale.horizDenominator = rgbCamera->properties.ispScale.vertDenominator = boardName==
"NG2094"?2:3;
493 auto rgbEncoder = pipeline.create<dai::node::VideoEncoder>();
494 rgbEncoder->setDefaultProfilePreset(this->
getImageRate(), dai::VideoEncoderProperties::Profile::MJPEG);
496 rgbCamera->video.link(rgbEncoder->input);
497 rgbEncoder->bitstream.link(sync->inputs[
"rgb"]);
500 auto stereoDepth = pipeline.create<dai::node::StereoDepth>();
502 stereoDepth->setDepthAlign(dai::CameraBoardSocket::CAM_A);
504 stereoDepth->setDepthAlign(dai::StereoDepthProperties::DepthAlign::RECTIFIED_LEFT);
505 if(subpixelFractionalBits_>=3 && subpixelFractionalBits_<=5)
507 stereoDepth->setSubpixel(
true);
508 stereoDepth->setSubpixelFractionalBits(subpixelFractionalBits_);
510 stereoDepth->setExtendedDisparity(extendedDisparity_);
511 stereoDepth->enableDistortionCorrection(
true);
512 stereoDepth->setDisparityToDepthUseSpecTranslation(useSpecTranslation_);
513 stereoDepth->setDepthAlignmentUseSpecTranslation(useSpecTranslation_);
514 if(alphaScaling_ > -1.0
f)
515 stereoDepth->setAlphaScaling(alphaScaling_);
516 stereoDepth->initialConfig.setConfidenceThreshold(confThreshold_);
517 stereoDepth->initialConfig.setLeftRightCheck(lrcThreshold_>=0);
519 stereoDepth->initialConfig.setLeftRightCheckThreshold(lrcThreshold_);
520 stereoDepth->initialConfig.setMedianFilter(dai::MedianFilter(medianFilter_));
521 auto config = stereoDepth->initialConfig.get();
522 config.censusTransform.kernelSize = dai::StereoDepthConfig::CensusTransform::KernelSize::KERNEL_7x9;
523 config.censusTransform.kernelMask = 0X5092A28C5152428;
524 config.costMatching.disparityWidth = disparityWidth_==64?dai::StereoDepthConfig::CostMatching::DisparityWidth::DISPARITY_64:dai::StereoDepthConfig::CostMatching::DisparityWidth::DISPARITY_96;
525 config.costMatching.enableCompanding = enableCompanding_;
526 config.costMatching.linearEquationParameters.alpha = 2;
527 config.costMatching.linearEquationParameters.beta = 4;
528 config.costAggregation.horizontalPenaltyCostP1 = 100;
529 config.costAggregation.horizontalPenaltyCostP2 = 500;
530 config.costAggregation.verticalPenaltyCostP1 = 100;
531 config.costAggregation.verticalPenaltyCostP2 = 500;
532 config.postProcessing.brightnessFilter.maxBrightness = 255;
533 stereoDepth->initialConfig.set(
config);
535 stereoDepth->depth.link(sync->inputs[
"depth"]);
539 auto leftEncoder = pipeline.create<dai::node::VideoEncoder>();
540 leftEncoder->setDefaultProfilePreset(this->
getImageRate(), dai::VideoEncoderProperties::Profile::MJPEG);
543 stereoDepth->rectifiedLeft.link(leftEncoder->input);
545 stereoDepth->syncedLeft.link(leftEncoder->input);
546 leftEncoder->bitstream.link(sync->inputs[
"left"]);
551 auto rightEncoder = pipeline.create<dai::node::VideoEncoder>();
552 rightEncoder->setDefaultProfilePreset(this->
getImageRate(), dai::VideoEncoderProperties::Profile::MJPEG);
555 stereoDepth->rectifiedRight.link(rightEncoder->input);
557 stereoDepth->syncedRight.link(rightEncoder->input);
558 rightEncoder->bitstream.link(sync->inputs[
"right"]);
561 if(boardName ==
"BC2087")
563 auto leftCamera = pipeline.create<dai::node::ColorCamera>();
564 leftCamera->setCamera(
"left");
565 leftCamera->setResolution(dai::ColorCameraProperties::SensorResolution::THE_1200_P);
566 leftCamera->setIspScale(imageWidth_/640, 3);
569 auto rightCamera = pipeline.create<dai::node::ColorCamera>();
570 rightCamera->setCamera(
"right");
571 rightCamera->setResolution(dai::ColorCameraProperties::SensorResolution::THE_1200_P);
572 rightCamera->setIspScale(imageWidth_/640, 3);
575 leftCamera->isp.link(stereoDepth->left);
576 rightCamera->isp.link(stereoDepth->right);
580 auto leftCamera = pipeline.create<dai::node::MonoCamera>();
581 leftCamera->setCamera(
"left");
582 leftCamera->setResolution(imageWidth_==640?dai::MonoCameraProperties::SensorResolution::THE_400_P:dai::MonoCameraProperties::SensorResolution::THE_800_P);
585 auto rightCamera = pipeline.create<dai::node::MonoCamera>();
586 rightCamera->setCamera(
"right");
587 rightCamera->setResolution(imageWidth_==640?dai::MonoCameraProperties::SensorResolution::THE_400_P:dai::MonoCameraProperties::SensorResolution::THE_800_P);
590 leftCamera->out.link(stereoDepth->left);
591 rightCamera->out.link(stereoDepth->right);
594 if(detectFeatures_ == 1)
596 auto gfttDetector = pipeline.create<dai::node::FeatureTracker>();
597 gfttDetector->setHardwareResources(2, 2);
598 gfttDetector->initialConfig.setCornerDetector(
599 useHarrisDetector_?dai::FeatureTrackerConfig::CornerDetector::Type::HARRIS:dai::FeatureTrackerConfig::CornerDetector::Type::SHI_THOMASI);
600 gfttDetector->initialConfig.setNumTargetFeatures(numTargetFeatures_);
601 gfttDetector->initialConfig.setMotionEstimator(
false);
602 auto cfg = gfttDetector->initialConfig.get();
603 cfg.featureMaintainer.minimumDistanceBetweenFeatures = minDistance_ * minDistance_;
604 gfttDetector->initialConfig.set(cfg);
607 rgbCamera->video.link(gfttDetector->inputImage);
608 else if(imagesRectified_)
609 stereoDepth->rectifiedLeft.link(gfttDetector->inputImage);
611 stereoDepth->syncedLeft.link(gfttDetector->inputImage);
612 gfttDetector->outputFeatures.link(sync->inputs[
"feat"]);
614 else if(detectFeatures_ >= 2)
616 auto imageManip = pipeline.create<dai::node::ImageManip>();
617 imageManip->setKeepAspectRatio(
false);
618 imageManip->setMaxOutputFrameSize(320 * 200);
619 imageManip->initialConfig.setResize(320, 200);
620 imageManip->initialConfig.setFrameType(dai::ImgFrame::Type::GRAY8);
622 auto neuralNetwork = pipeline.create<dai::node::NeuralNetwork>();
623 neuralNetwork->setBlobPath(blobPath_);
624 neuralNetwork->setNumInferenceThreads(2);
625 neuralNetwork->setNumNCEPerInferenceThread(1);
626 neuralNetwork->input.setBlocking(
false);
629 rgbCamera->video.link(imageManip->inputImage);
630 else if(imagesRectified_)
631 stereoDepth->rectifiedLeft.link(imageManip->inputImage);
633 stereoDepth->syncedLeft.link(imageManip->inputImage);
634 imageManip->out.link(neuralNetwork->input);
635 neuralNetwork->out.link(sync->inputs[
"feat"]);
638 auto xoutCamera = pipeline.create<dai::node::XLinkOut>();
639 xoutCamera->setStreamName(
"camera");
641 sync->out.link(xoutCamera->input);
645 auto imu = pipeline.create<dai::node::IMU>();
646 if(imuType ==
"BMI270")
647 imu->enableIMUSensor({dai::IMUSensor::ACCELEROMETER_RAW, dai::IMUSensor::GYROSCOPE_RAW}, 200);
649 imu->enableIMUSensor({dai::IMUSensor::ACCELEROMETER, dai::IMUSensor::GYROSCOPE_UNCALIBRATED}, 200);
650 imu->setBatchReportThreshold(boardName==
"NG9097"?4:1);
651 imu->setMaxBatchReports(10);
653 auto xoutIMU = pipeline.create<dai::node::XLinkOut>();
654 xoutIMU->setStreamName(
"imu");
656 imu->out.link(xoutIMU->input);
659 device_->startPipeline(pipeline);
660 if(!device_->getIrDrivers().empty())
662 UINFO(
"Setting IR intensity");
663 device_->setIrLaserDotProjectorIntensity(dotIntensity_);
664 device_->setIrFloodLightIntensity(floodIntensity_);
666 else if(dotIntensity_ > 0 || floodIntensity_ > 0)
668 UWARN(
"No IR drivers were detected! IR intensity cannot be set.");
671 cameraQueue_ = device_->getOutputQueue(
"camera", 8,
false);
675 UINFO(
"IMU local transform = %s", imuLocalTransform_.prettyPrint().c_str());
676 device_->getOutputQueue(
"imu", 50,
false)->addCallback([
this](
const std::shared_ptr<dai::ADatatype>
data) {
677 auto imuData = std::dynamic_pointer_cast<dai::IMUData>(
data);
678 auto imuPackets = imuData->packets;
680 for(
auto& imuPacket : imuPackets)
682 auto& acceleroValues = imuPacket.acceleroMeter;
683 auto& gyroValues = imuPacket.gyroscope;
684 double accStamp = std::chrono::duration<double>(acceleroValues.getTimestampDevice().time_since_epoch()).count();
685 double gyroStamp = std::chrono::duration<double>(gyroValues.getTimestampDevice().time_since_epoch()).count();
689 IMU imu(cv::Vec3f(gyroValues.x, gyroValues.y, gyroValues.z), cv::Mat::eye(3,3,CV_64FC1),
690 cv::Vec3f(acceleroValues.x, acceleroValues.y, acceleroValues.z), cv::Mat::eye(3,3,CV_64FC1),
697 accBuffer_.emplace_hint(accBuffer_.end(), accStamp, cv::Vec3f(acceleroValues.x, acceleroValues.y, acceleroValues.z));
698 gyroBuffer_.emplace_hint(gyroBuffer_.end(), gyroStamp, cv::Vec3f(gyroValues.x, gyroValues.y, gyroValues.z));
709 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");
716 #ifdef RTABMAP_DEPTHAI
717 return outputMode_ == 0?stereoModel_.isValidForProjection():stereoModel_.left().isValidForProjection();
725 #ifdef RTABMAP_DEPTHAI
726 return device_->getMxId();
734 #ifdef RTABMAP_DEPTHAI
736 auto messageGroup = cameraQueue_->get<dai::MessageGroup>();
737 auto rgbOrLeft = messageGroup->get<dai::ImgFrame>(outputMode_==2?
"rgb":
"left");
738 auto depthOrRight = messageGroup->get<dai::ImgFrame>(outputMode_?
"depth":
"right");
740 double stamp = std::chrono::duration<double>(depthOrRight->getTimestampDevice(dai::CameraExposureOffset::MIDDLE).time_since_epoch()).count();
742 data =
SensorData(cv::imdecode(rgbOrLeft->getData(), cv::IMREAD_ANYCOLOR), depthOrRight->getCvFrame(), stereoModel_.left(),
this->getNextSeqID(), stamp);
744 data =
SensorData(cv::imdecode(rgbOrLeft->getData(), cv::IMREAD_GRAYSCALE), cv::imdecode(depthOrRight->getData(), cv::IMREAD_GRAYSCALE), stereoModel_,
this->getNextSeqID(), stamp);
749 std::map<double, cv::Vec3f>::const_iterator iterA, iterB;
752 while(accBuffer_.empty() || gyroBuffer_.empty() || accBuffer_.rbegin()->first < stamp || gyroBuffer_.rbegin()->first < stamp)
760 iterB = accBuffer_.lower_bound(stamp);
762 if(iterA != accBuffer_.begin())
764 if(iterA == iterB || stamp == iterB->first)
768 else if(stamp > iterA->first && stamp < iterB->
first)
770 float t = (stamp-iterA->first) / (iterB->first-iterA->first);
771 acc = iterA->second +
t*(iterB->second - iterA->second);
773 accBuffer_.erase(accBuffer_.begin(), iterB);
776 iterB = gyroBuffer_.lower_bound(stamp);
778 if(iterA != gyroBuffer_.begin())
780 if(iterA == iterB || stamp == iterB->first)
782 gyro = iterB->second;
784 else if(stamp > iterA->first && stamp < iterB->
first)
786 float t = (stamp-iterA->first) / (iterB->first-iterA->first);
787 gyro = iterA->second +
t*(iterB->second - iterA->second);
789 gyroBuffer_.erase(gyroBuffer_.begin(), iterB);
792 data.setIMU(
IMU(gyro, cv::Mat::eye(3, 3, CV_64FC1), acc, cv::Mat::eye(3, 3, CV_64FC1), imuLocalTransform_));
795 if(detectFeatures_ == 1)
797 auto features = messageGroup->get<dai::TrackedFeatures>(
"feat")->trackedFeatures;
798 std::vector<cv::KeyPoint> keypoints;
799 for(
auto& feature : features)
800 keypoints.emplace_back(cv::KeyPoint(feature.position.x, feature.position.y, 3));
801 data.setFeatures(keypoints, std::vector<cv::Point3f>(), cv::Mat());
803 else if(detectFeatures_ >= 2)
805 auto features = messageGroup->get<dai::NNData>(
"feat");
806 std::vector<float> scores_dense, local_descriptor_map, global_descriptor;
807 if(detectFeatures_ == 2)
809 scores_dense = features->getLayerFp16(
"heatmap");
810 local_descriptor_map = features->getLayerFp16(
"desc");
812 else if(detectFeatures_ == 3)
814 scores_dense = features->getLayerFp16(
"pred/local_head/detector/Squeeze");
815 local_descriptor_map = features->getLayerFp16(
"pred/local_head/descriptor/transpose");
816 global_descriptor = features->getLayerFp16(
"pred/global_head/l2_normalize_1");
819 cv::Mat scores(200, 320, CV_32FC1, scores_dense.data());
820 cv::resize(scores, scores, targetSize_, 0, 0, cv::INTER_CUBIC);
823 cv::Mat dilated_scores(targetSize_, CV_32FC1);
824 cv::dilate(scores, dilated_scores, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(nmsRadius_*2+1, nmsRadius_*2+1)));
825 cv::Mat max_mask = scores == dilated_scores;
826 cv::dilate(scores, dilated_scores, cv::Mat());
827 cv::Mat max_mask_r1 = scores == dilated_scores;
828 cv::Mat supp_mask(targetSize_, CV_8UC1);
829 for(
size_t i=0;
i<2;
i++)
831 cv::dilate(max_mask, supp_mask, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(nmsRadius_*2+1, nmsRadius_*2+1)));
832 cv::Mat supp_scores = scores.clone();
833 supp_scores.setTo(0, supp_mask);
834 cv::dilate(supp_scores, dilated_scores, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(nmsRadius_*2+1, nmsRadius_*2+1)));
835 cv::Mat new_max_mask = cv::Mat::zeros(targetSize_, CV_8UC1);
836 cv::bitwise_not(supp_mask, supp_mask);
837 cv::bitwise_and(supp_scores == dilated_scores, supp_mask, new_max_mask, max_mask_r1);
838 cv::bitwise_or(max_mask, new_max_mask, max_mask);
840 cv::bitwise_not(max_mask, supp_mask);
841 scores.setTo(0, supp_mask);
844 std::vector<cv::Point> kpts;
848 std::vector<cv::KeyPoint> keypoints;
849 for(
auto& kpt : kpts)
851 float response = scores.at<
float>(kpt);
852 keypoints.emplace_back(cv::KeyPoint(kpt, 8, -1, response));
855 cv::Mat coarse_desc(25, 40, CV_32FC(256), local_descriptor_map.data());
856 if(detectFeatures_ == 2)
857 coarse_desc.forEach<cv::Vec<float, 256>>([&](cv::Vec<float, 256>&
descriptor,
const int position[]) ->
void {
860 cv::Mat mapX(keypoints.size(), 1, CV_32FC1);
861 cv::Mat mapY(keypoints.size(), 1, CV_32FC1);
862 for(
size_t i=0;
i<keypoints.size(); ++
i)
864 mapX.at<
float>(
i) = (keypoints[
i].pt.x - (targetSize_.width-1)/2) * 40/targetSize_.width + (40-1)/2;
865 mapY.at<
float>(
i) = (keypoints[
i].pt.y - (targetSize_.height-1)/2) * 25/targetSize_.height + (25-1)/2;
867 cv::Mat map1, map2, descriptors;
868 cv::convertMaps(mapX, mapY, map1, map2, CV_16SC2);
869 cv::remap(coarse_desc, descriptors, map1, map2, cv::INTER_LINEAR);
870 descriptors.forEach<cv::Vec<float, 256>>([&](cv::Vec<float, 256>&
descriptor,
const int position[]) ->
void {
873 descriptors = descriptors.reshape(1);
875 data.setFeatures(keypoints, std::vector<cv::Point3f>(), descriptors);
878 if(detectFeatures_ == 3)
879 data.addGlobalDescriptor(
GlobalDescriptor(1, cv::Mat(1, global_descriptor.size(), CV_32FC1, global_descriptor.data()).clone()));
883 UERROR(
"CameraDepthAI: RTAB-Map is not built with depthai-core support!");