#include #include #include #include #include namespace icl{ #if 0 // OLD style .. will be removed soon ExtrinsicCameraCalibrator::ExtrinsicCameraCalibrator(const std::string method, float *params): m_method(method){ if(method != "linear" && method != "linear+stochastic"){ ERROR_LOG("wrong method ..."); m_method = "linear"; return; } if(method == "linear+stochastic"){ m_params.push_back(params ? params[0] : 10000); m_params.push_back(params ? params[1] : 0.001); } } #endif static FixedMatrix compute_Q_Matrix(const std::vector &XWs, const std::vector &XIs){ ICLASSERT_RETURN_VAL(XWs.size() == XIs.size(), (FixedMatrix(0.0)) ); int N = (int)XWs.size(); DynMatrix U(1,2*N); for(int i=0;i B(11,2*N); for(int i=0;i Cv = B.pinv() * U; return FixedMatrix(Cv[0],Cv[1],Cv[2],Cv[3], Cv[4],Cv[5],Cv[6],Cv[7], Cv[8],Cv[9],Cv[10],1); } static Vec vec3to4(const FixedMatrix &v,float x=0){ return Vec(v[0],v[1],v[2],x); } class StochasticCameraOptimizer : public StochasticOptimizer{ Camera cam; const std::vector &XWs; const std::vector &XIs; float data[7]; float noise[7]; float noiseVar; bool optimizeFocalLength; bool useAnnealing; public: StochasticCameraOptimizer(const Camera &cam, const std::vector &XWs, const std::vector &XIs, float noiseVar, bool optimizeFocalLength, bool useAnnealing): StochasticOptimizer(optimizeFocalLength ? 7 : 6/*(f) and pos and rot*/),cam(cam),XWs(XWs), XIs(XIs),noiseVar(noiseVar),optimizeFocalLength(optimizeFocalLength),useAnnealing(useAnnealing) { randomSeed(); } Camera camFromData(const float *data){ Camera cam = this->cam; cam.translate(data[0]*10,data[1]*10,data[2]*10); cam.rotate(data[3],data[4],data[5]); if(optimizeFocalLength) cam.setFocalLength(this->cam.getFocalLength()+data[6]*10); /* cam.translate(data[0],data[1],data[2]); cam.rotate(data[3],data[4],data[5]); if(optimizeFocalLength) cam.setFocalLength(this->cam.getFocalLength()+data[6]); */ return cam; } protected: virtual void reinitialize(){ std::fill(data,data+7,0); } virtual float *getData(){ return data; } virtual float getError(const float *data){ return ExtrinsicCameraCalibrator::estimateRMSE(XWs,XIs,camFromData(data)); /* Camera cam = camFromData(data); float err = 0; const std::vector XIs2 = cam.project(XWs); for(unsigned int i=0;i &XWs, std::vector &XIs) throw (NotEnoughDataPointsException){ if(XWs.size() > XIs.size()){ ERROR_LOG("got more world points than image points (erasing additional world points)"); XWs.resize(XIs.size()); } else if(XWs.size() < XIs.size()){ ERROR_LOG("got less world points than image points (erasing additional image points)"); XIs.resize(XWs.size()); } if(XWs.size() < 6){ throw NotEnoughDataPointsException(); } for(unsigned int i=0;i XWs, std::vector XIs, const Size &imageSize, const float focalLength, float *rmse, bool optimizeFocalLength) const throw (ExtrinsicCameraCalibrator::InvalidWorldPositionException, ExtrinsicCameraCalibrator::NotEnoughDataPointsException){ checkAndFixPoints(XWs,XIs); if(m_method == "linear" || m_method == "linear+stochastic"){ std::vector XIs_save = XIs; float fInv = 1.0/focalLength; Camera cam; cam.setViewPort(Rect(Point::null,imageSize)); cam.setFocalLength(focalLength); for(unsigned int i=0;i Q; try{ Q = compute_Q_Matrix(XWs, XIs); }catch(...){ throw InvalidWorldPositionException(); } FixedMatrix M = Q.part<0,0,3,3>(); FixedMatrix c4 = Q.col(3); FixedMatrix K; // intrinsic parameters FixedMatrix R; // extrinsic (rotation matrix) FixedMatrix T; // extrinsic (tranlation vector) decompose_QR(M,R,K); T = -M.inv() * c4; /* std::cout <<"Computed Pos: " << T.transp() << std::endl; std::cout <<"Orig Cam Pos: "<< scene.getCamera(0).getPos().transp() << std::endl; std::cout << "----------" << std::endl; */ Vec pos(T[0],T[1],T[2]); Vec norm = vec3to4(R.transp()*FixedMatrix(0,0,1)); Vec up = vec3to4(R.transp()*FixedMatrix(0,1,0)); if(m_method == "linear+stochastic"){ Camera cam(pos,norm, up, Rect(Point::null,imageSize),focalLength); StochasticCameraOptimizer stochOpt(cam,XWs,XIs_save,m_params[1], optimizeFocalLength,false); StochasticOptimizer::Result result = stochOpt.optimize(m_params[0]); cam = stochOpt.camFromData(result.data); if(rmse) *rmse = estimateRMSE(XWs,XIs_save,cam); return cam; }else{ Camera cam(pos,norm, up, Rect(Point::null,imageSize),focalLength); if(rmse) *rmse = estimateRMSE(XWs,XIs_save,cam); return cam; } } return Camera(); } #endif ExtrinsicCameraCalibrator::Result ExtrinsicCameraCalibrator::calibrateLinear(std::vector XWs, std::vector XIs, const Size &imageSize, const float &focalLength) throw (InvalidWorldPositionException, NotEnoughDataPointsException){ checkAndFixPoints(XWs,XIs); std::vector XIs_save = XIs; float fInv = 1.0/focalLength; Camera cam; cam.setViewPort(Rect(Point::null,imageSize)); cam.setFocalLength(focalLength); for(unsigned int i=0;i Q; try{ Q = compute_Q_Matrix(XWs, XIs); }catch(...){ throw InvalidWorldPositionException(); } FixedMatrix M = Q.part<0,0,3,3>(); FixedMatrix c4 = Q.col(3); FixedMatrix K; // intrinsic parameters FixedMatrix R; // extrinsic (rotation matrix) FixedMatrix T; // extrinsic (tranlation vector) decompose_QR(M,R,K); T = -M.inv() * c4; /* std::cout <<"Computed Pos: " << T.transp() << std::endl; std::cout <<"Orig Cam Pos: "<< scene.getCamera(0).getPos().transp() << std::endl; std::cout << "----------" << std::endl; */ Vec pos(T[0],T[1],T[2]); Vec norm = vec3to4(R.transp()*FixedMatrix(0,0,1)); Vec up = vec3to4(R.transp()*FixedMatrix(0,1,0)); cam = Camera(pos,norm, up, Rect(Point::null,imageSize),focalLength); Result result = { "linear", cam, estimateRMSE(XWs,XIs_save,cam) }; return result; } ExtrinsicCameraCalibrator::Result ExtrinsicCameraCalibrator::calibrateStochastic(std::vector XWs, std::vector XIs, const Camera &cam, int steps, float minErrorThreshold, bool optimizeFocalLength, bool useAnnealing) throw (ExtrinsicCameraCalibrator::NotEnoughDataPointsException){ checkAndFixPoints(XWs,XIs); /* DEBUG_LOG("stoch. opt steps: " << steps << " err-thresh:" << minErrorThreshold << " optF: " << (optimizeFocalLength?"yes":"no" ) << " ann: " << (useAnnealing?"yes":"no" ) ); */ StochasticCameraOptimizer stochOpt(cam,XWs,XIs,useAnnealing ? 0.01 : 0.001, optimizeFocalLength, useAnnealing); StochasticOptimizer::Result resStOpt = stochOpt.optimize(minErrorThreshold,steps); Result result = { "stochastic" , stochOpt.camFromData(resStOpt.data), resStOpt.error//estimateRMSE(XWs,XIs,restStOpt.cam) }; return result; } ExtrinsicCameraCalibrator::Result ExtrinsicCameraCalibrator::calibrateLinearAndStochastic(std::vector XIs, std::vector XWs, const Size &imageSize, const float &focalLength, int steps, float minErrorThreshold, bool optimizeFocalLength, bool useAnnealing) throw (ExtrinsicCameraCalibrator::InvalidWorldPositionException, ExtrinsicCameraCalibrator::NotEnoughDataPointsException){ Result lin = calibrateLinear(XIs,XWs,imageSize,focalLength); Result linAndStochRes = calibrateStochastic(XIs,XWs,lin.camera,steps,minErrorThreshold,optimizeFocalLength,useAnnealing); linAndStochRes.method+="+stochastic"; return linAndStochRes; } float ExtrinsicCameraCalibrator::estimateRMSE(const std::vector &worldPoints, const std::vector XIs, const Camera &cam){ float err = 0; const std::vector XIs2 = cam.project(worldPoints); for(unsigned int i=0;i