56 PnPRansacCallback(Mat _cameraMatrix=Mat(3,3,CV_64F), Mat _distCoeffs=Mat(4,1,CV_64F),
int _flags=CV_ITERATIVE,
57 bool _useExtrinsicGuess=
false, Mat _rvec=Mat(), Mat _tvec=Mat() )
58 : cameraMatrix(_cameraMatrix), distCoeffs(_distCoeffs), flags(_flags), useExtrinsicGuess(_useExtrinsicGuess),
59 rvec(_rvec), tvec(_tvec) {}
63 int runKernel( InputArray _m1, InputArray _m2, OutputArray _model )
const 65 Mat opoints = _m1.getMat(), ipoints = _m2.getMat();
67 bool correspondence = solvePnP( _m1, _m2, cameraMatrix, distCoeffs,
68 rvec, tvec, useExtrinsicGuess, flags );
71 hconcat(rvec, tvec, _local_model);
72 _local_model.copyTo(_model);
74 return correspondence;
79 void computeError( InputArray _m1, InputArray _m2, InputArray _model, OutputArray _err )
const 82 Mat opoints = _m1.getMat(), ipoints = _m2.getMat(), model = _model.getMat();
84 int i, count = opoints.checkVector(3);
85 Mat _rvec = model.col(0);
86 Mat _tvec = model.col(1);
89 Mat projpoints(count, 2, CV_32FC1);
90 projectPoints(opoints, _rvec, _tvec, cameraMatrix, distCoeffs, projpoints);
92 const Point2f* ipoints_ptr = ipoints.ptr<Point2f>();
93 const Point2f* projpoints_ptr = projpoints.ptr<Point2f>();
95 _err.create(count, 1, CV_32FC1);
96 float* err = _err.getMat().ptr<
float>();
98 for ( i = 0; i < count; ++i)
99 err[i] = (
float)norm( ipoints_ptr[i] - projpoints_ptr[i] );
113 InputArray _cameraMatrix, InputArray _distCoeffs,
114 OutputArray _rvec, OutputArray _tvec,
bool useExtrinsicGuess,
115 int iterationsCount,
float reprojectionError,
double confidence,
116 OutputArray _inliers,
int flags)
119 Mat opoints0 = _opoints.getMat(), ipoints0 = _ipoints.getMat();
120 Mat opoints, ipoints;
121 if( opoints0.depth() == CV_64F || !opoints0.isContinuous() )
122 opoints0.convertTo(opoints, CV_32F);
125 if( ipoints0.depth() == CV_64F || !ipoints0.isContinuous() )
126 ipoints0.convertTo(ipoints, CV_32F);
130 int npoints =
std::max(opoints.checkVector(3, CV_32F), opoints.checkVector(3, CV_64F));
131 CV_Assert( npoints >= 0 && npoints ==
std::max(ipoints.checkVector(2, CV_32F), ipoints.checkVector(2, CV_64F)) );
133 CV_Assert(opoints.isContinuous());
134 CV_Assert(opoints.depth() == CV_32F || opoints.depth() == CV_64F);
135 CV_Assert((opoints.rows == 1 && opoints.channels() == 3) || opoints.cols*opoints.channels() == 3);
136 CV_Assert(ipoints.isContinuous());
137 CV_Assert(ipoints.depth() == CV_32F || ipoints.depth() == CV_64F);
138 CV_Assert((ipoints.rows == 1 && ipoints.channels() == 2) || ipoints.cols*ipoints.channels() == 2);
140 _rvec.create(3, 1, CV_64FC1);
141 _tvec.create(3, 1, CV_64FC1);
143 Mat rvec = useExtrinsicGuess ? _rvec.getMat() : Mat(3, 1, CV_64FC1);
144 Mat tvec = useExtrinsicGuess ? _tvec.getMat() : Mat(3, 1, CV_64FC1);
145 Mat cameraMatrix = _cameraMatrix.getMat(), distCoeffs = _distCoeffs.getMat();
147 int model_points = 5;
148 int ransac_kernel_method = CV_EPNP;
153 ransac_kernel_method = CV_P3P;
156 Ptr<PointSetRegistrator::Callback> cb;
157 cb = Ptr<PnPRansacCallback>(
new PnPRansacCallback( cameraMatrix, distCoeffs, ransac_kernel_method, useExtrinsicGuess, rvec, tvec));
159 double param1 = reprojectionError;
160 double param2 = confidence;
161 int param3 = iterationsCount;
163 Mat _local_model(3, 2, CV_64FC1);
164 Mat _mask_local_inliers(1, opoints.rows, CV_8UC1);
168 param1, param2, param3)->run(opoints, ipoints, _local_model, _mask_local_inliers);
172 std::vector<Point3d> opoints_inliers;
173 std::vector<Point2d> ipoints_inliers;
174 opoints.convertTo(opoints_inliers, CV_64F);
175 ipoints.convertTo(ipoints_inliers, CV_64F);
178 int npoints1 =
compressElems(&opoints_inliers[0], mask, 1, npoints);
181 opoints_inliers.resize(npoints1);
182 ipoints_inliers.resize(npoints1);
183 result = solvePnP(opoints_inliers, ipoints_inliers, cameraMatrix,
184 distCoeffs, rvec, tvec,
false, flags == CV_P3P ? CV_EPNP : flags) ? 1 : -1;
187 if( result <= 0 || _local_model.rows <= 0)
192 if( _inliers.needed() )
199 _local_model.col(0).copyTo(_rvec);
200 _local_model.col(1).copyTo(_tvec);
203 if(_inliers.needed())
206 for (
int i = 0; i < npoints; ++i)
208 if((
int)_mask_local_inliers.at<
uchar>(i) != 0)
209 _local_inliers.push_back(i);
211 _local_inliers.copyTo(_inliers);
218 if( modelPoints <= 0 )
219 CV_Error( 0,
"the number of model points should be positive" );
227 double num =
MAX(1. - p, DBL_MIN);
228 double denom = 1. -
std::pow(1. - ep, modelPoints);
229 if( denom < DBL_MIN )
235 return denom >= 0 || -num >= maxIters*(-denom) ? maxIters : cvRound(num/denom);
242 int _modelPoints=0,
double _threshold=0,
double _confidence=0.99,
int _maxIters=1000)
243 : cb(_cb), modelPoints(_modelPoints), threshold(_threshold), confidence(_confidence), maxIters(_maxIters)
245 checkPartialSubsets =
false;
248 int findInliers(
const Mat& m1,
const Mat& m2,
const Mat& model, Mat& err, Mat&
mask,
double thresh )
const 250 cb->computeError( m1, m2, model, err );
251 mask.create(err.size(), CV_8U);
253 CV_Assert( err.isContinuous() && err.type() == CV_32F && mask.isContinuous() && mask.type() == CV_8U);
254 const float* errptr = err.ptr<
float>();
256 float t = (float)(thresh*thresh);
257 int i, n = (int)err.total(), nz = 0;
258 for( i = 0; i < n; i++ )
260 int f = errptr[i] <= t;
261 maskptr[i] = (
uchar)f;
268 Mat& ms1, Mat& ms2, RNG& rng,
269 int maxAttempts=1000 )
const 271 cv::AutoBuffer<int> _idx(modelPoints);
273 int i = 0, j, k, iters = 0;
274 int esz1 = (int)m1.elemSize(), esz2 = (int)m2.elemSize();
275 int d1 = m1.channels() > 1 ? m1.channels() : m1.cols;
276 int d2 = m2.channels() > 1 ? m2.channels() : m2.cols;
277 int count = m1.checkVector(d1), count2 = m2.checkVector(d2);
278 const int *m1ptr = m1.ptr<
int>(), *m2ptr = m2.ptr<
int>();
280 ms1.create(modelPoints, 1, CV_MAKETYPE(m1.depth(), d1));
281 ms2.create(modelPoints, 1, CV_MAKETYPE(m2.depth(), d2));
283 int *ms1ptr = ms1.ptr<
int>(), *ms2ptr = ms2.ptr<
int>();
285 CV_Assert( count >= modelPoints && count == count2 );
286 CV_Assert( (esz1 %
sizeof(
int)) == 0 && (esz2 %
sizeof(
int)) == 0 );
290 for(; iters < maxAttempts; iters++)
292 for( i = 0; i < modelPoints && iters < maxAttempts; )
297 idx_i = idx[i] = rng.uniform(0, count);
298 for( j = 0; j < i; j++ )
299 if( idx_i == idx[j] )
304 for( k = 0; k < esz1; k++ )
305 ms1ptr[i*esz1 + k] = m1ptr[idx_i*esz1 + k];
306 for( k = 0; k < esz2; k++ )
307 ms2ptr[i*esz2 + k] = m2ptr[idx_i*esz2 + k];
308 if( checkPartialSubsets && !cb->checkSubset( ms1, ms2, i+1 ))
312 i = rng.uniform(0, i+1);
318 if( !checkPartialSubsets && i == modelPoints && !cb->checkSubset(ms1, ms2, i))
323 return i == modelPoints && iters < maxAttempts;
326 bool run(InputArray _m1, InputArray _m2, OutputArray _model, OutputArray _mask)
const 329 Mat m1 = _m1.getMat(), m2 = _m2.getMat();
330 Mat err,
mask, model, bestModel, ms1, ms2;
332 int iter, niters =
MAX(maxIters, 1);
333 int d1 = m1.channels() > 1 ? m1.channels() : m1.cols;
334 int d2 = m2.channels() > 1 ? m2.channels() : m2.cols;
335 int count = m1.checkVector(d1), count2 = m2.checkVector(d2), maxGoodCount = 0;
340 CV_Assert( confidence > 0 && confidence < 1 );
342 CV_Assert( count >= 0 && count2 == count );
343 if( count < modelPoints )
346 Mat bestMask0, bestMask;
350 _mask.create(count, 1, CV_8U, -1,
true);
351 bestMask0 = bestMask = _mask.getMat();
352 CV_Assert( (bestMask.cols == 1 || bestMask.rows == 1) && (
int)bestMask.total() == count );
356 bestMask.create(count, 1, CV_8U);
357 bestMask0 = bestMask;
360 if( count == modelPoints )
362 if( cb->runKernel(m1, m2, bestModel) <= 0 )
364 bestModel.copyTo(_model);
369 for( iter = 0; iter < niters; iter++ )
371 int i, goodCount, nmodels;
372 if( count > modelPoints )
374 bool found = getSubset( m1, m2, ms1, ms2, rng, 10000 );
383 nmodels = cb->runKernel( ms1, ms2, model );
386 CV_Assert( model.rows % nmodels == 0 );
387 Size modelSize(model.cols, model.rows/nmodels);
389 for( i = 0; i < nmodels; i++ )
391 Mat model_i = model.rowRange( i*modelSize.height, (i+1)*modelSize.height );
392 goodCount = findInliers( m1, m2, model_i, err, mask, threshold );
394 if( goodCount >
MAX(maxGoodCount, modelPoints-1) )
396 std::swap(mask, bestMask);
397 model_i.copyTo(bestModel);
398 maxGoodCount = goodCount;
399 niters =
RANSACUpdateNumIters( confidence, (
double)(count - goodCount)/count, modelPoints, niters );
404 if( maxGoodCount > 0 )
406 if( bestMask.data != bestMask0.data )
408 if( bestMask.size() == bestMask0.size() )
409 bestMask.copyTo(bestMask0);
411 transpose(bestMask, bestMask0);
413 bestModel.copyTo(_model);
422 void setCallback(
const Ptr<PointSetRegistrator::Callback>& _cb) { cb = _cb; }
424 Ptr<PointSetRegistrator::Callback>
cb;
436 int _modelPoints=0,
double _confidence=0.99,
int _maxIters=1000)
439 bool run(InputArray _m1, InputArray _m2, OutputArray _model, OutputArray _mask)
const 441 const double outlierRatio = 0.45;
443 Mat m1 = _m1.getMat(), m2 = _m2.getMat();
444 Mat ms1, ms2, err, errf, model, bestModel,
mask, mask0;
446 int d1 = m1.channels() > 1 ? m1.channels() : m1.cols;
447 int d2 = m2.channels() > 1 ? m2.channels() : m2.cols;
448 int count = m1.checkVector(d1), count2 = m2.checkVector(d2);
449 double minMedian = DBL_MAX, sigma;
454 CV_Assert( confidence > 0 && confidence < 1 );
456 CV_Assert( count >= 0 && count2 == count );
457 if( count < modelPoints )
462 _mask.create(count, 1, CV_8U, -1,
true);
463 mask0 = mask = _mask.getMat();
464 CV_Assert( (mask.cols == 1 || mask.rows == 1) && (
int)mask.total() == count );
467 if( count == modelPoints )
469 if( cb->runKernel(m1, m2, bestModel) <= 0 )
471 bestModel.copyTo(_model);
477 niters =
MAX(niters, 3);
479 for( iter = 0; iter < niters; iter++ )
482 if( count > modelPoints )
484 bool found = getSubset( m1, m2, ms1, ms2, rng );
493 nmodels = cb->runKernel( ms1, ms2, model );
497 CV_Assert( model.rows % nmodels == 0 );
498 Size modelSize(model.cols, model.rows/nmodels);
500 for( i = 0; i < nmodels; i++ )
502 Mat model_i = model.rowRange( i*modelSize.height, (i+1)*modelSize.height );
503 cb->computeError( m1, m2, model_i, err );
504 if( err.depth() != CV_32F )
505 err.convertTo(errf, CV_32F);
508 CV_Assert( errf.isContinuous() && errf.type() == CV_32F && (int)errf.total() == count );
509 std::sort(errf.ptr<
int>(), errf.ptr<
int>() + count);
511 double median = count % 2 != 0 ?
512 errf.at<
float>(count/2) : (errf.at<
float>(count/2-1) + errf.at<
float>(count/2))*0.5;
514 if( median < minMedian )
517 model_i.copyTo(bestModel);
522 if( minMedian < DBL_MAX )
524 sigma = 2.5*1.4826*(1 + 5./(count - modelPoints))*
std::sqrt(minMedian);
525 sigma =
MAX( sigma, 0.001 );
527 count = findInliers( m1, m2, bestModel, err, mask, sigma );
528 if( _mask.needed() && mask0.data != mask.data )
530 if( mask0.size() == mask.size() )
533 transpose(mask, mask0);
535 bestModel.copyTo(_model);
536 result = count >= modelPoints;
547 int _modelPoints,
double _threshold,
548 double _confidence,
int _maxIters)
550 return Ptr<PointSetRegistrator>(
556 int _modelPoints,
double _confidence,
int _maxIters)
558 return Ptr<PointSetRegistrator>(
566 int runKernel( InputArray _m1, InputArray _m2, OutputArray _model )
const 568 Mat m1 = _m1.getMat(), m2 = _m2.getMat();
569 const Point3f* from = m1.ptr<Point3f>();
570 const Point3f* to = m2.ptr<Point3f>();
573 double buf[N*N + N + N];
574 Mat A(N, N, CV_64F, &buf[0]);
575 Mat B(N, 1, CV_64F, &buf[0] + N*N);
576 Mat X(N, 1, CV_64F, &buf[0] + N*N + N);
577 double* Adata = A.ptr<
double>();
578 double* Bdata = B.ptr<
double>();
581 for(
int i = 0; i < (N/3); i++ )
583 Bdata[i*3] = to[i].x;
584 Bdata[i*3+1] = to[i].y;
585 Bdata[i*3+2] = to[i].z;
587 double *aptr = Adata + i*3*N;
588 for(
int k = 0; k < 3; ++k)
598 solve(A, B, X, DECOMP_SVD);
599 X.reshape(1, 3).copyTo(_model);
604 void computeError( InputArray _m1, InputArray _m2, InputArray _model, OutputArray _err )
const 606 Mat m1 = _m1.getMat(), m2 = _m2.getMat(), model = _model.getMat();
607 const Point3f* from = m1.ptr<Point3f>();
608 const Point3f* to = m2.ptr<Point3f>();
609 const double* F = model.ptr<
double>();
611 int count = m1.checkVector(3);
612 CV_Assert( count > 0 );
614 _err.create(count, 1, CV_32F);
615 Mat err = _err.getMat();
616 float* errptr = err.ptr<
float>();
618 for(
int i = 0; i < count; i++ )
620 const Point3f&
f = from[i];
621 const Point3f& t = to[i];
623 double a = F[0]*f.x + F[1]*f.y + F[ 2]*f.z + F[ 3] - t.x;
624 double b = F[4]*f.x + F[5]*f.y + F[ 6]*f.z + F[ 7] - t.y;
625 double c = F[8]*f.x + F[9]*f.y + F[10]*f.z + F[11] - t.z;
627 errptr[i] = (float)
std::sqrt(a*a + b*b + c*c);
631 bool checkSubset( InputArray _ms1, InputArray _ms2,
int count )
const 633 const float threshold = 0.996f;
634 Mat ms1 = _ms1.getMat(), ms2 = _ms2.getMat();
636 for(
int inp = 1; inp <= 2; inp++ )
638 int j, k, i = count - 1;
639 const Mat* msi = inp == 1 ? &ms1 : &ms2;
640 const Point3f* ptr = msi->ptr<Point3f>();
642 CV_Assert( count <= msi->rows );
646 for(j = 0; j < i; ++j)
648 Point3f d1 = ptr[j] - ptr[i];
649 float n1 = d1.x*d1.x + d1.y*d1.y;
651 for(k = 0; k < j; ++k)
653 Point3f d2 = ptr[k] - ptr[i];
654 float denom = (d2.x*d2.x + d2.y*d2.y)*n1;
655 float num = d1.x*d2.x + d1.y*d2.y;
657 if( num*num > threshold*threshold*denom )
GLM_FUNC_DECL genType log(genType const &x)
GLM_FUNC_DECL genIType mask(genIType const &count)
int RANSACUpdateNumIters(double p, double ep, int modelPoints, int maxIters)
Ptr< PointSetRegistrator > createRANSACPointSetRegistrator(const Ptr< PointSetRegistrator::Callback > &_cb, int _modelPoints, double _threshold, double _confidence, int _maxIters)
bool getSubset(const Mat &m1, const Mat &m2, Mat &ms1, Mat &ms2, RNG &rng, int maxAttempts=1000) const
Ptr< PointSetRegistrator::Callback > cb
GLM_FUNC_DECL vecType< T, P > sqrt(vecType< T, P > const &x)
bool run(InputArray _m1, InputArray _m2, OutputArray _model, OutputArray _mask) const
RANSACPointSetRegistrator(const Ptr< PointSetRegistrator::Callback > &_cb=Ptr< PointSetRegistrator::Callback >(), int _modelPoints=0, double _threshold=0, double _confidence=0.99, int _maxIters=1000)
GLM_FUNC_DECL bool all(vecType< bool, P > const &v)
bool solvePnPRansac(InputArray _opoints, InputArray _ipoints, InputArray _cameraMatrix, InputArray _distCoeffs, OutputArray _rvec, OutputArray _tvec, bool useExtrinsicGuess, int iterationsCount, float reprojectionError, double confidence, OutputArray _inliers, int flags)
int runKernel(InputArray _m1, InputArray _m2, OutputArray _model) const
void computeError(InputArray _m1, InputArray _m2, InputArray _model, OutputArray _err) const
bool run(InputArray _m1, InputArray _m2, OutputArray _model, OutputArray _mask) const
int findInliers(const Mat &m1, const Mat &m2, const Mat &model, Mat &err, Mat &mask, double thresh) const
int compressElems(T *ptr, const uchar *mask, int mstep, int count)
bool checkSubset(InputArray _ms1, InputArray _ms2, int count) const
unsigned long long uint64
GLM_FUNC_DECL genType max(genType const &x, genType const &y)
GLM_FUNC_DECL genType pow(genType const &base, genType const &exponent)
void computeError(InputArray _m1, InputArray _m2, InputArray _model, OutputArray _err) const
int runKernel(InputArray _m1, InputArray _m2, OutputArray _model) const
LMeDSPointSetRegistrator(const Ptr< PointSetRegistrator::Callback > &_cb=Ptr< PointSetRegistrator::Callback >(), int _modelPoints=0, double _confidence=0.99, int _maxIters=1000)
PnPRansacCallback(Mat _cameraMatrix=Mat(3, 3, CV_64F), Mat _distCoeffs=Mat(4, 1, CV_64F), int _flags=CV_ITERATIVE, bool _useExtrinsicGuess=false, Mat _rvec=Mat(), Mat _tvec=Mat())
void setCallback(const Ptr< PointSetRegistrator::Callback > &_cb)
Ptr< PointSetRegistrator > createLMeDSPointSetRegistrator(const Ptr< PointSetRegistrator::Callback > &_cb, int _modelPoints, double _confidence, int _maxIters)