5 #include <sam_onnx_ros/segmentation.hpp>
6 #include <sensor_msgs/Image.h>
7 #include <sensor_msgs/PointCloud2.h>
8 #include <yolo_onnx_ros/detection.hpp>
46 SEG::Backend backend = SEG::Backend::kOnnx;
49 if (backend_str ==
"tensorRT")
51 backend = SEG::Backend::kSpeedSam;
52 ROS_INFO(
"Using SpeedSAM (TensorRT) backend for SAM inference.");
54 else if (backend_str ==
"onnx")
56 backend = SEG::Backend::kOnnx;
57 ROS_INFO(
"Using ONNX backend for SAM inference.");
61 ROS_WARN(
"Unsupported SAM backend '%s'. Defaulting to ONNX.", backend_str.
c_str());
76 ROS_WARN_THROTTLE(1.0,
"SamSegPipeline is currently initializing in the background. Skipping frame...");
87 resYolo = Detector(
pimpl_->yoloDetector, img);
92 pimpl_->sam_res.boxes.clear();
95 for (
const auto& result : resYolo)
100 if (!ignore_label.
empty() && yolo_class == ignore_label)
102 ROS_DEBUG(
"Pre-filtering box for '%s' (matches ignore_label '%s')", yolo_class.
c_str(), ignore_label.
c_str());
115 if (x1 <= x0 || y1 <= y0)
118 ROS_WARN(
"Pre-filtering box for '%s' (entirely outside depth image bounds)", yolo_class.
c_str());
125 cv::Mat box_depth =
depth_image(cv::Rect(x0, y0, w, h));
129 if (cv::countNonZero(valid_mask) < 0.3 * w * h)
131 ROS_WARN(
"Pre-filtering box for '%s' (less than 30%% depth points within frustum volume)", yolo_class.
c_str());
136 pimpl_->sam_res.boxes.push_back(result.box);
139 ROS_DEBUG(
"Confidence: %f", result.confidence);
140 ROS_DEBUG(
"Class: %s", yolo_class.
c_str());
141 ROS_DEBUG(
"Class ID: %d", result.classId);
161 ROS_WARN(
"\n=== Segmentation Pipeline Latency ===\n");
162 ROS_WARN(
" YOLO infer: %7.2f ms (%zu bboxs)\n", seg_result.
latency.
yolo_infer_ms, resYolo.size());
167 if (!
pimpl_->resSam.empty())
169 seg_result.
masks = std::move(
pimpl_->resSam.front().masks);
171 seg_result.
boxes = std::move(
pimpl_->sam_res.boxes);
181 ROS_WARN(
"SAM produced %zu masks for %zu YOLO boxes — alignment broken, discarding labels this frame",
195 cv::Scalar(0, 0, 255),
196 cv::Scalar(0, 255, 0),
197 cv::Scalar(255, 0, 0),
198 cv::Scalar(0, 255, 255),
199 cv::Scalar(255, 0, 255),
200 cv::Scalar(255, 255, 0),
201 cv::Scalar(128, 0, 128),
202 cv::Scalar(0, 128, 128)
206 cv::Mat overlay = rgb.clone();
208 for (
size_t i = 0; i < masks.
size(); i++)
211 cv::Mat working_mask = masks[i].clone();
214 if (working_mask.rows != rgb.rows || working_mask.cols != rgb.cols)
215 cv::resize(working_mask, working_mask, rgb.size(), 0, 0, cv::INTER_NEAREST);
218 if (cv::countNonZero((working_mask > 0) & (working_mask < 255)) > 0)
219 cv::threshold(working_mask, working_mask, 127, 255, cv::THRESH_BINARY);
222 cv::Scalar color = colors[i % colors.
size()];
225 cv::Mat colorMask = cv::Mat::zeros(rgb.size(), CV_8UC3);
226 colorMask.setTo(color, working_mask);
229 cv::addWeighted(overlay, 1.0, colorMask, 0.2, 0, overlay);
233 cv::findContours(working_mask, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
236 cv::drawContours(rgb, contours, -1, cv::Scalar(0, 0, 0), 2);
237 cv::drawContours(rgb, contours, -1, color, 1);
241 cv::addWeighted(rgb, 0.7, overlay, 0.3, 0, rgb);