color_histogram_classifier_nodelet.cpp
Go to the documentation of this file.
1 // -*- mode: c++ -*-
2 /*********************************************************************
3  * Software License Agreement (BSD License)
4  *
5  * Copyright (c) 2017, 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  * color_histogram_classifier_nodelet.cpp
37  * Author: Yuki Furuta <furushchev@jsk.imi.i.u-tokyo.ac.jp>
38  */
39 
40 #include <limits>
42 #include <jsk_recognition_msgs/ClassificationResult.h>
43 
44 namespace jsk_pcl_ros
45 {
47  {
48  DiagnosticNodelet::onInit();
49  classifier_name_ = "color_histogram";
50 
51  if (!loadReference()) return;
52 
53  srv_ = boost::make_shared<dynamic_reconfigure::Server<Config> >(*pnh_);
54  dynamic_reconfigure::Server<Config>::CallbackType f =
55  boost::bind(&ColorHistogramClassifier::configCallback, this, _1, _2);
56  srv_->setCallback(f);
57  pub_class_ = advertise<jsk_recognition_msgs::ClassificationResult>(*pnh_, "output", 1);
59  }
60 
62  {
63 
64  // load label names
65  std::vector<std::string> labels;
66  pnh_->param("label_names", labels, std::vector<std::string>());
67  if (labels.empty()) {
68  NODELET_FATAL_STREAM("param ~label_names must not be empty");
69  return false;
70  }
71 
72  // load histograms
73  for (size_t i = 0; i < labels.size(); ++i) {
74  std::string name = "histograms/" + labels[i];
75  NODELET_INFO_STREAM("Loading " << name);
76  std::vector<float> hist;
77  pnh_->param(name, hist, std::vector<float>());
78  if (hist.empty()) {
79  NODELET_ERROR_STREAM("Failed to load " << name);
80  } else {
81  label_names_.push_back(labels[i]);
82  reference_histograms_.push_back(hist);
83  }
84  }
85 
86  // check bin size
87  bin_size_ = reference_histograms_[0].size();
88  for (size_t i = 0; i < label_names_.size(); ++i) {
89  if (reference_histograms_[i].size() != bin_size_) {
90  NODELET_FATAL_STREAM("size of histogram " << label_names_[i] << " is different from " << label_names_[0]);
91  return false;
92  }
93  }
94 
95  NODELET_INFO_STREAM("Loaded " << label_names_.size() << " references");
96  return true;
97  }
98 
99  void ColorHistogramClassifier::configCallback(Config &config, uint32_t level)
100  {
101  boost::mutex::scoped_lock lock(mutex_);
102  compare_policy_ = jsk_recognition_utils::ComparePolicy(config.compare_policy);
103  detection_threshold_ = config.detection_threshold;
104 
105  if (queue_size_ != config.queue_size) {
106  queue_size_ = config.queue_size;
107  if (isSubscribed()) {
108  unsubscribe();
109  subscribe();
110  }
111  }
112  }
113 
115  {
116  sub_hist_ = pnh_->subscribe("input", 1, &ColorHistogramClassifier::feature, this);
117  sub_hists_ = pnh_->subscribe("input/array", 1, &ColorHistogramClassifier::features, this);
118  }
119 
121  {
124  }
125 
126  void ColorHistogramClassifier::computeDistance(const std::vector<float>& histogram,
127  std::vector<double>& distances) {
128  distances.resize(reference_histograms_.size());
129  for (size_t i = 0; i < reference_histograms_.size(); ++i) {
131  histogram, reference_histograms_[i],
132  compare_policy_, distances[i]);
133  }
134  }
135 
136  void ColorHistogramClassifier::feature(const jsk_recognition_msgs::ColorHistogram::ConstPtr& histogram)
137  {
138  boost::mutex::scoped_lock lock(mutex_);
139 
140  jsk_recognition_msgs::ClassificationResult result;
141  result.header = histogram->header;
142  result.classifier = classifier_name_;
143  result.target_names = label_names_;
144 
145  std::vector<double> distances;
146  computeDistance(histogram->histogram, distances);
147 
148  double max_prob = 0.0;
149  int label;
150  for (size_t i = 0; i < distances.size(); ++i) {
151  double prob = distances[i];
152  result.probabilities.push_back(prob);
153  if (prob > max_prob) {
154  max_prob = prob;
155  label = i;
156  }
157  }
158 
159  if (max_prob >= detection_threshold_) {
160  result.labels.push_back(label);
161  result.label_names.push_back(label_names_[label]);
162  result.label_proba.push_back(max_prob);
163  } else {
164  result.labels.push_back(-1);
165  result.label_names.push_back(std::string());
166  result.label_proba.push_back(0.0);
167  }
168 
169  pub_class_.publish(result);
170  }
171 
172  void ColorHistogramClassifier::features(const jsk_recognition_msgs::ColorHistogramArray::ConstPtr& histograms)
173  {
174  boost::mutex::scoped_lock lock(mutex_);
175 
176  jsk_recognition_msgs::ClassificationResult result;
177  result.header = histograms->header;
178  result.classifier = classifier_name_;
179  result.target_names = label_names_;
180 
181  for (size_t i = 0; i < histograms->histograms.size(); ++i) {
182  std::vector<double> distances;
183  computeDistance(histograms->histograms[i].histogram, distances);
184 
185  double max_prob = 0.0;
186  int label;
187  for (size_t i = 0; i < distances.size(); ++i) {
188  double prob = distances[i];
189  result.probabilities.push_back(prob);
190  if (prob > max_prob) {
191  max_prob = prob;
192  label = i;
193  }
194  }
195 
196  if (max_prob >= detection_threshold_) {
197  result.labels.push_back(label);
198  result.label_names.push_back(label_names_[label]);
199  result.label_proba.push_back(max_prob);
200  } else {
201  result.labels.push_back(-1);
202  result.label_names.push_back(std::string());
203  result.label_proba.push_back(0.0);
204  }
205  }
206 
207  pub_class_.publish(result);
208  }
209 }
210 
#define NODELET_INFO_STREAM(...)
virtual void configCallback(Config &config, uint32_t level)
label
void publish(const boost::shared_ptr< M > &message) const
bool compareHistogram(const std::vector< float > &input, const std::vector< float > &reference, const ComparePolicy policy, double &distance)
boost::shared_ptr< dynamic_reconfigure::Server< Config > > srv_
virtual void features(const jsk_recognition_msgs::ColorHistogramArray::ConstPtr &histograms)
size
struct svm_problem prob
#define NODELET_ERROR_STREAM(...)
result
boost::shared_ptr< ros::NodeHandle > pnh_
virtual void feature(const jsk_recognition_msgs::ColorHistogram::ConstPtr &histogram)
jsk_recognition_utils::ComparePolicy compare_policy_
std::vector< std::vector< float > > reference_histograms_
labels
#define NODELET_FATAL_STREAM(...)
PLUGINLIB_EXPORT_CLASS(jsk_pcl_ros::ColorHistogramClassifier, nodelet::Nodelet)
virtual void computeDistance(const std::vector< float > &histogram, std::vector< double > &distance)


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