auto_white_balance_nodelet.cpp
Go to the documentation of this file.
00001 #include <iostream>
00002 #include <string>
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 <iostream>
00017 #include <fstream>
00018 
00019 
00020 #include "Camera.h"
00021 #include "CameraContext.h"
00022 #include "CameraException.h"
00023 
00024 
00025 
00026 #include "omnicamera_msgs/GetLadybugCameraConfig.h"
00027 #include "omnicamera_msgs/GetVirtualCameraConfig.h"
00028 #include "omnicamera_msgs/VirtualCameraConfig.h"
00029 #include "omnicamera_msgs/LadybugCameraConfig.h"
00030 
00031 
00032 
00033 
00034 
00035 namespace omnicamera {
00036 class Whitebalancing : public nodelet::Nodelet{
00037 public:
00038     Whitebalancing(){}
00039     
00040 private:
00041  
00042 boost::shared_ptr<image_transport::ImageTransport> it;
00043 image_transport::Subscriber sub; 
00044 int white_bal_BU;
00045 int white_bal_RU;
00046 int white_bal_BU_old;
00047 int white_bal_RU_old;
00048 int count;
00049 
00050 double vertical_startposition;
00051 double vertical_endposition;
00052 double horizontal_startposition;
00053 double horizontal_endposition;
00054 
00055 double cor_blue;
00056 double cor_red;
00057 
00058 cv::Vec3i mean_col;
00059 
00060 
00061 
00062 
00063   
00064 void onInit() {
00065          NODELET_INFO("Auto white balancing initialising");
00066      
00067          ros::NodeHandle &nh = getNodeHandle();
00068          it.reset(new image_transport::ImageTransport(nh));
00069          sub = it->subscribe("in", 1, &Whitebalancing::ballancing, this);
00070          
00071          
00072          // The positions of the reference area relative to the image size
00073          nh.param("vertical_startposition", vertical_startposition, 0.5);
00074          nh.param("vertical_endposition", vertical_endposition, 0.65);
00075          nh.param("horizontal_startposition", horizontal_startposition, 0.94);
00076          nh.param("horizontal_endposition", horizontal_endposition, 1.0);
00077          // only read the image every 10 published images
00078          nh.param("wait_images",count,10);
00079          
00080          nh.param("cor_blue",cor_blue,1.0);
00081          nh.param("cor_red",cor_red,1.0);
00082          
00083          // intial white balancing settings
00084          white_bal_BU=700;
00085          white_bal_RU=512;
00086          
00087          
00088          // Using system calls for dynamic reconfigure. 
00089          system("rosrun dynamic_reconfigure dynparam set /viz/camera1394_driver white_balance_BU 700");
00090          sleep(0.5);
00091          system("rosrun dynamic_reconfigure dynparam set /viz/camera1394_driver white_balance_RV 512");
00092          sleep(0.5);
00093          
00094          NODELET_INFO("Auto white balancing started");
00095          
00096 }
00097     
00098 void ballancing(const sensor_msgs::ImageConstPtr& msg){ //callback method
00099   if (count<10){
00100     count++;
00101     return;
00102   }
00103   count =0;
00104   cv_bridge::CvImagePtr cv_msg;
00105   cv::Mat* im;
00106   cv_msg= cv_bridge::toCvCopy( msg, std::string());
00107   im=&(cv_msg->image);
00108   if ((*im).empty()){
00109     ROS_INFO("Image message is empty, can not perform auto white balancing");
00110   }
00111   else {
00112     cv::Vec3i mean_col=getMeanColour(im,true);//(bgr)
00113 
00114  
00115  
00116     // calculation of the parameters for white balance adaption
00117     float b_c=mean_col(1)*cor_blue/(mean_col(0));
00118     float r_c=mean_col(1)*cor_red/(mean_col(2));
00119     
00120     b_c=1.0+((b_c-1)/2.0);
00121     r_c=1.0+((r_c-1)/2.0);
00122     
00123     //if the difference is small, do not change the parameters
00124     
00125    // NODELET_INFO("TEST");
00126     
00127         if(white_bal_BU*b_c-white_bal_BU>100){
00128             b_c=(white_bal_BU+100)/(double)(white_bal_BU);
00129         }
00130         
00131          if(white_bal_RU*r_c-white_bal_RU>100){
00132             r_c=(white_bal_RU+100)/(double)(white_bal_RU);
00133         }
00134         
00135          if(white_bal_BU-white_bal_BU*b_c>100){
00136             b_c=(white_bal_BU-100)/(double)(white_bal_BU);
00137         }
00138         
00139          if(white_bal_RU-white_bal_BU*r_c>100){
00140             r_c=(white_bal_RU-100)/(double)(white_bal_RU);
00141         }
00142    
00143         white_bal_BU=(int)white_bal_BU*b_c;
00144         
00145 
00146         white_bal_RU=(int)white_bal_RU*r_c;
00147         
00148         
00149     if (white_bal_BU>1024)
00150         white_bal_BU=1024;
00151     if (white_bal_RU>1024)
00152         white_bal_RU=1024;
00153    
00154     
00155     std::stringstream ss;
00156     ss << white_bal_BU;
00157     
00158     // Using system calls to change the parameters of the camera. Is there a better way using c++ ?
00159     system(("rosrun dynamic_reconfigure dynparam set /viz/camera1394_driver white_balance_BU "+ss.str()).c_str());
00160 //    ROS_INFO("changing BU");
00161  //   std::cout <<white_bal_BU<<"\n"<<white_bal_RU<<"\n"<<b_c<<"\n"<<r_c<<"\n"<<mean_col(1);
00162     
00163     sleep(0.5);
00164     
00165     ss.clear();
00166     ss.str(std::string());
00167     ss << white_bal_RU;
00168     
00169     system(("rosrun dynamic_reconfigure dynparam set /viz/camera1394_driver white_balance_RV "+ss.str()).c_str());
00170     
00171     sleep(0.5);
00172     
00173    
00174  
00175 }
00176 
00177   }
00178 
00179 cv::Vec3i getMeanColour(cv::Mat* im,bool sat_ign){ 
00180     cv::Vec3i mean_col;
00181     cv::Vec3i col;
00182 
00183     int rows=im->rows;
00184     int cols=im->cols;
00185     
00186     double temp;
00187    
00188    
00189    // Vector initialisation
00190     int S=0;
00191     for (int i=0;i<3;i++){
00192         mean_col(i)=0;
00193         }
00194     for(int i=vertical_startposition*rows;i<vertical_endposition*rows;i++){       
00195          for(int j=horizontal_startposition*cols;j<horizontal_endposition*cols;j++){
00196             col =(*im).at<cv::Vec3b>(i,j); 
00197             //if (col(1)<253 && col(2)<253 && col(3)<253){ // ignore too bright pixels, flare spots, gives problems
00198             mean_col=mean_col+col;
00199             S++;
00200             //}
00201          }
00202     }
00203     for (int k =0;k<3;k++){
00204        
00205         temp=((double)mean_col(k))/S;
00206         mean_col(k)=(int)temp;
00207         
00208         }
00209     return mean_col;
00210  
00211 }
00212 
00213 }; //End class Whitebalancing
00214 
00215 } // ENd namespace
00216 
00217 PLUGINLIB_DECLARE_CLASS(omnicamera, omnicam_whitebalance, omnicamera::Whitebalancing, nodelet::Nodelet)
00218 
00219 
00220 
00221 
00222 
00223 
00224 
00225 
00226 
00227 
00228 
00229 
00230 
00231 
00232 
00233 
00234 
00235 
00236 
00237 
00238 
00239 
00240 
00241 
00242 
00243 
00244 
00245 
00246 
00247 
 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