GSoC2011SfM  0.1
Google Summer of Code 2011: Structure from motion
D:/Travail/These/Determination caracteristiques camera/GSoC/SfM/src/CameraPinholeDistor.cpp
00001 #include "CameraPinholeDistor.h"
00002 
00003 using std::vector;
00004 using cv::Mat;
00005 using cv::Vec2d;
00006 using cv::Vec3d;
00007 using cv::Vec4d;
00008 using cv::Vec6d;
00009 
00010 namespace OpencvSfM{
00011 
00012   CameraPinholeDistor::CameraPinholeDistor( cv::Mat intra_params,
00013     cv::Vec6d radial_dist, unsigned char nbRadialParam,
00014     cv::Vec2d tangential_dist, int img_w, int img_h,
00015     unsigned char wantedEstimation )
00016     :CameraPinhole( intra_params, img_w, img_h, wantedEstimation )
00017   {
00018     updateDistortionParameters( radial_dist,nbRadialParam,tangential_dist );
00019   }
00020 
00021   CameraPinholeDistor::CameraPinholeDistor( 
00022     const std::vector< std::vector< cv::Point3f> >& objectPoints,
00023     const std::vector< std::vector< cv::Point2f> >& imagePoints,
00024     cv::Size imageSize, double aspectRatio/*=1.*/,
00025     cv::Vec6d radial_dist, unsigned char nbRadialParam,
00026     cv::Vec2d tangential_dist, int img_w, int img_h,
00027     unsigned char wantedEstimation )
00028     :CameraPinhole( objectPoints,imagePoints,imageSize,aspectRatio,
00029      img_w, img_h, wantedEstimation )
00030   {
00031     updateDistortionParameters( radial_dist,nbRadialParam,tangential_dist );
00032   }
00033   CameraPinholeDistor::~CameraPinholeDistor( )
00034   {
00035     //TODO
00036   }
00037 
00038   uchar CameraPinholeDistor::getNbMissingParams( ) const
00039   {
00040     int nbParams = CameraPinhole::getNbMissingParams( );
00041     if( (estimation_needed_ & RADIAL_PARAM) != 0 )
00042       nbParams += nb_radial_params_;//2 focals
00043     if( (estimation_needed_ & TANGEANT_PARAM) != 0 )
00044       nbParams += nb_tangent_params_;//1 param
00045     return nbParams;
00046   }
00047 
00048   void CameraPinholeDistor::updateIntrinsic( double* values, uchar nbVal, bool add )
00049   {
00050     CameraPinhole::updateIntrinsic( values, nbVal, add );
00051     //TODO!
00052   }
00053 
00054   void CameraPinholeDistor::updateDistortionParameters(
00055     const cv::Vec6d& radial_dist, unsigned char nbRadialParam,
00056     const cv::Vec2d& tangential_dist,unsigned char wantedEstimation )
00057   {
00058     this->estimation_needed_= ( this->estimation_needed_ & 0x0F ) | ( wantedEstimation & 0xF0 );
00059     this->radial_dist_=radial_dist;
00060     this->nb_radial_params_=nbRadialParam;
00061     this->tangential_dist_=tangential_dist;
00062     if( estimation_needed_&RADIAL_PARAM )
00063     {
00064       int nbParamTotal=nb_radial_params_ + ( (estimation_needed_&TANGEANT_PARAM )>>4 );
00065       distortionVector.create( nbParamTotal,1,CV_64F );//( k_1, k_2, p_1, p_2[ , k_3[ , k_4, k_5, k_6 ]] )
00066       double * vals=( double* )distortionVector.data;
00067       vals[ 0 ]=radial_dist_[ 0 ];
00068       vals[ 1 ]=radial_dist_[ 1 ];
00069       if( estimation_needed_&TANGEANT_PARAM )
00070       {
00071         vals[ 2 ]=tangential_dist_[ 0 ];
00072         vals[ 3 ]=tangential_dist_[ 1 ];
00073         if( nbRadialParam>4 )
00074         {
00075           vals[ 4 ]=radial_dist_[ 2 ];
00076           if( nbRadialParam>5 )
00077           {
00078             vals[ 5 ]=radial_dist_[ 3 ];
00079             vals[ 6 ]=radial_dist_[ 4 ];
00080             vals[ 7 ]=radial_dist_[ 5 ];
00081           }
00082         }
00083       }
00084     }
00085   }
00086 
00087   std::vector< cv::Vec4d > CameraPinholeDistor::convertFromImageTo3Dray( 
00088     std::vector< cv::Vec3d > points )
00089   {
00090     //TODO
00091     return vector<Vec4d>( );
00092   }
00093 
00094   vector<Vec2d> CameraPinholeDistor::pixelToNormImageCoordinates(
00095     std::vector< cv::Vec2d > points ) const
00096   {
00097     vector<Vec2d> undistordedPoints;
00098     //rectify the distorion, but keep points in pixels coordinates:
00099     cv::undistortPoints( points,undistordedPoints,this->intra_params_,this->distortionVector );
00100     return undistordedPoints;
00101   }
00102 
00103   vector<Vec2d> CameraPinholeDistor::normImageToPixelCoordinates( 
00104     std::vector<cv::Vec2d> points ) const
00105   {
00106 
00107     vector<Vec2d> redistortedPoints;
00108 
00109     double r2, icdist, deltaX, deltaY;
00110     double xn, yn, xc, yc;
00111 
00112     for (unsigned int i = 0; i < points.size(); i++) {
00113         // Extract normalized, undistorted point co-ordinates
00114         xn = points.at(i)[0];
00115         yn = points.at(i)[1];
00116 
00117         //printf("%s << (xn, yn) = (%f, %f)\n", __FUNCTION__, xn, yn);
00118 
00119         // Determine radial distance from centre
00120         r2 = xn*xn + yn*yn;
00121 
00122         // Determine distortion factors (might only work for rational model at this stage)
00123         icdist = (1 + ((radial_dist_[5]*r2 + radial_dist_[4])*r2 + radial_dist_[3])*r2)/
00124           (1 + ((radial_dist_[2]*r2 + radial_dist_[1])*r2 + radial_dist_[0])*r2);
00125         deltaX = 2*tangential_dist_[0]*xn*yn + tangential_dist_[1]*(r2 + 2*xn*xn);
00126         deltaY = tangential_dist_[0]*(r2 + 2*yn*yn) + 2*tangential_dist_[1]*xn*yn;
00127 
00128         // Distort the points, but keep them in normalized co-ordinate system
00129         xc = (xn/icdist) + deltaX;
00130         yc = (yn/icdist) + deltaY;
00131 
00132         redistortedPoints.push_back(cv::Point2d(xc, yc));
00133 
00134         //printf("%s << (xc, yc) = (%f, %f)\n", __FUNCTION__, xc, yc);
00135 
00136     }
00137 
00138     // Convert these re-distorted but normalized points back to pixel co-ordinates
00139     vector<Vec2d> pointsPixelCoord =
00140       CameraPinhole::normImageToPixelCoordinates( redistortedPoints );
00141 
00142     return pointsPixelCoord;
00143   }
00144 
00145   cv::Ptr<Camera> CameraPinholeDistor::read( const cv::FileNode& node )
00146   {
00147     std::string myName=node.name( );
00148     if( myName != "CameraPinholeDistor" )
00149     {
00150       std::string error = "CameraPinholeDistor FileNode is not correct!\n"
00151         "Expected \"CameraPinholeDistor\", got ";
00152       error += node.name();
00153       CV_Error( CV_StsError, error.c_str() );
00154     }
00155 
00156     Mat intra_params;
00157     Vec6d radial_dist;
00158     unsigned char nbRadialParam;
00159     cv::Vec2d tangential_dist;
00160 
00161     //load intra parameters:
00162     cv::Ptr<Camera> cam_tmp = CameraPinhole::read( node["CameraPinhole"] );
00163 
00164     node[ "nb_radial_params_" ] >> nbRadialParam;
00165     for(int i=0;i<nbRadialParam;i++)
00166       radial_dist[i] = node[ "radial_dist_" ][i];
00167     for(int i=nbRadialParam;i<6;i++)
00168       radial_dist[i] = 0;
00169 
00170     for(int i=0;i<2;i++)
00171       tangential_dist[i] = node[ "tangential_dist_" ][i];
00172 
00173     return cv::Ptr<Camera>( new CameraPinholeDistor(
00174       ((CameraPinhole*)((Camera*)cam_tmp))->getIntraMatrix(),
00175       radial_dist, nbRadialParam, tangential_dist) );
00176   }
00177 
00178   void CameraPinholeDistor::write( cv::FileStorage& fs ) const
00179   {
00180     fs << "CameraPinholeDistor" << "{";
00181 
00182     ((CameraPinhole*)this)->write( fs );
00183 
00184     fs << "radial_dist_" << "[:";
00185     for(int i=0;i<6;i++)
00186       fs << this->radial_dist_[i];
00187     fs << "]";
00188 
00189     fs << "nb_radial_params_" << this->nb_radial_params_;
00190     fs << "tangential_dist_" << "[:";
00191     for(int i=0;i<2;i++)
00192       fs << this->tangential_dist_[i];
00193     fs << "]";
00194     fs << "}";
00195   }
00196 }
 All Classes Functions Variables