Skip to content

Commit 98c78e0

Browse files
committed
Use directly solvePnP when the number of input points is equal to the number of model points. Enable useExtrinsicGuess parameter. Return rvec and tvec estimated using all the inliers instead of the best rvec and tvec estimated during the Minimal Sample Sets step. Document the behavior of solvePnPRansac.
1 parent 7b8e630 commit 98c78e0

File tree

2 files changed

+62
-22
lines changed

2 files changed

+62
-22
lines changed

modules/calib3d/include/opencv2/calib3d.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,13 @@ makes the function resistant to outliers.
627627
@note
628628
- An example of how to use solvePNPRansac for object detection can be found at
629629
opencv_source_code/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/
630+
- The default method used to estimate the camera pose for the Minimal Sample Sets step
631+
is #SOLVEPNP_EPNP. Exceptions are:
632+
- if you choose #SOLVEPNP_P3P or #SOLVEPNP_AP3P, these methods will be used.
633+
- if the number of input points is equal to 4, #SOLVEPNP_P3P is used.
634+
- The method used to estimate the camera pose using all the inliers is defined by the
635+
flags parameters unless it is equal to #SOLVEPNP_P3P or #SOLVEPNP_AP3P. In this case,
636+
the method #SOLVEPNP_EPNP will be used instead.
630637
*/
631638
CV_EXPORTS_W bool solvePnPRansac( InputArray objectPoints, InputArray imagePoints,
632639
InputArray cameraMatrix, InputArray distCoeffs,

modules/calib3d/src/solvepnp.cpp

Lines changed: 55 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ bool solvePnPRansac(InputArray _opoints, InputArray _ipoints,
249249
ipoints = ipoints0;
250250

251251
int npoints = std::max(opoints.checkVector(3, CV_32F), opoints.checkVector(3, CV_64F));
252-
CV_Assert( npoints >= 0 && npoints == std::max(ipoints.checkVector(2, CV_32F), ipoints.checkVector(2, CV_64F)) );
252+
CV_Assert( npoints >= 4 && npoints == std::max(ipoints.checkVector(2, CV_32F), ipoints.checkVector(2, CV_64F)) );
253253

254254
CV_Assert(opoints.isContinuous());
255255
CV_Assert(opoints.depth() == CV_32F || opoints.depth() == CV_64F);
@@ -279,6 +279,31 @@ bool solvePnPRansac(InputArray _opoints, InputArray _ipoints,
279279
ransac_kernel_method = SOLVEPNP_P3P;
280280
}
281281

282+
if( model_points == npoints )
283+
{
284+
bool result = solvePnP(opoints, ipoints, cameraMatrix, distCoeffs, _rvec, _tvec, useExtrinsicGuess, ransac_kernel_method);
285+
286+
if(!result)
287+
{
288+
if( _inliers.needed() )
289+
_inliers.release();
290+
291+
return false;
292+
}
293+
294+
if(_inliers.needed())
295+
{
296+
_inliers.create(npoints, 1, CV_32S);
297+
Mat _local_inliers = _inliers.getMat();
298+
for(int i = 0; i < npoints; i++)
299+
{
300+
_local_inliers.at<int>(i) = i;
301+
}
302+
}
303+
304+
return true;
305+
}
306+
282307
Ptr<PointSetRegistrator::Callback> cb; // pointer to callback
283308
cb = makePtr<PnPRansacCallback>( cameraMatrix, distCoeffs, ransac_kernel_method, useExtrinsicGuess, rvec, tvec);
284309

@@ -293,26 +318,6 @@ bool solvePnPRansac(InputArray _opoints, InputArray _ipoints,
293318
int result = createRANSACPointSetRegistrator(cb, model_points,
294319
param1, param2, param3)->run(opoints, ipoints, _local_model, _mask_local_inliers);
295320

296-
if( result > 0 )
297-
{
298-
vector<Point3d> opoints_inliers;
299-
vector<Point2d> ipoints_inliers;
300-
opoints = opoints.reshape(3);
301-
ipoints = ipoints.reshape(2);
302-
opoints.convertTo(opoints_inliers, CV_64F);
303-
ipoints.convertTo(ipoints_inliers, CV_64F);
304-
305-
const uchar* mask = _mask_local_inliers.ptr<uchar>();
306-
int npoints1 = compressElems(&opoints_inliers[0], mask, 1, npoints);
307-
compressElems(&ipoints_inliers[0], mask, 1, npoints);
308-
309-
opoints_inliers.resize(npoints1);
310-
ipoints_inliers.resize(npoints1);
311-
result = solvePnP(opoints_inliers, ipoints_inliers, cameraMatrix,
312-
distCoeffs, rvec, tvec, false,
313-
(flags == SOLVEPNP_P3P || flags == SOLVEPNP_AP3P) ? SOLVEPNP_EPNP : flags) ? 1 : -1;
314-
}
315-
316321
if( result <= 0 || _local_model.rows <= 0)
317322
{
318323
_rvec.assign(rvec); // output rotation vector
@@ -323,10 +328,38 @@ bool solvePnPRansac(InputArray _opoints, InputArray _ipoints,
323328

324329
return false;
325330
}
326-
else
331+
332+
vector<Point3d> opoints_inliers;
333+
vector<Point2d> ipoints_inliers;
334+
opoints = opoints.reshape(3);
335+
ipoints = ipoints.reshape(2);
336+
opoints.convertTo(opoints_inliers, CV_64F);
337+
ipoints.convertTo(ipoints_inliers, CV_64F);
338+
339+
const uchar* mask = _mask_local_inliers.ptr<uchar>();
340+
int npoints1 = compressElems(&opoints_inliers[0], mask, 1, npoints);
341+
compressElems(&ipoints_inliers[0], mask, 1, npoints);
342+
343+
opoints_inliers.resize(npoints1);
344+
ipoints_inliers.resize(npoints1);
345+
result = solvePnP(opoints_inliers, ipoints_inliers, cameraMatrix,
346+
distCoeffs, rvec, tvec, useExtrinsicGuess,
347+
(flags == SOLVEPNP_P3P || flags == SOLVEPNP_AP3P) ? SOLVEPNP_EPNP : flags) ? 1 : -1;
348+
349+
if( result <= 0 )
327350
{
328351
_rvec.assign(_local_model.col(0)); // output rotation vector
329352
_tvec.assign(_local_model.col(1)); // output translation vector
353+
354+
if( _inliers.needed() )
355+
_inliers.release();
356+
357+
return false;
358+
}
359+
else
360+
{
361+
_rvec.assign(rvec); // output rotation vector
362+
_tvec.assign(tvec); // output translation vector
330363
}
331364

332365
if(_inliers.needed())

0 commit comments

Comments
 (0)