2 #include <opencv2/imgproc/imgproc.hpp>     3 #include <opencv2/calib3d/calib3d.hpp>    11 cv::Mat  
getRTMatrix(
const cv::Mat &R_, 
const cv::Mat &T_, 
int forceType) {
    16     if (R.type() == CV_64F) {
    17         assert(T.type() == CV_64F);
    18         cv::Mat Matrix = cv::Mat::eye(4, 4, CV_64FC1);
    20         cv::Mat R33 = cv::Mat(Matrix, cv::Rect(0, 0, 3, 3));
    22             cv::Rodrigues(R, R33);
    23         } 
else if (R.total() == 9) {
    25             R.convertTo(R64, CV_64F);
    28         for (
int i = 0; i < 3; i++)
    29             Matrix.at< 
double >(i, 3) = T.ptr< 
double >(0)[i];
    31     } 
else if (R.depth() == CV_32F) {
    32         cv::Mat Matrix = cv::Mat::eye(4, 4, CV_32FC1);
    33         cv::Mat R33 = cv::Mat(Matrix, cv::Rect(0, 0, 3, 3));
    35             cv::Rodrigues(R, R33);
    36         } 
else if (R.total() == 9) {
    38             R.convertTo(R32, CV_32F);
    42         for (
int i = 0; i < 3; i++)
    43             Matrix.at< 
float >(i, 3) = T.ptr< 
float >(0)[i];
    51         M.convertTo(MTyped, forceType);
    55 vector<cv::Mat> 
IPPE::solvePnP(
const vector<cv::Point3f>  &objPoints,
const  std::vector<cv::Point2f>&imgPoints, cv::InputArray cameraMatrix, cv::InputArray distCoeffs)
    59     float markerLength = cv::norm(objPoints[1]-objPoints[0]);
    60      float reprojErr1, reprojErr2;
    67 std::vector<std::pair<cv::Mat,double> > 
IPPE::solvePnP_(
const std::vector<cv::Point3f> &objPoints,
const  std::vector<cv::Point2f> &imgPoints, cv::InputArray cameraMatrix, cv::InputArray distCoeffs){
    69     float markerLength = cv::norm(objPoints[1]-objPoints[0]);
    70      float reprojErr1, reprojErr2;
    74       return {make_pair(
getRTMatrix(Rvec,Tvec,CV_32F),reprojErr1), make_pair(
getRTMatrix(Rvec2,Tvec2,CV_32F),reprojErr2) } ;
    79                                     OutputArray _rvec1, OutputArray _tvec1, 
float & reprojErr1, OutputArray _rvec2, OutputArray _tvec2, 
float & reprojErr2)
    82     cv::Mat undistortedPoints; 
    83     cv::Mat modelPoints(4, 1,  CV_32FC3);
    85     modelPoints.ptr< Vec3f >(0)[0] = Vec3f(-squareLength / 2.0
f, squareLength / 2.0
f, 0);
    86     modelPoints.ptr< Vec3f >(0)[1] = Vec3f(squareLength / 2.0
f, squareLength / 2.0
f, 0);
    87     modelPoints.ptr< Vec3f >(0)[2] = Vec3f(squareLength / 2.0
f, -squareLength / 2.0
f, 0);
    88     modelPoints.ptr< Vec3f >(0)[3] = Vec3f(-squareLength / 2.0
f, -squareLength / 2.0
f, 0);
    91     _rvec1.create(3,1,CV_64FC1);
    92     _tvec1.create(3,1,CV_64FC1);
    93     _rvec2.create(3,1,CV_64FC1);
    94     _tvec2.create(3,1,CV_64FC1);
    96     cv::Mat H,Ra,Rb,ta,tb;
    97     cv::Mat tvec1 = _tvec1.getMat();
    98     cv::Mat rvec1 = _rvec1.getMat();
    99     cv::Mat tvec2 = _tvec2.getMat();
   100     cv::Mat rvec2 = _rvec2.getMat();
   104     undistortPoints(imagePoints,undistortedPoints,cameraMatrix,distCoeffs);
   110     double j00, j01, j10,j11, v0,v1;
   112     j00 = H.at<
double>(0,0)-H.at<
double>(2,0)*H.at<
double>(0,2);
   113     j01 = H.at<
double>(0,1)-H.at<
double>(2,1)*H.at<
double>(0,2);
   114     j10 = H.at<
double>(1,0)-H.at<
double>(2,0)*H.at<
double>(1,2);
   115     j11 = H.at<
double>(1,1)-H.at<
double>(2,1)*H.at<
double>(1,2);
   118     v0 = H.at<
double>(0,2);
   119     v1 = H.at<
double>(1,2);
   132     if (reprojErra < reprojErrb)
   134         tvec1.at<
double>(0) = ta.at<
double>(0);
   135         tvec1.at<
double>(1) = ta.at<
double>(1);
   136         tvec1.at<
double>(2) = ta.at<
double>(2);
   139         tvec2.at<
double>(0) = tb.at<
double>(0);
   140         tvec2.at<
double>(1) = tb.at<
double>(1);
   141         tvec2.at<
double>(2) = tb.at<
double>(2);
   144         reprojErr1 = reprojErra;
   145         reprojErr2 = reprojErrb;
   149         tvec1.at<
double>(0) = tb.at<
double>(0);
   150         tvec1.at<
double>(1) = tb.at<
double>(1);
   151         tvec1.at<
double>(2) = tb.at<
double>(2);
   154         tvec2.at<
double>(0) = ta.at<
double>(0);
   155         tvec2.at<
double>(1) = ta.at<
double>(1);
   156         tvec2.at<
double>(2) = ta.at<
double>(2);
   159         reprojErr1 = reprojErrb;
   160         reprojErr2 = reprojErra;
   167 int IPPE::IPPEvalBestPose(InputArray _R1, InputArray _R2, InputArray _t1, InputArray _t2, InputArray _objectPoints, InputArray _undistortedPoints)
   169     cv::Mat modelPoints = _objectPoints.getMat();
   170     cv::Mat imgPoints = _undistortedPoints.getMat();
   172     cv::Mat R1 = _R1.getMat();
   173     cv::Mat t1 = _t1.getMat();
   175     cv::Mat R2 = _R2.getMat();
   176     cv::Mat t2 = _t2.getMat();
   178     int numPts = modelPoints.rows;
   182     float reprojError1 = 0; 
   183     float reprojError2 = 0; 
   186     for (
int i=0;i<numPts;i++)
   190         px = R1.at<
double>(0,0)*modelPoints.at<Vec3f>(i)(0) + R1.at<
double>(0,1)*modelPoints.at<Vec3f>(i)(1) + R1.at<
double>(0,2)*modelPoints.at<Vec3f>(i)(2) + t1.at<
double>(0);
   191         py = R1.at<
double>(1,0)*modelPoints.at<Vec3f>(i)(0) + R1.at<
double>(1,1)*modelPoints.at<Vec3f>(i)(1) + R1.at<
double>(1,2)*modelPoints.at<Vec3f>(i)(2) + t1.at<
double>(1);
   192         pz = R1.at<
double>(2,0)*modelPoints.at<Vec3f>(i)(0) + R1.at<
double>(2,1)*modelPoints.at<Vec3f>(i)(1) + R1.at<
double>(2,2)*modelPoints.at<Vec3f>(i)(2) + t1.at<
double>(2);
   194         dx = px/pz - imgPoints.at<Vec2f>(i)(0);
   195         dy = py/pz - imgPoints.at<Vec2f>(i)(1);
   197         reprojError1 = reprojError1 + 
sqrt(dx*dx + dy*dy);
   200         px = R2.at<
double>(0,0)*modelPoints.at<Vec3f>(i)(0) + R2.at<
double>(0,1)*modelPoints.at<Vec3f>(i)(1) + R2.at<
double>(0,2)*modelPoints.at<Vec3f>(i)(2) + t2.at<
double>(0);
   201         py = R2.at<
double>(1,0)*modelPoints.at<Vec3f>(i)(0) + R2.at<
double>(1,1)*modelPoints.at<Vec3f>(i)(1) + R2.at<
double>(1,2)*modelPoints.at<Vec3f>(i)(2) + t2.at<
double>(1);
   202         pz = R2.at<
double>(2,0)*modelPoints.at<Vec3f>(i)(0) + R2.at<
double>(2,1)*modelPoints.at<Vec3f>(i)(1) + R2.at<
double>(2,2)*modelPoints.at<Vec3f>(i)(2) + t2.at<
double>(2);
   204         dx = px/pz - imgPoints.at<Vec2f>(i)(0);
   205         dy = py/pz - imgPoints.at<Vec2f>(i)(1);
   207         reprojError2 = reprojError2 + 
sqrt(dx*dx + dy*dy);
   210     if (reprojError1<reprojError2)
   223     cv::Mat modelPoints = _objectPoints.getMat();
   224     cv::Mat imgPoints = _undistortedPoints.getMat();
   226     cv::Mat R = _R.getMat();
   227     cv::Mat t = _t.getMat();
   229     int numPts = modelPoints.rows;
   231     float reprojError = 0;
   234     for (
int i=0;i<numPts;i++)
   237         px = R.at<
double>(0,0)*modelPoints.at<Vec3f>(i)(0) + R.at<
double>(0,1)*modelPoints.at<Vec3f>(i)(1) + R.at<
double>(0,2)*modelPoints.at<Vec3f>(i)(2) + t.at<
double>(0);
   238         py = R.at<
double>(1,0)*modelPoints.at<Vec3f>(i)(0) + R.at<
double>(1,1)*modelPoints.at<Vec3f>(i)(1) + R.at<
double>(1,2)*modelPoints.at<Vec3f>(i)(2) + t.at<
double>(1);
   239         pz = R.at<
double>(2,0)*modelPoints.at<Vec3f>(i)(0) + R.at<
double>(2,1)*modelPoints.at<Vec3f>(i)(1) + R.at<
double>(2,2)*modelPoints.at<Vec3f>(i)(2) + t.at<
double>(2);
   241         dx = px/pz - imgPoints.at<Vec2f>(i)(0);
   242         dy = py/pz - imgPoints.at<Vec2f>(i)(1);
   244         reprojError = reprojError + 
sqrt(dx*dx + dy*dy);
   253     cv::Mat R = _R.getMat();
   254     cv::Mat rvec = _r.getMat();
   255     double trace = R.at<
double>(0,0) + R.at<
double>(1,1) + R.at<
double>(2,2);
   256     double w_norm = 
acos((trace-1.0)/2.0);
   258     double eps =  std::numeric_limits<double>::epsilon();
   259     double d =  1/(2*
sin(w_norm))*w_norm;
   266         c0 = R.at<
double>(2,1)-R.at<
double>(1,2);
   267         c1 = R.at<
double>(0,2)-R.at<
double>(2,0);
   268         c2 = R.at<
double>(1,0)-R.at<
double>(0,1);
   269         rvec.at<
double>(0) = d*c0;
   270         rvec.at<
double>(1) = d*c1;
   271         rvec.at<
double>(2) = d*c2;
   280     cv::Mat modelPoints = _objectPoints.getMat();
   281     cv::Mat imgPoints = _imgPoints.getMat();
   282     int numPts = modelPoints.rows;
   284     _t.create(3,1,CV_64FC1);
   286     cv::Mat R = _R.getMat();
   289     double ATA00 = numPts;
   291     double ATA11 = numPts;
   305     double S00, S01, S02;
   306     double S10, S11, S12;
   307     double S20, S21, S22;
   315     for (
int i=0;i<numPts;i++)
   317         rx = R.at<
double>(0,0)*modelPoints.at<Vec3f>(i)(0) + R.at<
double>(0,1)*modelPoints.at<Vec3f>(i)(1) + R.at<
double>(0,2)*modelPoints.at<Vec3f>(i)(2);
   318         ry = R.at<
double>(1,0)*modelPoints.at<Vec3f>(i)(0) + R.at<
double>(1,1)*modelPoints.at<Vec3f>(i)(1) + R.at<
double>(1,2)*modelPoints.at<Vec3f>(i)(2);
   319         rz = R.at<
double>(2,0)*modelPoints.at<Vec3f>(i)(0) + R.at<
double>(2,1)*modelPoints.at<Vec3f>(i)(1) + R.at<
double>(2,2)*modelPoints.at<Vec3f>(i)(2);
   320         a2 = -imgPoints.at<Vec2f>(i)(0);
   321         b2 = -imgPoints.at<Vec2f>(i)(1);
   326         ATA22 = ATA22 + a2*a2 + b2*b2;
   327         bx = (imgPoints.at<Vec2f>(i)(0))*rz -  rx;
   328         by = (imgPoints.at<Vec2f>(i)(1))*rz -  ry;
   331         ATb2 = ATb2 + a2*bx + b2*by;
   334     double detAInv = 1.0/(ATA00*ATA11*ATA22 - ATA00*ATA12*ATA21  - ATA02*ATA11*ATA20);
   337     S00 = ATA11*ATA22 - ATA12*ATA21;
   341     S11 = ATA00*ATA22 - ATA02*ATA20;
   349     t.at<
double>(0) = detAInv*(S00*ATb0 + S01*ATb1 + S02*ATb2);
   350     t.at<
double>(1) = detAInv*(S10*ATb0 + S11*ATb1 + S12*ATb2);
   351     t.at<
double>(2) = detAInv*(S20*ATb0 + S21*ATb1 + S22*ATb2);
   355 void IPPE::IPPComputeRotations(
double j00, 
double j01, 
double j10, 
double j11, 
double p, 
double q, OutputArray _R1, OutputArray _R2)
   358     _R1.create(3,3,CV_64FC1);
   359     _R2.create(3,3,CV_64FC1);
   362     double a00, a01, a10,a11, ata00, ata01,ata11,b00, b01, b10,b11,binv00, binv01, binv10,binv11;
   363     double rv00, rv01, rv02,rv10, rv11, rv12,rv20, rv21, rv22;
   364     double rtilde00, rtilde01, rtilde10, rtilde11;
   365     double rtilde00_2, rtilde01_2, rtilde10_2, rtilde11_2;
   366     double b0, b1 ,gamma,dtinv;
   367     double s,t,sp,krs0,krs1,krs0_2, krs1_2,costh,sinth;
   369     s = 
sqrt(p*p + q*q + 1);
   372     sinth = 
sqrt(1-1/(s*s));
   379     rv00=  (costh - 1)*krs0_2 + 1;
   380     rv01 = krs0*krs1*(costh - 1);
   382     rv10 =   krs0*krs1*(costh - 1);
   383     rv11 =   (costh - 1)*krs1_2 + 1;
   387     rv22 =  (costh - 1)*(krs0_2 + krs1_2) + 1;
   395     dtinv =  1.0/((b00*b11 - b01*b10));
   402     a00 = binv00*j00  +  binv01*j10;
   403     a01 = binv00*j01  +  binv01*j11;
   404     a10 = binv10*j00  +  binv11*j10;
   405     a11 = binv10*j01  +  binv11*j11;
   408     ata00 =  a00*a00 + a01*a01;
   409     ata01 = a00*a10 + a01*a11;
   410      ata11 =a10*a10 + a11*a11;
   412     gamma =  
sqrt(0.5*(ata00 +ata11 + 
sqrt((ata00-ata11)*(ata00-ata11) + 4.0*ata01*ata01)));
   415     rtilde00 = a00/gamma;
   416     rtilde01 = a01/gamma;
   417     rtilde10 = a10/gamma;
   418     rtilde11 = a11/gamma;
   420     rtilde00_2 = rtilde00*rtilde00;
   421     rtilde01_2 = rtilde01*rtilde01;
   422     rtilde10_2 = rtilde10*rtilde10;
   423     rtilde11_2 = rtilde11*rtilde11;
   425      b0 =  
sqrt(- rtilde00_2 - rtilde10_2 + 1);
   426     b1 =  
sqrt(- rtilde01_2 - rtilde11_2 + 1);
   427     sp = (- rtilde00*rtilde01 - rtilde10*rtilde11);
   435     Mat R1 = _R1.getMat();
   436     Mat R2 = _R2.getMat();
   438     R1.at<
double>(0,0) = (rtilde00)*rv00 + (rtilde10)*rv01 + (b0)*rv02;
   439     R1.at<
double>(0,1) = (rtilde01)*rv00 + (rtilde11)*rv01 + (b1)*rv02;
   440     R1.at<
double>(0,2) = (b1*rtilde10 - b0*rtilde11)*rv00 + (b0*rtilde01 - b1*rtilde00)*rv01 + (rtilde00*rtilde11 - rtilde01*rtilde10)*rv02;
   441     R1.at<
double>(1,0) = (rtilde00)*rv10 + (rtilde10)*rv11 + (b0)*rv12;
   442     R1.at<
double>(1,1) = (rtilde01)*rv10 + (rtilde11)*rv11 + (b1)*rv12;
   443     R1.at<
double>(1,2) = (b1*rtilde10 - b0*rtilde11)*rv10 + (b0*rtilde01 - b1*rtilde00)*rv11 + (rtilde00*rtilde11 - rtilde01*rtilde10)*rv12;
   444     R1.at<
double>(2,0) = (rtilde00)*rv20 + (rtilde10)*rv21 + (b0)*rv22;
   445     R1.at<
double>(2,1) = (rtilde01)*rv20 + (rtilde11)*rv21 + (b1)*rv22;
   446     R1.at<
double>(2,2) = (b1*rtilde10 - b0*rtilde11)*rv20 + (b0*rtilde01 - b1*rtilde00)*rv21 + (rtilde00*rtilde11 - rtilde01*rtilde10)*rv22;
   448     R2.at<
double>(0,0) = (rtilde00)*rv00 + (rtilde10)*rv01 + (-b0)*rv02;
   449     R2.at<
double>(0,1) = (rtilde01)*rv00 + (rtilde11)*rv01 + (-b1)*rv02;
   450     R2.at<
double>(0,2) = (b0*rtilde11 - b1*rtilde10)*rv00 + (b1*rtilde00 - b0*rtilde01)*rv01 + (rtilde00*rtilde11 - rtilde01*rtilde10)*rv02;
   451     R2.at<
double>(1,0) = (rtilde00)*rv10 + (rtilde10)*rv11 + (-b0)*rv12;
   452     R2.at<
double>(1,1) = (rtilde01)*rv10 + (rtilde11)*rv11 + (-b1)*rv12;
   453     R2.at<
double>(1,2) = (b0*rtilde11 - b1*rtilde10)*rv10 + (b1*rtilde00 - b0*rtilde01)*rv11 + (rtilde00*rtilde11 - rtilde01*rtilde10)*rv12;
   454     R2.at<
double>(2,0) = (rtilde00)*rv20 + (rtilde10)*rv21 + (-b0)*rv22;
   455     R2.at<
double>(2,1) = (rtilde01)*rv20 + (rtilde11)*rv21 + (-b1)*rv22;
   456     R2.at<
double>(2,2) = (b0*rtilde11 - b1*rtilde10)*rv20 + (b1*rtilde00 - b0*rtilde01)*rv21 + (rtilde00*rtilde11 - rtilde01*rtilde10)*rv22;
   463     cv::Mat pts = _targetPts.getMat();
   464     H_.create(3,3,CV_64FC1);
   467     double p1x = -pts.at<Vec2f>(0)(0);
   468     double p1y = -pts.at<Vec2f>(0)(1);
   470     double p2x = -pts.at<Vec2f>(1)(0);
   471     double p2y = -pts.at<Vec2f>(1)(1);
   473     double p3x = -pts.at<Vec2f>(2)(0);
   474     double p3y = -pts.at<Vec2f>(2)(1);
   476     double p4x = -pts.at<Vec2f>(3)(0);
   477     double p4y = -pts.at<Vec2f>(3)(1);
   481     double detsInv = -1/(halfLength*(p1x*p2y - p2x*p1y - p1x*p4y + p2x*p3y - p3x*p2y + p4x*p1y + p3x*p4y - p4x*p3y));
   483     H.at<
double>(0,0) =  detsInv*(p1x*p3x*p2y - p2x*p3x*p1y - p1x*p4x*p2y + p2x*p4x*p1y - p1x*p3x*p4y + p1x*p4x*p3y + p2x*p3x*p4y - p2x*p4x*p3y);
   484     H.at<
double>(0,1) =  detsInv*(p1x*p2x*p3y - p1x*p3x*p2y - p1x*p2x*p4y + p2x*p4x*p1y + p1x*p3x*p4y - p3x*p4x*p1y - p2x*p4x*p3y + p3x*p4x*p2y);
   485     H.at<
double>(0,2) =  detsInv*halfLength*(p1x*p2x*p3y - p2x*p3x*p1y - p1x*p2x*p4y + p1x*p4x*p2y - p1x*p4x*p3y + p3x*p4x*p1y + p2x*p3x*p4y - p3x*p4x*p2y);
   486     H.at<
double>(1,0) =  detsInv*(p1x*p2y*p3y - p2x*p1y*p3y - p1x*p2y*p4y + p2x*p1y*p4y - p3x*p1y*p4y + p4x*p1y*p3y + p3x*p2y*p4y - p4x*p2y*p3y);
   487     H.at<
double>(1,1) =  detsInv*(p2x*p1y*p3y - p3x*p1y*p2y - p1x*p2y*p4y + p4x*p1y*p2y + p1x*p3y*p4y - p4x*p1y*p3y - p2x*p3y*p4y + p3x*p2y*p4y);
   488     H.at<
double>(1,2) =  detsInv*halfLength*(p1x*p2y*p3y - p3x*p1y*p2y - p2x*p1y*p4y + p4x*p1y*p2y - p1x*p3y*p4y + p3x*p1y*p4y + p2x*p3y*p4y - p4x*p2y*p3y);
   489     H.at<
double>(2,0) =                                  -detsInv*(p1x*p3y - p3x*p1y - p1x*p4y - p2x*p3y + p3x*p2y + p4x*p1y + p2x*p4y - p4x*p2y);
   490     H.at<
double>(2,1) =                                 detsInv*(p1x*p2y - p2x*p1y - p1x*p3y + p3x*p1y + p2x*p4y - p4x*p2y - p3x*p4y + p4x*p3y);
   491     H.at<
double>(2,2) = 1.0;
 
std::vector< cv::Mat > solvePnP(const std::vector< cv::Point3f > &objPoints, const std::vector< cv::Point2f > &imgPoints, cv::InputArray cameraMatrix, cv::InputArray distCoeffs)
void IPPERot2vec(cv::InputArray _R, cv::OutputArray _r)
Fast conversion from a rotation matrix to a rotation vector using Rodrigues' formula. 
void homographyFromSquarePoints(cv::InputArray _targetPts, double halfLength, cv::OutputArray _H)
Closed-form solution for the homography mapping with four corner correspondences of a square (it maps...
void solvePoseOfCentredSquare(float squareLength, cv::InputArray imagePoints, cv::InputArray cameraMatrix, cv::InputArray distCoeffs, cv::OutputArray _rvec1, cv::OutputArray _tvec1, float &reprojErr1, cv::OutputArray _rvec2, cv::OutputArray _tvec2, float &reprojErr2)
Finds the two possible poses of a square planar object given its four corner correspondences in an im...
int IPPEvalBestPose(cv::InputArray _R1, cv::InputArray _R2, cv::InputArray _t1, cv::InputArray _t2, cv::InputArray _objectPoints, cv::InputArray _undistortedPoints)
Determines which of the two pose solutions from IPPE has the lowest reprojection error. 
cv::Mat getRTMatrix(const cv::Mat &R_, const cv::Mat &T_, int forceType)
const CwiseUnaryOp< internal::scalar_sin_op< Scalar >, const Derived > sin() const 
float IPPEvalReprojectionError(cv::InputArray _R, cv::InputArray _t, cv::InputArray _objectPoints, cv::InputArray _undistortedPoints)
Determines the reprojection error of a pose solution. 
void IPPComputeTranslation(cv::InputArray _objectPoints, cv::InputArray _imgPoints, cv::InputArray _R, cv::OutputArray _t)
Computes the translation solution for a given rotation solution. 
void IPPComputeRotations(double j00, double j01, double j10, double j11, double p, double q, cv::OutputArray _R1, cv::OutputArray _R2)
Computes the two rotation solutions from the Jacobian of a homography matrix H. For highest accuracy ...
std::vector< std::pair< cv::Mat, double > > solvePnP_(const std::vector< cv::Point3f > &objPoints, const std::vector< cv::Point2f > &imgPoints, cv::InputArray cameraMatrix, cv::InputArray distCoeffs)
const CwiseUnaryOp< internal::scalar_sqrt_op< Scalar >, const Derived > sqrt() const 
const CwiseUnaryOp< internal::scalar_acos_op< Scalar >, const Derived > acos() const