solvePnPRansac and solvePnP output consistency (Bug #2508)


Added by Simone Gasparini over 12 years ago. Updated almost 10 years ago.


Status:Done Start date:2012-11-05
Priority:Normal Due date:
Assignee:- % Done:

0%

Category:calibration, 3d
Target version:3.0
Affected version:branch 'master' (3.0-dev) Operating System:Any
Difficulty: HW Platform:Any
Pull request:

Description

Both solvePnPRansac and solvePnP always return rvec and tvec as CV_64F matrices, no matter the type of the input points.

For example solvePnPRansac in solvepnp.cpp (modules/calib3d/src) line 308

    CV_Assert(opoints.isContinuous());
    CV_Assert(opoints.depth() == CV_32F);
    CV_Assert((opoints.rows == 1 && opoints.channels() == 3) || opoints.cols*opoints.channels() == 3);
    CV_Assert(ipoints.isContinuous());
    CV_Assert(ipoints.depth() == CV_32F);
    CV_Assert((ipoints.rows == 1 && ipoints.channels() == 2) || ipoints.cols*ipoints.channels() == 2);

    _rvec.create(3, 1, CV_64FC1);
    _tvec.create(3, 1, CV_64FC1);

it requires the input points to be 32F while the generate output _rvec and _tvec are 64F. This is inconsistent and may force a later conversion if we need to use the _rvec and _tvec in any operation with the input points (eg. computing the reprojection error, we need to multiply the 3D points by the matrix composed by _rvec and _tvec).

The same happens in solvePnP and, furthermore, solvePnP does seem to support both 32F and 64F for input points (line 54)

    int npoints = std::max(opoints.checkVector(3, CV_32F), opoints.checkVector(3, CV_64F));
    CV_Assert( npoints >= 0 && npoints == std::max(ipoints.checkVector(2, CV_32F), ipoints.checkVector(2, CV_64F)) );
    _rvec.create(3, 1, CV_64F);
    _tvec.create(3, 1, CV_64F);

I don't know whether there is a precise design behind this, but it would be better to make everything more coherent:

1) _rvec and _tvec should be of the same type as the input, so i think just applying this to both functions would be enough

    _rvec.create(3, 1, opoints.type());
    _tvec.create(3, 1, opoints.type());

Also an assert checking that opoints and ipoints have the same type should be added before.

2) (This is maybe more a wanted feature) if there are no other constraint that i'm not aware of opoints and ipoints in solvePnPRansac should be allowed to be either 32F or 64F. In this case it should be enough to change the above asserts to

  CV_Assert(opoints.depth() == CV_32F || opoints.depth() == CV_64F);
  ...
  CV_Assert(ipoints.depth() == CV_32F || ipoints.depth() == CV_64F);

3) Finally in case 2) is accepted the relevant documentation has to be changed accordingly. In any case the current documentation explicity says to use 32F points as input. Maybe it should mention that for solvePnP also 64F can be used

Thanks!

Simone


Related issues

related to Bugfix #3799: solvePnPRansac rejects double precision Done 2014-07-07

Associated revisions

Revision 8ac93f9b
Added by Andrey Pavlenko almost 11 years ago

Merge pull request #2508 from akarsakov:fix_erode_intel

History

Updated by Vadim Pisarevsky almost 10 years ago

I believe, the problem has been solved in https://github.com/Itseez/opencv/pull/4053

  • Target version set to 3.0
  • HW Platform set to Any
  • Operating System set to Any
  • Affected version set to branch 'master' (3.0-dev)

Updated by Vadim Pisarevsky almost 10 years ago

  • Status changed from Open to Done

Also available in: Atom PDF