Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #define BOOST_PARAMETER_MAX_ARITY 7
00037 #include "jsk_pcl_ros/heightmap_morphological_filtering.h"
00038 #include "jsk_pcl_ros/heightmap_utils.h"
00039 #include <sensor_msgs/image_encodings.h>
00040
00041 namespace jsk_pcl_ros
00042 {
00043 void HeightmapMorphologicalFiltering::onInit()
00044 {
00045 DiagnosticNodelet::onInit();
00046 pub_config_ = pnh_->advertise<jsk_recognition_msgs::HeightmapConfig>("output/config",
00047 1, true);
00048 srv_ = boost::make_shared <dynamic_reconfigure::Server<Config> > (*pnh_);
00049 typename dynamic_reconfigure::Server<Config>::CallbackType f =
00050 boost::bind (&HeightmapMorphologicalFiltering::configCallback, this, _1, _2);
00051 srv_->setCallback (f);
00052
00053 pnh_->param("max_queue_size", max_queue_size_, 10);
00054 pub_ = advertise<sensor_msgs::Image>(*pnh_, "output", 1);
00055 sub_config_ = pnh_->subscribe(getHeightmapConfigTopic(pnh_->resolveName("input")), 1,
00056 &HeightmapMorphologicalFiltering::configTopicCallback,
00057 this);
00058 }
00059
00060 void HeightmapMorphologicalFiltering::subscribe()
00061 {
00062 sub_ = pnh_->subscribe(
00063 "input", max_queue_size_,
00064 &HeightmapMorphologicalFiltering::filter, this);
00065 }
00066
00067 void HeightmapMorphologicalFiltering::unsubscribe()
00068 {
00069 sub_.shutdown();
00070 }
00071
00072 void HeightmapMorphologicalFiltering::configTopicCallback(const jsk_recognition_msgs::HeightmapConfig::ConstPtr& msg)
00073 {
00074 pub_config_.publish(msg);
00075 }
00076
00077 void HeightmapMorphologicalFiltering::configCallback(
00078 Config& config, uint32_t level)
00079 {
00080 boost::mutex::scoped_lock lock(mutex_);
00081 mask_size_ = config.mask_size;
00082 max_variance_ = config.max_variance;
00083 }
00084
00085 void HeightmapMorphologicalFiltering::filter(
00086 const sensor_msgs::Image::ConstPtr& msg)
00087 {
00088 boost::mutex::scoped_lock lock(mutex_);
00089 vital_checker_->poke();
00090 cv::Mat input = cv_bridge::toCvShare(
00091 msg, sensor_msgs::image_encodings::TYPE_32FC1)->image;
00092 cv::Mat filtered_image = input.clone();
00093
00094 for (size_t j = 0; j < input.rows; j++) {
00095 for (size_t i = 0; i < input.cols; i++) {
00096 float v = input.at<float>(j, i);
00097 if (isnan(v) || v == -FLT_MAX) {
00098 Accumulator acc;
00099 for (int jj = - mask_size_; jj <= mask_size_; jj++) {
00100 int target_j = j + jj;
00101 if (target_j >= 0 && target_j < input.rows) {
00102 for (int ii = - mask_size_; ii <= mask_size_; ii++) {
00103 int target_i = i + ii;
00104 if (target_i >= 0 && target_i < input.cols) {
00105 if (std::abs(jj) + std::abs(ii) <= mask_size_) {
00106 float vv = input.at<float>(target_j, target_i);
00107 if (!isnan(vv) && vv != -FLT_MAX) {
00108 acc(vv);
00109 }
00110 }
00111 }
00112 }
00113 }
00114 }
00115 if (boost::accumulators::count(acc) != 0) {
00116 float newv = boost::accumulators::mean(acc);
00117 float variance = boost::accumulators::variance(acc);
00118 if (variance < max_variance_) {
00119 filtered_image.at<float>(j, i) = newv;
00120 }
00121 }
00122 }
00123 }
00124 }
00125
00126 pub_.publish(cv_bridge::CvImage(
00127 msg->header,
00128 sensor_msgs::image_encodings::TYPE_32FC1,
00129 filtered_image).toImageMsg());
00130 }
00131 }
00132
00133 #include <pluginlib/class_list_macros.h>
00134 PLUGINLIB_EXPORT_CLASS (jsk_pcl_ros::HeightmapMorphologicalFiltering, nodelet::Nodelet);