34 #include <boost/version.hpp> 35 #if ((BOOST_VERSION / 100) % 1000) >= 53 36 #include <boost/thread/lock_guard.hpp> 49 #include <opencv2/calib3d/calib3d.hpp> 53 #include <stereo_msgs/DisparityImage.h> 55 #include <stereo_image_proc/DisparityConfig.h> 56 #include <dynamic_reconfigure/server.h> 85 typedef stereo_image_proc::DisparityConfig
Config;
94 virtual void onInit();
98 void imageCb(
const ImageConstPtr& l_image_msg,
const CameraInfoConstPtr& l_info_msg,
99 const ImageConstPtr& r_image_msg,
const CameraInfoConstPtr& r_info_msg);
101 void configCb(Config &config, uint32_t level);
114 private_nh.
param(
"queue_size", queue_size, 5);
116 private_nh.
param(
"approximate_sync", approx,
false);
117 private_nh.
param(
"downsampling_factor", downsampling_factor_, 1);
121 sub_l_image_, sub_l_info_,
122 sub_r_image_, sub_r_info_) );
124 this, _1, _2, _3, _4));
129 sub_l_image_, sub_l_info_,
130 sub_r_image_, sub_r_info_) );
132 this, _1, _2, _3, _4));
139 reconfigure_server_->setCallback(f);
144 boost::lock_guard<boost::mutex> lock(connect_mutex_);
145 pub_disparity_ = nh.
advertise<DisparityImage>(
"disparity", 1, connect_cb, connect_cb);
151 boost::lock_guard<boost::mutex> lock(connect_mutex_);
152 if (pub_disparity_.getNumSubscribers() == 0)
154 sub_l_image_.unsubscribe();
155 sub_l_info_ .unsubscribe();
156 sub_r_image_.unsubscribe();
157 sub_r_info_ .unsubscribe();
159 else if (!sub_l_image_.getSubscriber())
165 sub_l_image_.subscribe(*it_,
"left/image_rect", 1, hints);
166 sub_l_info_ .subscribe(nh,
"left/camera_info", 1);
167 sub_r_image_.subscribe(*it_,
"right/image_rect", 1, hints);
168 sub_r_info_ .subscribe(nh,
"right/camera_info", 1);
173 const cv::Mat& input_image,
174 const uint32_t downsample_factor_per_dimension) {
175 cv::Mat blurred_image;
176 const int32_t kernel_size = 2 * downsample_factor_per_dimension + 1;
178 input_image, blurred_image, cv::Size(kernel_size, kernel_size),
179 downsample_factor_per_dimension);
183 uint32_t downsampled_height = std::ceil(
184 input_image.size().height /
185 static_cast<double>(downsample_factor_per_dimension));
186 uint32_t downsampled_width = std::ceil(
187 input_image.size().width /
188 static_cast<double>(downsample_factor_per_dimension));
189 cv::Mat downsampled_image(
190 downsampled_height, downsampled_width, input_image.type());
192 for (uint32_t destination_row = 0u; destination_row < downsampled_image.size().height; destination_row++) {
193 for (uint32_t destination_col = 0u; destination_col < downsampled_image.size().width; destination_col++) {
194 downsampled_image.at<uint8_t>(destination_row, destination_col) =
195 blurred_image.at<uint8_t>(destination_row * downsample_factor_per_dimension,
196 destination_col * downsample_factor_per_dimension);
199 return downsampled_image;
203 const cv::Mat& disparity,
const cv::Size& destination_size,
204 const uint32_t upsample_factor_per_dimension) {
205 cv::Mat upsampled_disparity(
206 destination_size, disparity.type(), -1.);
208 for (uint32_t destination_row = 0u; destination_row < upsampled_disparity.size().height; destination_row++) {
209 for (uint32_t destination_col = 0u; destination_col < upsampled_disparity.size().width; destination_col++) {
210 upsampled_disparity.at<
float>(destination_row, destination_col) = upsample_factor_per_dimension *
211 disparity.at<
float>(destination_row / upsample_factor_per_dimension,
212 destination_col / upsample_factor_per_dimension);
215 return upsampled_disparity;
219 const CameraInfoConstPtr& l_info_msg,
220 const ImageConstPtr& r_image_msg,
221 const CameraInfoConstPtr& r_info_msg)
224 model_.fromCameraInfo(l_info_msg, r_info_msg);
227 DisparityImagePtr disp_msg = boost::make_shared<DisparityImage>();
228 disp_msg->header = l_info_msg->header;
229 disp_msg->image.header = l_info_msg->header;
232 int border = block_matcher_.getCorrelationWindowSize() / 2;
233 int left = block_matcher_.getDisparityRange() + block_matcher_.getMinDisparity() + border - 1;
234 int wtf = (block_matcher_.getMinDisparity() >= 0) ? border + block_matcher_.getMinDisparity() : std::max(border, -block_matcher_.getMinDisparity());
235 int right = disp_msg->image.width - 1 - wtf;
237 int bottom = disp_msg->image.height - 1 - border;
238 disp_msg->valid_window.x_offset = left;
239 disp_msg->valid_window.y_offset = top;
240 disp_msg->valid_window.width = right - left;
241 disp_msg->valid_window.height = bottom - top;
247 cv::Mat_<uint8_t> l_sub_image;
248 cv::Mat_<uint8_t> r_sub_image;
250 if (downsampling_factor_ != 1) {
255 l_sub_image = l_image;
256 r_sub_image = r_image;
260 block_matcher_.processDisparity(l_sub_image, r_sub_image, model_, *disp_msg);
263 if (downsampling_factor_ != 1) {
265 const cv::Mat disp_upsampled_image =
267 disp_subsampled_image, l_image.size(), downsampling_factor_);
270 disp_image_container.toImageMsg(disp_msg->image);
274 double cx_l = model_.left().cx();
275 double cx_r = model_.right().cx();
277 cv::Mat_<float> disp_image(disp_msg->image.height, disp_msg->image.width,
278 reinterpret_cast<float*>(&disp_msg->image.data[0]),
279 disp_msg->image.step);
280 cv::subtract(disp_image, cv::Scalar(cx_l - cx_r), disp_image);
283 pub_disparity_.publish(disp_msg);
289 config.prefilter_size |= 0x1;
290 config.correlation_window_size |= 0x1;
291 config.disparity_range = (config.disparity_range / 16) * 16;
296 block_matcher_.setPreFilterCap(config.prefilter_cap);
297 block_matcher_.setCorrelationWindowSize(config.correlation_window_size);
298 block_matcher_.setMinDisparity(config.min_disparity);
299 block_matcher_.setDisparityRange(config.disparity_range);
300 block_matcher_.setUniquenessRatio(config.uniqueness_ratio);
301 block_matcher_.setSpeckleSize(config.speckle_size);
302 block_matcher_.setSpeckleRange(config.speckle_range);
303 if (config.stereo_algorithm == stereo_image_proc::Disparity_StereoBM) {
305 block_matcher_.setPreFilterSize(config.prefilter_size);
306 block_matcher_.setTextureThreshold(config.texture_threshold);
308 else if (config.stereo_algorithm == stereo_image_proc::Disparity_StereoSGBM) {
310 block_matcher_.setSgbmMode(config.fullDP);
311 block_matcher_.setP1(config.P1);
312 block_matcher_.setP2(config.P2);
313 block_matcher_.setDisp12MaxDiff(config.disp12MaxDiff);
boost::mutex connect_mutex_
CvImageConstPtr toCvShare(const sensor_msgs::ImageConstPtr &source, const std::string &encoding=std::string())
ExactTime< Image, CameraInfo, Image, CameraInfo > ExactPolicy
boost::shared_ptr< ReconfigureServer > reconfigure_server_
boost::function< void(const SingleSubscriberPublisher &)> SubscriberStatusCallback
ros::Publisher pub_disparity_
ApproximateTime< Image, CameraInfo, Image, CameraInfo > ApproximatePolicy
cv::Mat subsampleTheImage(const cv::Mat &input_image, const uint32_t downsample_factor_per_dimension)
void imageCb(const ImageConstPtr &l_image_msg, const CameraInfoConstPtr &l_info_msg, const ImageConstPtr &r_image_msg, const CameraInfoConstPtr &r_info_msg)
boost::shared_ptr< ExactSync > exact_sync_
boost::shared_ptr< image_transport::ImageTransport > it_
image_geometry::StereoCameraModel model_
dynamic_reconfigure::Server< Config > ReconfigureServer
message_filters::Synchronizer< ExactPolicy > ExactSync
boost::recursive_mutex config_mutex_
message_filters::Synchronizer< ApproximatePolicy > ApproximateSync
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
PLUGINLIB_EXPORT_CLASS(image_proc::CropNonZeroNodelet, nodelet::Nodelet)
message_filters::Subscriber< CameraInfo > sub_r_info_
cv::Mat upsampleTheDisparityImageWithoutInterpolation(const cv::Mat &disparity, const cv::Size &destination_size, const uint32_t upsample_factor_per_dimension)
const std::string TYPE_32FC1
stereo_image_proc::StereoProcessor block_matcher_
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
stereo_image_proc::DisparityConfig Config
image_transport::SubscriberFilter sub_r_image_
boost::shared_ptr< ApproximateSync > approximate_sync_
void configCb(Config &config, uint32_t level)