Skip to content

Commit 42c0914

Browse files
committed
Merge pull request opencv#9086 from catree:improve_solvePnPRansac
2 parents 49e1f6b + 98c78e0 commit 42c0914

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)