00001 #include <ros/ros.h>
00002 #include <nodelet/nodelet.h>
00003 #include <image_transport/image_transport.h>
00004 #include <sensor_msgs/image_encodings.h>
00005 #include "names.h"
00006
00009
00010 namespace openni_camera {
00011
00012 class CropDecimateNodelet : public nodelet::Nodelet
00013 {
00014 boost::shared_ptr<image_transport::ImageTransport> it_;
00015 image_transport::CameraSubscriber sub_;
00016 image_transport::CameraPublisher pub_;
00017
00018 int queue_size_;
00020 int decimation_x;
00021 int decimation_y;
00022
00023 virtual void onInit();
00024
00025 void connectCb();
00026
00027 void imageCb(const sensor_msgs::ImageConstPtr& image_msg,
00028 const sensor_msgs::CameraInfoConstPtr& info_msg);
00029 };
00030
00031 void CropDecimateNodelet::onInit()
00032 {
00033 ros::NodeHandle& nh = getNodeHandle();
00034 ros::NodeHandle& param_nh = getPrivateNodeHandle();
00035 it_.reset(new image_transport::ImageTransport(nh));
00036
00037
00038 param_nh.param("queue_size", queue_size_, 5);
00039 param_nh.param("decimation_x", decimation_x, 1);
00040 param_nh.param("decimation_y", decimation_y, 1);
00041
00042
00043 image_transport::SubscriberStatusCallback connect_cb = boost::bind(&CropDecimateNodelet::connectCb, this);
00044 pub_ = it_->advertiseCamera(resolve(nh, "camera_out/image_raw"), 1, connect_cb, connect_cb);
00045 }
00046
00047
00048 void CropDecimateNodelet::connectCb()
00049 {
00050 if (pub_.getNumSubscribers() == 0)
00051 sub_.shutdown();
00052 else if (!sub_)
00053 sub_ = it_->subscribeCamera(resolve(getNodeHandle(), "camera/image_raw"),
00054 queue_size_, &CropDecimateNodelet::imageCb, this);
00055 }
00056
00057 void CropDecimateNodelet::imageCb(const sensor_msgs::ImageConstPtr& image_msg,
00058 const sensor_msgs::CameraInfoConstPtr& info_msg)
00059 {
00060 if (decimation_x == 1 && decimation_y == 1)
00061 {
00062 pub_.publish(image_msg, info_msg);
00063 return;
00064 }
00065
00067 if (decimation_x % 2 != 0 || decimation_y % 2 != 0)
00068 {
00069 NODELET_ERROR_THROTTLE(2, "Odd binning not supported yet");
00070 return;
00071 }
00072
00074 if (!sensor_msgs::image_encodings::isBayer(image_msg->encoding))
00075 {
00076 NODELET_ERROR_THROTTLE(2, "Only Bayer encodings supported currenty");
00077 return;
00078 }
00079
00081
00082
00083 sensor_msgs::CameraInfoPtr out_info = boost::make_shared<sensor_msgs::CameraInfo>(*info_msg);
00084 out_info->binning_x = std::max((int)out_info->binning_x, 1) * decimation_x;
00085 out_info->binning_y = std::max((int)out_info->binning_y, 1) * decimation_y;
00086
00087
00088 sensor_msgs::ImagePtr out_image = boost::make_shared<sensor_msgs::Image>();
00089 out_image->header = image_msg->header;
00090 out_image->height = image_msg->height / decimation_y;
00091 out_image->width = image_msg->width / decimation_x;
00092 out_image->encoding = sensor_msgs::image_encodings::BGR8;
00093 out_image->step = out_image->width * 3;
00094 out_image->data.resize(out_image->height * out_image->step);
00095
00096
00097 int R, G1, G2, B;
00098 if (image_msg->encoding == sensor_msgs::image_encodings::BAYER_RGGB8)
00099 {
00100 R = 0;
00101 G1 = 1;
00102 G2 = image_msg->step;
00103 B = image_msg->step + 1;
00104 }
00105 else if (image_msg->encoding == sensor_msgs::image_encodings::BAYER_BGGR8)
00106 {
00107 B = 0;
00108 G1 = 1;
00109 G2 = image_msg->step;
00110 R = image_msg->step + 1;
00111 }
00112 else if (image_msg->encoding == sensor_msgs::image_encodings::BAYER_GBRG8)
00113 {
00114 G1 = 0;
00115 B = 1;
00116 R = image_msg->step;
00117 G2 = image_msg->step + 1;
00118 }
00119 else if (image_msg->encoding == sensor_msgs::image_encodings::BAYER_GRBG8)
00120 {
00121 G1 = 0;
00122 R = 1;
00123 B = image_msg->step;
00124 G2 = image_msg->step + 1;
00125 }
00126 else
00127 {
00128 NODELET_ERROR_THROTTLE(2, "Unrecognized Bayer encoding '%s'", image_msg->encoding.c_str());
00129 return;
00130 }
00131
00132
00133 int bayer_step = decimation_y * image_msg->step;
00134 int bayer_skip = decimation_x;
00135 const uint8_t* bayer_row = &image_msg->data[0];
00136 uint8_t* bgr_buffer = &out_image->data[0];
00137
00138
00139 for (int y = 0; y < (int)out_image->height; ++y, bayer_row += bayer_step)
00140 {
00141 const uint8_t* bayer_buffer = bayer_row;
00142 for (int x = 0; x < (int)out_image->width; ++x, bayer_buffer += bayer_skip, bgr_buffer += 3)
00143 {
00144 bgr_buffer[0] = bayer_buffer[B];
00145 bgr_buffer[1] = (bayer_buffer[G1] + bayer_buffer[G2]) / 2;
00146 bgr_buffer[2] = bayer_buffer[R];
00147 }
00148 }
00149
00150 pub_.publish(out_image, out_info);
00151 }
00152
00153 }
00154
00155
00156 #include <pluginlib/class_list_macros.h>
00157 PLUGINLIB_DECLARE_CLASS(openni_camera, crop_decimate, openni_camera::CropDecimateNodelet, nodelet::Nodelet)