GSoC2011SfM
0.1
Google Summer of Code 2011: Structure from motion
|
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 }