imageColourCorrection_Nodelet.cpp
Go to the documentation of this file.
00001 
00002 #include <iostream>
00003 #include <ros/ros.h>
00004 #include <sensor_msgs/Image.h>
00005 #include <ros/package.h>
00006 #include <nodelet/nodelet.h>
00007 #include <cv_bridge/cv_bridge.h>
00008 #include <opencv2/core/core.hpp>
00009 #include <opencv2/imgproc/imgproc.hpp>
00010 #include <dynamic_reconfigure/server.h>
00011 #include <sensor_msgs/image_encodings.h>
00012 #include <pluginlib/class_list_macros.h>
00013 #include <image_transport/image_transport.h>
00014 #include <opencv2/core/core.hpp>
00015 #include <opencv2/highgui/highgui.hpp>
00016 #include "Camera.h"
00017 #include "CameraContext.h"
00018 #include "CameraException.h"
00019 
00020 
00021 
00022 #include "omnicamera_msgs/GetLadybugCameraConfig.h"
00023 #include "omnicamera_msgs/GetVirtualCameraConfig.h"
00024 #include "omnicamera_msgs/VirtualCameraConfig.h"
00025 #include "omnicamera_msgs/LadybugCameraConfig.h"
00026 
00027 
00028 
00029 #define ARRAY_LENGTH 30
00030 
00031 //#define SATURATION_VAL1 250
00032 //#define SATURATION_VAL2 200
00033 //#define vertical_startposition 0.5
00034 //#define vertical_endposition 0.65
00035 //#define horizontal_startposition 0.94
00036 //#define horizontal_endposition 1
00037 
00038 
00039 namespace omnicamera{
00040 class ColourCorrection : public nodelet::Nodelet{
00041 
00042 
00043 public:
00044     ColourCorrection(){   
00045     }
00046     
00047 private:
00048 ros::NodeHandle n; 
00049 boost::shared_ptr<image_transport::ImageTransport> it;
00050 image_transport::Publisher cameraPub;
00051 image_transport::Subscriber sub;
00052 int iter;
00053 bool full;
00054 float b_list [ARRAY_LENGTH];
00055 float g_list [ARRAY_LENGTH];
00056 float r_list [ARRAY_LENGTH];
00057 double vertical_startposition;
00058 double vertical_endposition;
00059 double horizontal_startposition;
00060 double horizontal_endposition;
00061 int SATURATION_VAL1;
00062 int SATURATION_VAL2;
00063 
00064 double corb;
00065 double corg;
00066 double corr;
00067 
00068 
00069   
00070   
00071 void onInit(){
00072     
00073     NODELET_INFO("Starting image correction");
00074     ros::NodeHandle &n = getNodeHandle();
00075     it.reset(new image_transport::ImageTransport(n));
00076     sub = it->subscribe("in", 1, &ColourCorrection::correct_col, this);
00077     cameraPub = it->advertise("out", 1);
00078     
00079   
00080     iter=-1;
00081     full=false;
00082     
00083     // startposition is a value between 0 and 1, giving the relative position of the first
00084     // pixel of the reference area. It is multiplied by the number of rows/columns
00085     n.param("vertical_startposition", vertical_startposition, 0.5);
00086     n.param("vertical_endposition", vertical_endposition, 0.65);
00087     n.param("horizontal_startposition", horizontal_startposition, 0.94);
00088     n.param("horizontal_endposition", horizontal_endposition, 1.0);
00089     n.param("saturation_value1",SATURATION_VAL1,250);
00090     n.param("saturation_value2",SATURATION_VAL2,200);
00091     
00092     // correction factors for the colour of the wheels ( not perfect grey)
00093     n.param("cor_b",corb,1.07);
00094     n.param("cor_g",corg,1.0);
00095     n.param("cor_r",corr,0.95);
00096     
00097 
00098     
00099     }
00100 
00101 
00102 
00103 // function returns the RGB value of the mean wheel colour
00104 cv::Vec3i getMeanColour(cv::Mat* im,bool sat_ign){ 
00105     cv::Vec3i mean_col;
00106     cv::Vec3i col;
00107    // colour reference area is rectangular
00108     int rows=im->rows;
00109     int cols=im->cols;
00110    
00111    
00112    // Vector initialisation?
00113     int S=0;
00114     for (int i=0;i<3;i++){
00115         mean_col(i)=0;
00116         }
00117     for(int i=vertical_startposition*rows;i<vertical_endposition*rows;i++){     
00118          for(int j=horizontal_startposition*cols;j<horizontal_endposition*cols;j++){
00119             col =(*im).at<cv::Vec3b>(i,j);
00120             if ( col(1)<253 && col(2)<253 && col(3)<253){
00121             mean_col=mean_col+col;
00122             S++;
00123             }
00124          }
00125     }
00126     mean_col=mean_col/S;
00127     return mean_col;
00128  
00129 }
00130 
00131 
00132 void linear_correction(float b_c, float g_c,float r_c,cv::Mat* im){
00133 int i,j;
00134 float cors [3] ={b_c,g_c,r_c};
00135 int temp;
00136 bool sat=false;
00137 for (i=0;i<(*im).rows;i++){
00138     for(j=0;j<(*im).cols;j++){
00139         sat=false;
00140         cv::Vec3b* a =(*im).ptr<cv::Vec3b>(i,j);
00141         // Some tricks to make sure saturated pixels keep the maximal value
00142         for (int k=0;k<3;k++){
00143             if((*a)(k)>(uchar)SATURATION_VAL1)
00144                 sat=true;
00145         }
00146         if (sat){
00147             for(int k=0;k<3;k++){
00148                 if((*a)(k)<(uchar)SATURATION_VAL2){
00149                     sat=false;
00150                 }
00151             }
00152         }
00153        
00154         if (!sat){
00155             for (int k=0;k<3;k++){
00156                 // changing the RGB value of the pixels
00157                 temp=(*a)(k)*cors[k];
00158                     if(temp<255){
00159                         (*a)(k)= (uchar) temp;
00160                      }
00161                      else {
00162                         (*a)(k)=(uchar)255;
00163                         }
00164                   
00165              }
00166         }
00167     
00168     }
00169 
00170 
00171 }
00172 
00173 
00174 }
00175 
00176 void correct_col(const sensor_msgs::ImageConstPtr& msg){ //callback method
00177   
00178   cv_bridge::CvImagePtr cv_msg;
00179   cv::Mat* im;
00180   cv_msg= cv_bridge::toCvCopy( msg, std::string());
00181   im=&(cv_msg->image);
00182  
00183   if ((*im).empty()){
00184     ROS_INFO("No Image for colour correction");
00185   }
00186   else {
00187    // cv::namedWindow( "Display window",CV_WINDOW_NORMAL );// Create a window for display, to be removed
00188     //cv::waitKey(3);
00189     cv::Vec3i mean_col=getMeanColour(im,true);
00190     uint grey_col = ((uint)mean_col(0)+(uint)mean_col(1)+(uint)mean_col(2)) /3;
00191 
00192     // calculation of the three colour correction factors
00193     float b_c= grey_col*corb/(mean_col(0));
00194     float g_c= grey_col*corg/(mean_col(1));
00195     float r_c= grey_col*corr/(mean_col(2));
00196    
00197     
00198    
00199     iter++;
00200     if (iter==ARRAY_LENGTH){
00201         iter=0;
00202         full=true;
00203     }
00204     b_list[iter]=b_c;
00205     g_list[iter]=g_c;
00206     r_list[iter]=r_c;
00207     b_c=0;
00208     g_c=0;
00209     r_c=0;
00210     int list_end;
00211     if(full){
00212         list_end=ARRAY_LENGTH;
00213         }
00214     else{
00215         list_end=iter+1;
00216         }
00217     for(int i=0;i<list_end;i++){
00218         b_c+=b_list[i];
00219         g_c+=g_list[i];
00220         r_c+=r_list[i];
00221     }
00222     b_c=b_c/list_end;
00223     g_c=g_c/list_end;
00224     r_c=r_c/list_end;
00225         
00226     linear_correction(b_c,g_c,r_c,im);
00227     
00228     // NODELET_INFO("Image published");
00229     
00230     this->cameraPub.publish(cv_msg->toImageMsg());
00231   
00232   }
00233 }
00234 
00235 }; //End class colourCorrection
00236 } // End namespace omnicamera
00237 
00238 PLUGINLIB_DECLARE_CLASS(omnicamera,bag_colour_correction, omnicamera::ColourCorrection, nodelet::Nodelet)
00239 
00240 
00241 
00242 
 All Classes Namespaces Files Functions Variables Typedefs Defines


omnicamera
Author(s): Tomas Petricek / petrito1@cmp.felk.cvut.cz
autogenerated on Tue Dec 10 2013 14:26:53