PageRenderTime 49ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/calib3d/src/ptsetreg.cpp

https://gitlab.com/gaurav1981/opencv
C++ | 538 lines | 409 code | 84 blank | 45 comment | 105 complexity | 337801ce93a08a263b00327139249362 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-3.0
  1. /*M///////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
  4. //
  5. // By downloading, copying, installing or using the software you agree to this license.
  6. // If you do not agree to this license, do not download, install,
  7. // copy or use the software.
  8. //
  9. //
  10. // License Agreement
  11. // For Open Source Computer Vision Library
  12. //
  13. // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
  14. // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
  15. // Copyright (C) 2013, OpenCV Foundation, all rights reserved.
  16. // Third party copyrights are property of their respective owners.
  17. //
  18. // Redistribution and use in source and binary forms, with or without modification,
  19. // are permitted provided that the following conditions are met:
  20. //
  21. // * Redistribution's of source code must retain the above copyright notice,
  22. // this list of conditions and the following disclaimer.
  23. //
  24. // * Redistribution's in binary form must reproduce the above copyright notice,
  25. // this list of conditions and the following disclaimer in the documentation
  26. // and/or other materials provided with the distribution.
  27. //
  28. // * The name of the copyright holders may not be used to endorse or promote products
  29. // derived from this software without specific prior written permission.
  30. //
  31. // This software is provided by the copyright holders and contributors "as is" and
  32. // any express or implied warranties, including, but not limited to, the implied
  33. // warranties of merchantability and fitness for a particular purpose are disclaimed.
  34. // In no event shall the Intel Corporation or contributors be liable for any direct,
  35. // indirect, incidental, special, exemplary, or consequential damages
  36. // (including, but not limited to, procurement of substitute goods or services;
  37. // loss of use, data, or profits; or business interruption) however caused
  38. // and on any theory of liability, whether in contract, strict liability,
  39. // or tort (including negligence or otherwise) arising in any way out of
  40. // the use of this software, even if advised of the possibility of such damage.
  41. //
  42. //M*/
  43. #include "precomp.hpp"
  44. #include <algorithm>
  45. #include <iterator>
  46. #include <limits>
  47. namespace cv
  48. {
  49. int RANSACUpdateNumIters( double p, double ep, int modelPoints, int maxIters )
  50. {
  51. if( modelPoints <= 0 )
  52. CV_Error( Error::StsOutOfRange, "the number of model points should be positive" );
  53. p = MAX(p, 0.);
  54. p = MIN(p, 1.);
  55. ep = MAX(ep, 0.);
  56. ep = MIN(ep, 1.);
  57. // avoid inf's & nan's
  58. double num = MAX(1. - p, DBL_MIN);
  59. double denom = 1. - std::pow(1. - ep, modelPoints);
  60. if( denom < DBL_MIN )
  61. return 0;
  62. num = std::log(num);
  63. denom = std::log(denom);
  64. return denom >= 0 || -num >= maxIters*(-denom) ? maxIters : cvRound(num/denom);
  65. }
  66. class RANSACPointSetRegistrator : public PointSetRegistrator
  67. {
  68. public:
  69. RANSACPointSetRegistrator(const Ptr<PointSetRegistrator::Callback>& _cb=Ptr<PointSetRegistrator::Callback>(),
  70. int _modelPoints=0, double _threshold=0, double _confidence=0.99, int _maxIters=1000)
  71. : cb(_cb), modelPoints(_modelPoints), threshold(_threshold), confidence(_confidence), maxIters(_maxIters)
  72. {
  73. checkPartialSubsets = true;
  74. }
  75. int findInliers( const Mat& m1, const Mat& m2, const Mat& model, Mat& err, Mat& mask, double thresh ) const
  76. {
  77. cb->computeError( m1, m2, model, err );
  78. mask.create(err.size(), CV_8U);
  79. CV_Assert( err.isContinuous() && err.type() == CV_32F && mask.isContinuous() && mask.type() == CV_8U);
  80. const float* errptr = err.ptr<float>();
  81. uchar* maskptr = mask.ptr<uchar>();
  82. float t = (float)(thresh*thresh);
  83. int i, n = (int)err.total(), nz = 0;
  84. for( i = 0; i < n; i++ )
  85. {
  86. int f = errptr[i] <= t;
  87. maskptr[i] = (uchar)f;
  88. nz += f;
  89. }
  90. return nz;
  91. }
  92. bool getSubset( const Mat& m1, const Mat& m2,
  93. Mat& ms1, Mat& ms2, RNG& rng,
  94. int maxAttempts=1000 ) const
  95. {
  96. cv::AutoBuffer<int> _idx(modelPoints);
  97. int* idx = _idx;
  98. int i = 0, j, k, iters = 0;
  99. int esz1 = (int)m1.elemSize(), esz2 = (int)m2.elemSize();
  100. int d1 = m1.channels() > 1 ? m1.channels() : m1.cols;
  101. int d2 = m2.channels() > 1 ? m2.channels() : m2.cols;
  102. int count = m1.checkVector(d1), count2 = m2.checkVector(d2);
  103. const int *m1ptr = (const int*)m1.data, *m2ptr = (const int*)m2.data;
  104. ms1.create(modelPoints, 1, CV_MAKETYPE(m1.depth(), d1));
  105. ms2.create(modelPoints, 1, CV_MAKETYPE(m2.depth(), d2));
  106. int *ms1ptr = (int*)ms1.data, *ms2ptr = (int*)ms2.data;
  107. CV_Assert( count >= modelPoints && count == count2 );
  108. CV_Assert( (esz1 % sizeof(int)) == 0 && (esz2 % sizeof(int)) == 0 );
  109. esz1 /= sizeof(int);
  110. esz2 /= sizeof(int);
  111. for(; iters < maxAttempts; iters++)
  112. {
  113. for( i = 0; i < modelPoints && iters < maxAttempts; )
  114. {
  115. int idx_i = 0;
  116. for(;;)
  117. {
  118. idx_i = idx[i] = rng.uniform(0, count);
  119. for( j = 0; j < i; j++ )
  120. if( idx_i == idx[j] )
  121. break;
  122. if( j == i )
  123. break;
  124. }
  125. for( k = 0; k < esz1; k++ )
  126. ms1ptr[i*esz1 + k] = m1ptr[idx_i*esz1 + k];
  127. for( k = 0; k < esz2; k++ )
  128. ms2ptr[i*esz2 + k] = m2ptr[idx_i*esz2 + k];
  129. if( checkPartialSubsets && !cb->checkSubset( ms1, ms2, i+1 ))
  130. {
  131. iters++;
  132. continue;
  133. }
  134. i++;
  135. }
  136. if( !checkPartialSubsets && i == modelPoints && !cb->checkSubset(ms1, ms2, i))
  137. continue;
  138. break;
  139. }
  140. return i == modelPoints && iters < maxAttempts;
  141. }
  142. bool run(InputArray _m1, InputArray _m2, OutputArray _model, OutputArray _mask) const
  143. {
  144. bool result = false;
  145. Mat m1 = _m1.getMat(), m2 = _m2.getMat();
  146. Mat err, mask, model, bestModel, ms1, ms2;
  147. int iter, niters = MAX(maxIters, 1);
  148. int d1 = m1.channels() > 1 ? m1.channels() : m1.cols;
  149. int d2 = m2.channels() > 1 ? m2.channels() : m2.cols;
  150. int count = m1.checkVector(d1), count2 = m2.checkVector(d2), maxGoodCount = 0;
  151. RNG rng((uint64)-1);
  152. CV_Assert( cb );
  153. CV_Assert( confidence > 0 && confidence < 1 );
  154. CV_Assert( count >= 0 && count2 == count );
  155. if( count < modelPoints )
  156. return false;
  157. Mat bestMask0, bestMask;
  158. if( _mask.needed() )
  159. {
  160. _mask.create(count, 1, CV_8U, -1, true);
  161. bestMask0 = bestMask = _mask.getMat();
  162. CV_Assert( (bestMask.cols == 1 || bestMask.rows == 1) && (int)bestMask.total() == count );
  163. }
  164. else
  165. {
  166. bestMask.create(count, 1, CV_8U);
  167. bestMask0 = bestMask;
  168. }
  169. if( count == modelPoints )
  170. {
  171. if( cb->runKernel(m1, m2, bestModel) <= 0 )
  172. return false;
  173. bestModel.copyTo(_model);
  174. bestMask.setTo(Scalar::all(1));
  175. return true;
  176. }
  177. for( iter = 0; iter < niters; iter++ )
  178. {
  179. int i, goodCount, nmodels;
  180. if( count > modelPoints )
  181. {
  182. bool found = getSubset( m1, m2, ms1, ms2, rng );
  183. if( !found )
  184. {
  185. if( iter == 0 )
  186. return false;
  187. break;
  188. }
  189. }
  190. nmodels = cb->runKernel( ms1, ms2, model );
  191. if( nmodels <= 0 )
  192. continue;
  193. CV_Assert( model.rows % nmodels == 0 );
  194. Size modelSize(model.cols, model.rows/nmodels);
  195. for( i = 0; i < nmodels; i++ )
  196. {
  197. Mat model_i = model.rowRange( i*modelSize.height, (i+1)*modelSize.height );
  198. goodCount = findInliers( m1, m2, model_i, err, mask, threshold );
  199. if( goodCount > MAX(maxGoodCount, modelPoints-1) )
  200. {
  201. std::swap(mask, bestMask);
  202. model_i.copyTo(bestModel);
  203. maxGoodCount = goodCount;
  204. niters = RANSACUpdateNumIters( confidence, (double)(count - goodCount)/count, modelPoints, niters );
  205. }
  206. }
  207. }
  208. if( maxGoodCount > 0 )
  209. {
  210. if( bestMask.data != bestMask0.data )
  211. {
  212. if( bestMask.size() == bestMask0.size() )
  213. bestMask.copyTo(bestMask0);
  214. else
  215. transpose(bestMask, bestMask0);
  216. }
  217. bestModel.copyTo(_model);
  218. result = true;
  219. }
  220. else
  221. _model.release();
  222. return result;
  223. }
  224. void setCallback(const Ptr<PointSetRegistrator::Callback>& _cb) { cb = _cb; }
  225. AlgorithmInfo* info() const;
  226. Ptr<PointSetRegistrator::Callback> cb;
  227. int modelPoints;
  228. int maxBasicSolutions;
  229. bool checkPartialSubsets;
  230. double threshold;
  231. double confidence;
  232. int maxIters;
  233. };
  234. class LMeDSPointSetRegistrator : public RANSACPointSetRegistrator
  235. {
  236. public:
  237. LMeDSPointSetRegistrator(const Ptr<PointSetRegistrator::Callback>& _cb=Ptr<PointSetRegistrator::Callback>(),
  238. int _modelPoints=0, double _confidence=0.99, int _maxIters=1000)
  239. : RANSACPointSetRegistrator(_cb, _modelPoints, 0, _confidence, _maxIters) {}
  240. bool run(InputArray _m1, InputArray _m2, OutputArray _model, OutputArray _mask) const
  241. {
  242. const double outlierRatio = 0.45;
  243. bool result = false;
  244. Mat m1 = _m1.getMat(), m2 = _m2.getMat();
  245. Mat ms1, ms2, err, errf, model, bestModel, mask, mask0;
  246. int d1 = m1.channels() > 1 ? m1.channels() : m1.cols;
  247. int d2 = m2.channels() > 1 ? m2.channels() : m2.cols;
  248. int count = m1.checkVector(d1), count2 = m2.checkVector(d2);
  249. double minMedian = DBL_MAX, sigma;
  250. RNG rng((uint64)-1);
  251. CV_Assert( cb );
  252. CV_Assert( confidence > 0 && confidence < 1 );
  253. CV_Assert( count >= 0 && count2 == count );
  254. if( count < modelPoints )
  255. return false;
  256. if( _mask.needed() )
  257. {
  258. _mask.create(count, 1, CV_8U, -1, true);
  259. mask0 = mask = _mask.getMat();
  260. CV_Assert( (mask.cols == 1 || mask.rows == 1) && (int)mask.total() == count );
  261. }
  262. if( count == modelPoints )
  263. {
  264. if( cb->runKernel(m1, m2, bestModel) <= 0 )
  265. return false;
  266. bestModel.copyTo(_model);
  267. mask.setTo(Scalar::all(1));
  268. return true;
  269. }
  270. int iter, niters = RANSACUpdateNumIters(confidence, outlierRatio, modelPoints, maxIters);
  271. niters = MAX(niters, 3);
  272. for( iter = 0; iter < niters; iter++ )
  273. {
  274. int i, nmodels;
  275. if( count > modelPoints )
  276. {
  277. bool found = getSubset( m1, m2, ms1, ms2, rng );
  278. if( !found )
  279. {
  280. if( iter == 0 )
  281. return false;
  282. break;
  283. }
  284. }
  285. nmodels = cb->runKernel( ms1, ms2, model );
  286. if( nmodels <= 0 )
  287. continue;
  288. CV_Assert( model.rows % nmodels == 0 );
  289. Size modelSize(model.cols, model.rows/nmodels);
  290. for( i = 0; i < nmodels; i++ )
  291. {
  292. Mat model_i = model.rowRange( i*modelSize.height, (i+1)*modelSize.height );
  293. cb->computeError( m1, m2, model_i, err );
  294. if( err.depth() != CV_32F )
  295. err.convertTo(errf, CV_32F);
  296. else
  297. errf = err;
  298. CV_Assert( errf.isContinuous() && errf.type() == CV_32F && (int)errf.total() == count );
  299. std::sort((int*)errf.data, (int*)errf.data + count);
  300. double median = count % 2 != 0 ?
  301. errf.at<float>(count/2) : (errf.at<float>(count/2-1) + errf.at<float>(count/2))*0.5;
  302. if( median < minMedian )
  303. {
  304. minMedian = median;
  305. model_i.copyTo(bestModel);
  306. }
  307. }
  308. }
  309. if( minMedian < DBL_MAX )
  310. {
  311. sigma = 2.5*1.4826*(1 + 5./(count - modelPoints))*std::sqrt(minMedian);
  312. sigma = MAX( sigma, 0.001 );
  313. count = findInliers( m1, m2, bestModel, err, mask, sigma );
  314. if( _mask.needed() && mask0.data != mask.data )
  315. {
  316. if( mask0.size() == mask.size() )
  317. mask.copyTo(mask0);
  318. else
  319. transpose(mask, mask0);
  320. }
  321. bestModel.copyTo(_model);
  322. result = count >= modelPoints;
  323. }
  324. else
  325. _model.release();
  326. return result;
  327. }
  328. AlgorithmInfo* info() const;
  329. };
  330. CV_INIT_ALGORITHM(RANSACPointSetRegistrator, "PointSetRegistrator.RANSAC",
  331. obj.info()->addParam(obj, "threshold", obj.threshold);
  332. obj.info()->addParam(obj, "confidence", obj.confidence);
  333. obj.info()->addParam(obj, "maxIters", obj.maxIters))
  334. CV_INIT_ALGORITHM(LMeDSPointSetRegistrator, "PointSetRegistrator.LMeDS",
  335. obj.info()->addParam(obj, "confidence", obj.confidence);
  336. obj.info()->addParam(obj, "maxIters", obj.maxIters))
  337. Ptr<PointSetRegistrator> createRANSACPointSetRegistrator(const Ptr<PointSetRegistrator::Callback>& _cb,
  338. int _modelPoints, double _threshold,
  339. double _confidence, int _maxIters)
  340. {
  341. CV_Assert( !RANSACPointSetRegistrator_info_auto.name().empty() );
  342. return Ptr<PointSetRegistrator>(
  343. new RANSACPointSetRegistrator(_cb, _modelPoints, _threshold, _confidence, _maxIters));
  344. }
  345. Ptr<PointSetRegistrator> createLMeDSPointSetRegistrator(const Ptr<PointSetRegistrator::Callback>& _cb,
  346. int _modelPoints, double _confidence, int _maxIters)
  347. {
  348. CV_Assert( !LMeDSPointSetRegistrator_info_auto.name().empty() );
  349. return Ptr<PointSetRegistrator>(
  350. new LMeDSPointSetRegistrator(_cb, _modelPoints, _confidence, _maxIters));
  351. }
  352. class Affine3DEstimatorCallback : public PointSetRegistrator::Callback
  353. {
  354. public:
  355. int runKernel( InputArray _m1, InputArray _m2, OutputArray _model ) const
  356. {
  357. Mat m1 = _m1.getMat(), m2 = _m2.getMat();
  358. const Point3f* from = m1.ptr<Point3f>();
  359. const Point3f* to = m2.ptr<Point3f>();
  360. const int N = 12;
  361. double buf[N*N + N + N];
  362. Mat A(N, N, CV_64F, &buf[0]);
  363. Mat B(N, 1, CV_64F, &buf[0] + N*N);
  364. Mat X(N, 1, CV_64F, &buf[0] + N*N + N);
  365. double* Adata = A.ptr<double>();
  366. double* Bdata = B.ptr<double>();
  367. A = Scalar::all(0);
  368. for( int i = 0; i < (N/3); i++ )
  369. {
  370. Bdata[i*3] = to[i].x;
  371. Bdata[i*3+1] = to[i].y;
  372. Bdata[i*3+2] = to[i].z;
  373. double *aptr = Adata + i*3*N;
  374. for(int k = 0; k < 3; ++k)
  375. {
  376. aptr[0] = from[i].x;
  377. aptr[1] = from[i].y;
  378. aptr[2] = from[i].z;
  379. aptr[3] = 1.0;
  380. aptr += 16;
  381. }
  382. }
  383. solve(A, B, X, DECOMP_SVD);
  384. X.reshape(1, 3).copyTo(_model);
  385. return 1;
  386. }
  387. void computeError( InputArray _m1, InputArray _m2, InputArray _model, OutputArray _err ) const
  388. {
  389. Mat m1 = _m1.getMat(), m2 = _m2.getMat(), model = _model.getMat();
  390. const Point3f* from = m1.ptr<Point3f>();
  391. const Point3f* to = m2.ptr<Point3f>();
  392. const double* F = model.ptr<double>();
  393. int count = m1.checkVector(3);
  394. CV_Assert( count > 0 );
  395. _err.create(count, 1, CV_32F);
  396. Mat err = _err.getMat();
  397. float* errptr = err.ptr<float>();
  398. for(int i = 0; i < count; i++ )
  399. {
  400. const Point3f& f = from[i];
  401. const Point3f& t = to[i];
  402. double a = F[0]*f.x + F[1]*f.y + F[ 2]*f.z + F[ 3] - t.x;
  403. double b = F[4]*f.x + F[5]*f.y + F[ 6]*f.z + F[ 7] - t.y;
  404. double c = F[8]*f.x + F[9]*f.y + F[10]*f.z + F[11] - t.z;
  405. errptr[i] = (float)std::sqrt(a*a + b*b + c*c);
  406. }
  407. }
  408. bool checkSubset( InputArray _ms1, InputArray _ms2, int count ) const
  409. {
  410. const float threshold = 0.996f;
  411. Mat ms1 = _ms1.getMat(), ms2 = _ms2.getMat();
  412. for( int inp = 1; inp <= 2; inp++ )
  413. {
  414. int j, k, i = count - 1;
  415. const Mat* msi = inp == 1 ? &ms1 : &ms2;
  416. const Point3f* ptr = msi->ptr<Point3f>();
  417. CV_Assert( count <= msi->rows );
  418. // check that the i-th selected point does not belong
  419. // to a line connecting some previously selected points
  420. for(j = 0; j < i; ++j)
  421. {
  422. Point3f d1 = ptr[j] - ptr[i];
  423. float n1 = d1.x*d1.x + d1.y*d1.y;
  424. for(k = 0; k < j; ++k)
  425. {
  426. Point3f d2 = ptr[k] - ptr[i];
  427. float denom = (d2.x*d2.x + d2.y*d2.y)*n1;
  428. float num = d1.x*d2.x + d1.y*d2.y;
  429. if( num*num > threshold*threshold*denom )
  430. return false;
  431. }
  432. }
  433. }
  434. return true;
  435. }
  436. };
  437. }
  438. int cv::estimateAffine3D(InputArray _from, InputArray _to,
  439. OutputArray _out, OutputArray _inliers,
  440. double param1, double param2)
  441. {
  442. Mat from = _from.getMat(), to = _to.getMat();
  443. int count = from.checkVector(3);
  444. CV_Assert( count >= 0 && to.checkVector(3) == count );
  445. Mat dFrom, dTo;
  446. from.convertTo(dFrom, CV_32F);
  447. to.convertTo(dTo, CV_32F);
  448. dFrom = dFrom.reshape(3, count);
  449. dTo = dTo.reshape(3, count);
  450. const double epsilon = DBL_EPSILON;
  451. param1 = param1 <= 0 ? 3 : param1;
  452. param2 = (param2 < epsilon) ? 0.99 : (param2 > 1 - epsilon) ? 0.99 : param2;
  453. return createRANSACPointSetRegistrator(makePtr<Affine3DEstimatorCallback>(), 4, param1, param2)->run(dFrom, dTo, _out, _inliers);
  454. }