heightmap_morphological_filtering_nodelet.cpp
Go to the documentation of this file.
1 // -*- mode: c++ -*-
2 /*********************************************************************
3  * Software License Agreement (BSD License)
4  *
5  * Copyright (c) 2014, JSK Lab
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/o2r other materials provided
17  * with the distribution.
18  * * Neither the name of the JSK Lab nor the names of its
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *********************************************************************/
35 
36 #define BOOST_PARAMETER_MAX_ARITY 7
40 
41 namespace jsk_pcl_ros
42 {
44  {
45  DiagnosticNodelet::onInit();
46  pub_config_ = pnh_->advertise<jsk_recognition_msgs::HeightmapConfig>("output/config",
47  1, true);
48  srv_ = boost::make_shared <dynamic_reconfigure::Server<Config> > (*pnh_);
49  typename dynamic_reconfigure::Server<Config>::CallbackType f =
50  boost::bind (&HeightmapMorphologicalFiltering::configCallback, this, _1, _2);
51  srv_->setCallback (f);
52 
53  pnh_->param("max_queue_size", max_queue_size_, 10);
54  pub_ = advertise<sensor_msgs::Image>(*pnh_, "output", 1);
55  sub_config_ = pnh_->subscribe(getHeightmapConfigTopic(pnh_->resolveName("input")), 1,
57  this);
59 
60  }
61 
63  {
64  sub_ = pnh_->subscribe(
65  "input", max_queue_size_,
67  }
68 
70  {
71  sub_.shutdown();
72  }
73 
74  void HeightmapMorphologicalFiltering::configTopicCallback(const jsk_recognition_msgs::HeightmapConfig::ConstPtr& msg)
75  {
76  pub_config_.publish(msg);
77  }
78 
80  Config& config, uint32_t level)
81  {
82  boost::mutex::scoped_lock lock(mutex_);
83  mask_size_ = config.mask_size;
84  max_variance_ = config.max_variance;
85  smooth_method_ = config.smooth_method;
86  bilateral_filter_size_ = config.bilateral_filter_size;
87  bilateral_sigma_color_ = config.bilateral_sigma_color;
88  bilateral_sigma_space_ = config.bilateral_sigma_space;
89  use_bilateral_ = config.use_bilateral;
90  }
91 
93  const sensor_msgs::Image::ConstPtr& msg)
94  {
95  boost::mutex::scoped_lock lock(mutex_);
96  vital_checker_->poke();
97  cv::Mat input = cv_bridge::toCvShare(
99 
100  cv::Mat filtered_image;
101  filtered_image = input.clone();
102 
103  if (smooth_method_ == "average_variance") {
104  for (size_t j = 0; j < input.rows; j++) {
105  for (size_t i = 0; i < input.cols; i++) {
106  float v = input.at<cv::Vec2f>(j, i)[0];
107  if (std::isnan(v) || v == -FLT_MAX) { // Need to filter
108  Accumulator acc;
109  // store valid values around the target point
110  for (int jj = - mask_size_; jj <= mask_size_; jj++) {
111  int target_j = j + jj;
112  if (target_j >= 0 && target_j < input.rows) {
113  for (int ii = - mask_size_; ii <= mask_size_; ii++) {
114  int target_i = i + ii;
115  if (target_i >= 0 && target_i < input.cols) {
116  if (std::abs(jj) + std::abs(ii) <= mask_size_) {
117  float vv = input.at<cv::Vec2f>(target_j, target_i)[0];
118  if (!std::isnan(vv) && vv != -FLT_MAX) {
119  acc(vv);
120  }
121  }
122  }
123  }
124  }
125  }
126  // if valid values exist, add new value to the target point as interpolation
127  if (boost::accumulators::count(acc) != 0) {
128  float newv = boost::accumulators::mean(acc);
130  if (variance < max_variance_) {
131  filtered_image.at<cv::Vec2f>(j, i)[0] = newv;
132  filtered_image.at<cv::Vec2f>(j, i)[1] = 1 - variance/max_variance_;
133  }
134  }
135  }
136  }
137  }
138  }
139  else if (smooth_method_ == "average_distance") {
140  for (size_t j = 0; j < input.rows; j++) {
141  for (size_t i = 0; i < input.cols; i++) {
142  float v = input.at<cv::Vec2f>(j, i)[0];
143  if (std::isnan(v) || v == -FLT_MAX) { // Need to filter
144  Accumulator height_acc;
145  Accumulator dist_acc;
146  // store valid values around the target point
147  for (int jj = - mask_size_; jj <= mask_size_; jj++) {
148  int target_j = j + jj;
149  if (target_j >= 0 && target_j < input.rows) {
150  for (int ii = - mask_size_; ii <= mask_size_; ii++) {
151  int target_i = i + ii;
152  if (target_i >= 0 && target_i < input.cols) {
153  int len = std::abs(jj) + std::abs(ii);
154  if (len <= mask_size_) {
155  float vv = input.at<cv::Vec2f>(target_j, target_i)[0];
156  if (!std::isnan(vv) && vv != -FLT_MAX) {
157  height_acc(vv);
158  dist_acc(len);
159  }
160  }
161  }
162  }
163  }
164  }
165  // if valid values exist, add new value to the target point as interpolation
166  if (boost::accumulators::count(height_acc) != 0) {
167  float newv = boost::accumulators::mean(height_acc);
168  float variance = boost::accumulators::variance(height_acc);
169  if (variance < max_variance_) {
170  filtered_image.at<cv::Vec2f>(j, i)[0] = newv;
171  filtered_image.at<cv::Vec2f>(j, i)[1] = (float)(1.0/(1.0 + boost::accumulators::mean(dist_acc)));
172  }
173  }
174  }
175  }
176  }
177  }
178 
179  if (use_bilateral_) {
180  std::vector<cv::Mat> fimages;
181  cv::split(filtered_image, fimages);
182  cv::Mat res_image;
183  // filter
184  cv::bilateralFilter(fimages[0], res_image, bilateral_filter_size_, bilateral_sigma_color_, bilateral_sigma_space_);
185  {
186  for (size_t j = 0; j < res_image.rows; j++) {
187  for (size_t i = 0; i < res_image.cols; i++) {
188  float ov = fimages[0].at<float>(j, i);
189  if (ov == -FLT_MAX) {
190  res_image.at<float>(j, i) = -FLT_MAX;
191  }
192  }
193  }
194  }
195  // reconstruct images
196  std::vector<cv::Mat> ret_images;
197  ret_images.push_back(res_image);
198  ret_images.push_back(fimages[1]);
199  cv::merge(ret_images, filtered_image);
200  }
201 
203  msg->header,
205  filtered_image).toImageMsg());
206  }
207 }
208 
CvImageConstPtr toCvShare(const sensor_msgs::ImageConstPtr &source, const std::string &encoding=std::string())
virtual void filter(const sensor_msgs::Image::ConstPtr &msg)
virtual void configTopicCallback(const jsk_recognition_msgs::HeightmapConfig::ConstPtr &msg)
void publish(const boost::shared_ptr< M > &message) const
boost::shared_ptr< dynamic_reconfigure::Server< Config > > srv_
PLUGINLIB_EXPORT_CLASS(jsk_pcl_ros::HeightmapMorphologicalFiltering, nodelet::Nodelet)
std::string getHeightmapConfigTopic(const std::string &base_topic)
double variance(const OneDataStat &d)
wrapper function for variance method for boost::function
boost::shared_ptr< ros::NodeHandle > pnh_
jsk_topic_tools::VitalChecker::Ptr vital_checker_
GLfloat v[8][3]
double count(const OneDataStat &d)
wrapper function for count method for boost::function
const std::string TYPE_32FC2
boost::accumulators::accumulator_set< float, boost::accumulators::stats< boost::accumulators::tag::variance, boost::accumulators::tag::count, boost::accumulators::tag::mean > > Accumulator
sensor_msgs::ImagePtr toImageMsg() const


jsk_pcl_ros
Author(s): Yohei Kakiuchi
autogenerated on Mon May 3 2021 03:03:46