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
00037 #include "jsk_perception/kmeans.h"
00038 #include "jsk_perception/image_utils.h"
00039 #include <sensor_msgs/image_encodings.h>
00040 #include <cv_bridge/cv_bridge.h>
00041 #include <opencv2/opencv.hpp>
00042
00043 namespace jsk_perception
00044 {
00045 void KMeans::onInit()
00046 {
00047 DiagnosticNodelet::onInit();
00048 srv_ = boost::make_shared <dynamic_reconfigure::Server<Config> > (*pnh_);
00049 dynamic_reconfigure::Server<Config>::CallbackType f =
00050 boost::bind (&KMeans::configCallback, this, _1, _2);
00051 srv_->setCallback (f);
00052
00053 pub_ = advertise<sensor_msgs::Image>(*pnh_, "output", 1);
00054 }
00055
00056 void KMeans::subscribe()
00057 {
00058 sub_ = pnh_->subscribe("input", 1, &KMeans::apply, this);
00059 }
00060
00061 void KMeans::unsubscribe()
00062 {
00063 sub_.shutdown();
00064 }
00065
00066 void KMeans::configCallback(
00067 Config &config, uint32_t level)
00068 {
00069 boost::mutex::scoped_lock lock(mutex_);
00070 n_clusters_ = config.n_clusters;
00071 }
00072
00073 void KMeans::apply(
00074 const sensor_msgs::Image::ConstPtr& image_msg)
00075 {
00076 if ((image_msg->width == 0) && (image_msg->height == 0)) {
00077 JSK_ROS_WARN("invalid image input");
00078 return;
00079 }
00080 cv_bridge::CvImagePtr cv_ptr = cv_bridge::toCvCopy(
00081 image_msg, image_msg->encoding);
00082 cv::Mat image = cv_ptr->image;
00083
00084 cv::Mat reshaped_img = image.reshape(1, image.cols * image.rows);
00085 cv::Mat reshaped_img32f;
00086 reshaped_img.convertTo(reshaped_img32f, CV_32FC1, 1.0 / 255.0);
00087 cv::Mat labels;
00088 cv::TermCriteria criteria = cv::TermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0);
00089 cv::Mat centers;
00090 cv::kmeans(reshaped_img32f, n_clusters_, labels, criteria, 1, cv::KMEANS_PP_CENTERS, centers);
00091
00092 cv::Mat rgb_image(image.rows, image.cols, CV_8UC3);
00093 cv::MatIterator_<cv::Vec3b> rgb_first = rgb_image.begin<cv::Vec3b>();
00094 cv::MatIterator_<cv::Vec3b> rgb_last = rgb_image.end<cv::Vec3b>();
00095 cv::MatConstIterator_<int> label_first = labels.begin<int>();
00096
00097 cv::Mat centers_u8;
00098 centers.convertTo(centers_u8, CV_8UC1, 255.0);
00099 cv::Mat centers_u8c3 = centers_u8.reshape(3);
00100
00101 while ( rgb_first != rgb_last ) {
00102 const cv::Vec3b& rgb = centers_u8c3.ptr<cv::Vec3b>(*label_first)[0];
00103 *rgb_first = rgb;
00104 ++rgb_first;
00105 ++label_first;
00106 }
00107
00108 pub_.publish(cv_bridge::CvImage(
00109 image_msg->header,
00110 image_msg->encoding,
00111 rgb_image).toImageMsg());
00112 }
00113
00114 }
00115
00116 #include <pluginlib/class_list_macros.h>
00117 PLUGINLIB_EXPORT_CLASS (jsk_perception::KMeans, nodelet::Nodelet);