solvePnPRansac and solvePnP output consistency (Bug #2508)
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
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