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
00042 #include <ros/ros.h>
00043 #include <opencv2/core/core.hpp>
00044 #include <opencv2/imgproc/imgproc.hpp>
00045 #include <opencv2/highgui/highgui.hpp>
00046
00047 #include <image_transport/image_transport.h>
00048 #include <cv_bridge/cv_bridge.h>
00049 #include <sensor_msgs/image_encodings.h>
00050 #include <stereo_msgs/DisparityImage.h>
00051
00052 #include <dynamic_reconfigure/server.h>
00053 #include <pal_vision_segmentation/DisparitySegmentConfig.h>
00054
00055
00056 image_transport::Publisher mask_pub;
00057 int threshold;
00058 int dilate_iterations;
00059 int dilate_size;
00060 int erode_iterations;
00061 int erode_size;
00062 int scale_factor;
00063 cv::Mat image_rect;
00064 image_transport::CameraPublisher cam_pub;
00065 sensor_msgs::CameraInfo camera_info;
00066 ros::Subscriber cam_info_sub;
00067 cv::Mat mask;
00068
00069
00070 void disparityCb(const stereo_msgs::DisparityImageConstPtr& msg)
00071 {
00072 if(cam_pub.getNumSubscribers() > 0 ||
00073 mask_pub.getNumSubscribers() > 0)
00074 {
00075
00076
00077 if (msg->min_disparity == 0.0 && msg->max_disparity == 0.0)
00078 {
00079 ROS_ERROR("Disparity image fields min_disparity and max_disparity are not set");
00080 return;
00081 }
00082 if (msg->image.encoding != sensor_msgs::image_encodings::TYPE_32FC1)
00083 {
00084 ROS_ERROR("Disparity image must be 32-bit floating point (encoding '32FC1'), but has encoding '%s'",
00085 msg->image.encoding.c_str());
00086 return;
00087 }
00088
00089
00090
00091 float min_disparity = msg->min_disparity;
00092 float max_disparity = msg->max_disparity;
00093 float multiplier = 255.0f / (max_disparity - min_disparity);
00094
00095 const cv::Mat_<float> dmat(msg->image.height, msg->image.width,
00096 (float*)&msg->image.data[0], msg->image.step);
00097 cv::Mat disparity_greyscale;
00098 disparity_greyscale.create(msg->image.height, msg->image.width, CV_8UC1);
00099
00100 for (int row = 0; row < disparity_greyscale.rows; ++row) {
00101 const float* d = dmat[row];
00102 for (int col = 0; col < disparity_greyscale.cols; ++col) {
00103 int index = (d[col] - min_disparity) * multiplier + 0.5;
00104
00105
00106
00107 if(index >= threshold)
00108 disparity_greyscale.at<uchar>(row, col) = 255;
00109 else
00110 disparity_greyscale.at<uchar>(row, col) = 0;
00111 }
00112 }
00113
00114 cv::Mat tmp1, mask;
00115 cv::erode(disparity_greyscale, tmp1,
00116 cv::Mat::ones(erode_size, erode_size, CV_8UC1),
00117 cv::Point(-1, -1), erode_iterations);
00118 cv::dilate(tmp1, mask,
00119 cv::Mat::ones(dilate_size, dilate_size, CV_8UC1),
00120 cv::Point(-1, -1), dilate_iterations);
00121
00122 if(mask_pub.getNumSubscribers() > 0)
00123 {
00124 cv_bridge::CvImage mask_msg;
00125 mask_msg.header = msg->header;
00126 mask_msg.encoding = sensor_msgs::image_encodings::TYPE_8UC1;
00127 mask_msg.image = mask;
00128 mask_pub.publish(mask_msg.toImageMsg());
00129 }
00130
00131 if(!image_rect.empty() && cam_pub.getNumSubscribers() > 0)
00132 {
00133 cv::Mat masked;
00134 image_rect.copyTo(masked, mask);
00135 cv_bridge::CvImage masked_msg;
00136 masked_msg.header = msg->header;
00137 masked_msg.encoding = sensor_msgs::image_encodings::BGR8;
00138
00139
00140 if(scale_factor > 1)
00141 {
00142 cv::Mat masked_tmp = masked;
00143 cv::resize(masked_tmp, masked,
00144 cv::Size(masked.cols*scale_factor, masked.rows*scale_factor));
00145 }
00146 masked_msg.image = masked;
00147
00148 ros::Time currentTime = ros::Time::now();
00149 masked_msg.header.stamp = currentTime;
00150 camera_info.header.stamp = currentTime;
00151 cam_pub.publish(*masked_msg.toImageMsg(), camera_info);
00152 }
00153
00154
00155
00156 }
00157 }
00158
00159 void constMaskCb(const stereo_msgs::DisparityImageConstPtr& msg)
00160 {
00161 if(!image_rect.empty())
00162 {
00163 cv::Mat masked;
00164 image_rect.copyTo(masked, mask);
00165 cv_bridge::CvImage masked_msg;
00166 masked_msg.header = msg->header;
00167 masked_msg.encoding = sensor_msgs::image_encodings::BGR8;
00168
00169
00170 if(scale_factor > 1)
00171 {
00172 cv::Mat masked_tmp = masked;
00173 cv::resize(masked_tmp, masked,
00174 cv::Size(masked.cols*scale_factor, masked.rows*scale_factor));
00175 }
00176 masked_msg.image = masked;
00177 cam_pub.publish(*masked_msg.toImageMsg(), camera_info);
00178 }
00179
00180
00181
00182 }
00183
00184 void imageCb(const sensor_msgs::ImageConstPtr& msg)
00185 {
00186 cv_bridge::CvImagePtr cv_ptr;
00187 try
00188 {
00189 cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
00190 }
00191 catch (cv_bridge::Exception& e)
00192 {
00193 ROS_ERROR("cv_bridge exception: %s", e.what());
00194 return;
00195 }
00196
00197 image_rect = cv_ptr->image;
00198 }
00199
00200 void reconf_callback(pal_vision_segmentation::DisparitySegmentConfig &config, uint32_t level)
00201 {
00202 threshold = config.threshold;
00203 dilate_iterations = config.dilate_iterations;
00204 dilate_size = config.dilate_size;
00205 erode_iterations = config.erode_iterations;
00206 erode_size = config.erode_size;
00207 }
00208
00209 void camInfoCallback(const sensor_msgs::CameraInfo &msg)
00210 {
00211 camera_info = msg;
00212
00213 for(unsigned int i=0; i<camera_info.D.size(); ++i)
00214 camera_info.D[i] = 0.0;
00215
00216
00217 if(scale_factor > 1)
00218 {
00219 camera_info.width *= scale_factor;
00220 camera_info.height *= scale_factor;
00221 for(int i=0; i<12; i++)
00222 camera_info.P[i] *= scale_factor;
00223 camera_info.P[10] = 1.0;
00224 }
00225
00226
00227 for(int i=0; i<3; ++i)
00228 for(int j=0; j<3; ++j)
00229 camera_info.K[i*3+j] = camera_info.P[i*4+j];
00230 }
00231
00232 int main(int argc, char *argv[] )
00233 {
00234 ros::init(argc, argv, "disparity_segmentation");
00235 ros::NodeHandle nh("disparity_segmentation");
00236 nh.param<int>("threshold", threshold, 89);
00237 nh.param<int>("dilate_iterations", dilate_iterations, 9);
00238 nh.param<int>("dilate_size", dilate_size, 7);
00239 nh.param<int>("erode_iterations", erode_iterations, 1);
00240 nh.param<int>("erode_size", erode_size, 3);
00241 nh.param<int>("scale_factor", scale_factor, 1);
00242
00243 std::string mask_path;
00244 nh.param<std::string>("mask_path", mask_path, "");
00245
00246 image_transport::ImageTransport it(nh);
00247 ros::Subscriber disp_sub;
00248 if(mask_path == "")
00249 {
00250 disp_sub = nh.subscribe<stereo_msgs::DisparityImage>("/disparity_image", 1, &disparityCb);
00251 } else {
00252 mask = cv::imread(mask_path);
00253 disp_sub = nh.subscribe<stereo_msgs::DisparityImage>("/disparity_image", 1, &constMaskCb);
00254 }
00255 image_transport::Subscriber rect_sub = it.subscribe("/image", 1, &imageCb);
00256 cam_pub = it.advertiseCamera("image_masked", 1);
00257 cam_info_sub = nh.subscribe("/camera_info", 1, &camInfoCallback);
00258 mask_pub = it.advertise("mask", 1);
00259
00260 dynamic_reconfigure::Server<pal_vision_segmentation::DisparitySegmentConfig> server;
00261 dynamic_reconfigure::Server<pal_vision_segmentation::DisparitySegmentConfig>::CallbackType f;
00262 f = boost::bind(&reconf_callback, _1, _2);
00263 server.setCallback(f);
00264
00265 ros::spin();
00266 }
00267