Affine2DEstimator0.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. #include "StdAfx.h"
  2. #include "Affine2DEstimator0.h"
  3. int Affine2DEstimator0::findInliers(const CvMat* m1, const CvMat* m2,
  4. const CvMat* model, CvMat* _err,
  5. CvMat* _mask, double threshold)
  6. {
  7. int i, count = _err->rows*_err->cols, goodCount = 0;
  8. const float* err = _err->data.fl;
  9. uchar* mask = _mask->data.ptr;
  10. computeReprojError(m1, m2, model, _err);
  11. threshold *= threshold;
  12. for (i = 0; i < count; i++)
  13. goodCount += mask[i] = err[i] <= threshold;
  14. return goodCount;
  15. }
  16. void Affine2DEstimator0::computeReprojError(const CvMat* m1, const CvMat* m2, const CvMat* model, CvMat* error)
  17. {
  18. int count = m1->rows * m1->cols;
  19. const CvPoint2D64f* from = reinterpret_cast<const CvPoint2D64f*>(m1->data.ptr);
  20. const CvPoint2D64f* to = reinterpret_cast<const CvPoint2D64f*>(m2->data.ptr);
  21. const double* F = model->data.db;
  22. float* err = error->data.fl;
  23. for (int i = 0; i < count; i++)
  24. {
  25. const CvPoint2D64f& f = from[i];
  26. const CvPoint2D64f& t = to[i];
  27. double a = F[0] * f.x + F[1] * f.y + F[2] - t.x;
  28. double b = F[3] * f.x + F[4] * f.y + F[5] - t.y;
  29. err[i] = (float)sqrt(a*a + b*b);
  30. }
  31. }
  32. int Affine2DEstimator0::runRANSAC(const CvMat* m1, const CvMat* m2, CvMat* model,
  33. CvMat* mask0, double reprojThreshold,
  34. double confidence, int maxIters)
  35. {
  36. int result = 0;
  37. cv::Ptr<CvMat> mask = cvCloneMat(mask0);
  38. cv::Ptr<CvMat> models, err, tmask;
  39. cv::Ptr<CvMat> ms1, ms2;
  40. int iter, niters = maxIters;
  41. int count = m1->rows*m1->cols, maxGoodCount = 0;
  42. CV_Assert(CV_ARE_SIZES_EQ(m1, m2) && CV_ARE_SIZES_EQ(m1, mask));
  43. if (count < modelPoints)
  44. return false;
  45. models = cvCreateMat(modelSize.height*maxBasicSolutions, modelSize.width, CV_64FC1);
  46. err = cvCreateMat(1, count, CV_32FC1);
  47. tmask = cvCreateMat(1, count, CV_8UC1);
  48. if (count > modelPoints)
  49. {
  50. ms1 = cvCreateMat(1, modelPoints, m1->type);
  51. ms2 = cvCreateMat(1, modelPoints, m2->type);
  52. }
  53. else
  54. {
  55. niters = 1;
  56. ms1 = cvCloneMat(m1);
  57. ms2 = cvCloneMat(m2);
  58. }
  59. for (iter = 0; iter < niters; iter++)
  60. {
  61. int i, goodCount, nmodels;
  62. if (count > modelPoints)
  63. {
  64. bool found = getSubset(m1, m2, ms1, ms2, 300);
  65. if (!found)
  66. {
  67. if (iter == 0)
  68. return false;
  69. break;
  70. }
  71. }
  72. nmodels = runKernel(ms1, ms2, models);
  73. if (nmodels <= 0)
  74. continue;
  75. for (i = 0; i < nmodels; i++)
  76. {
  77. CvMat model_i;
  78. cvGetRows(models, &model_i, i*modelSize.height, (i + 1)*modelSize.height);
  79. goodCount = findInliers(m1, m2, &model_i, err, tmask, reprojThreshold);
  80. if (goodCount > MAX(maxGoodCount, modelPoints - 1))
  81. {
  82. std::swap(tmask, mask);
  83. cvCopy(&model_i, model);
  84. maxGoodCount = goodCount;
  85. niters = cvRANSACUpdateNumIters(confidence,
  86. (double)(count - goodCount) / count, modelPoints, niters);
  87. }
  88. }
  89. }
  90. if (maxGoodCount > 0)
  91. {
  92. if (mask != mask0)
  93. cvCopy(mask, mask0);
  94. result = maxGoodCount;
  95. }
  96. return result;
  97. }
  98. Mat getAffineTransform64f0(const Point2d src[], const Point2d dst[])
  99. {
  100. Mat M(2, 3, CV_64F), X(6, 1, CV_64F, M.data);
  101. double a[6 * 6], b[6];
  102. Mat A(6, 6, CV_64F, a), B(6, 1, CV_64F, b);
  103. for (int i = 0; i < 3; i++)
  104. {
  105. int j = i * 12;
  106. int k = i * 12 + 6;
  107. a[j] = a[k + 3] = src[i].x;
  108. a[j + 1] = a[k + 4] = src[i].y;
  109. a[j + 2] = a[k + 5] = 1;
  110. a[j + 3] = a[j + 4] = a[j + 5] = 0;
  111. a[k] = a[k + 1] = a[k + 2] = 0;
  112. b[i * 2] = dst[i].x;
  113. b[i * 2 + 1] = dst[i].y;
  114. }
  115. solve(A, B, X);
  116. return M;
  117. }
  118. int Affine2DEstimator0::runKernel(const CvMat* m1, const CvMat* m2, CvMat* model)
  119. {
  120. const Point2d* from = reinterpret_cast<const Point2d*>(m1->data.ptr);
  121. const Point2d* to = reinterpret_cast<const Point2d*>(m2->data.ptr);
  122. Mat M0 = cv::cvarrToMat(model);
  123. Mat M = getAffineTransform64f0(from, to);
  124. CV_Assert(M.size() == M0.size());
  125. M.convertTo(M0, M0.type());
  126. return model != NULL ? 1 : 0;
  127. }
  128. int estimateAffine2D0(InputArray _from, InputArray _to,
  129. OutputArray _out, OutputArray _inliers,
  130. double param1, double param2)
  131. {
  132. Mat from = _from.getMat(), to = _to.getMat();
  133. int count = from.checkVector(2, CV_32F);
  134. CV_Assert(count >= 0 && to.checkVector(2, CV_32F) == count);
  135. _out.create(2, 3, CV_64F);
  136. Mat out = _out.getMat();
  137. //_inliers.create(count, 1, CV_8U, -1, true);
  138. _inliers.create(1, count, CV_8U, -1, true);
  139. Mat inliers = _inliers.getMat();
  140. inliers = Scalar::all(1);
  141. Mat dFrom, dTo;
  142. from.convertTo(dFrom, CV_64F);
  143. to.convertTo(dTo, CV_64F);
  144. CvMat F2x3 = out;
  145. CvMat mask = inliers;
  146. CvMat m1 = dFrom;
  147. CvMat m2 = dTo;
  148. const double epsilon = std::numeric_limits<double>::epsilon();
  149. param1 = param1 <= 0 ? 3 : param1;
  150. param2 = (param2 < epsilon) ? 0.99 : (param2 > 1 - epsilon) ? 0.99 : param2;
  151. return Affine2DEstimator0().runRANSAC(&m1, &m2, &F2x3, &mask, param1, param2);
  152. }
  153. bool Affine2DEstimator0::getSubset(const CvMat* m1, const CvMat* m2,
  154. CvMat* ms1, CvMat* ms2, int maxAttempts)
  155. {
  156. cv::AutoBuffer<int> _idx(modelPoints);
  157. int* idx = _idx;
  158. int i = 0, j, k, idx_i, iters = 0;
  159. int type = CV_MAT_TYPE(m1->type), elemSize = CV_ELEM_SIZE(type);
  160. const int *m1ptr = m1->data.i, *m2ptr = m2->data.i;
  161. int *ms1ptr = ms1->data.i, *ms2ptr = ms2->data.i;
  162. int count = m1->cols*m1->rows;
  163. assert(CV_IS_MAT_CONT(m1->type & m2->type) && (elemSize % sizeof(int) == 0));
  164. elemSize /= sizeof(int);
  165. for (; iters < maxAttempts; iters++)
  166. {
  167. for (i = 0; i < modelPoints && iters < maxAttempts;)
  168. {
  169. idx[i] = idx_i = cvRandInt(&rng) % count;
  170. for (j = 0; j < i; j++)
  171. if (idx_i == idx[j])
  172. break;
  173. if (j < i)
  174. continue;
  175. for (k = 0; k < elemSize; k++)
  176. {
  177. ms1ptr[i*elemSize + k] = m1ptr[idx_i*elemSize + k];
  178. ms2ptr[i*elemSize + k] = m2ptr[idx_i*elemSize + k];
  179. }
  180. if (checkPartialSubsets && (!checkSubset(ms1, i + 1) || !checkSubset(ms2, i + 1)))
  181. {
  182. iters++;
  183. continue;
  184. }
  185. i++;
  186. }
  187. if (!checkPartialSubsets && i == modelPoints &&
  188. (!checkSubset(ms1, i) || !checkSubset(ms2, i)))
  189. continue;
  190. break;
  191. }
  192. return i == modelPoints && iters < maxAttempts;
  193. }
  194. bool Affine2DEstimator0::checkSubset(const CvMat* ms1, int count)
  195. {
  196. int j, k, i, i0, i1;
  197. CvPoint2D64f* ptr = (CvPoint2D64f*)ms1->data.ptr;
  198. assert(CV_MAT_TYPE(ms1->type) == CV_64FC2);
  199. if (checkPartialSubsets)
  200. i0 = i1 = count - 1;
  201. else
  202. i0 = 0, i1 = count - 1;
  203. for (i = i0; i <= i1; i++)
  204. {
  205. // check that the i-th selected point does not belong
  206. // to a line connecting some previously selected points
  207. for (j = 0; j < i; j++)
  208. {
  209. double dx1 = ptr[j].x - ptr[i].x;
  210. double dy1 = ptr[j].y - ptr[i].y;
  211. for (k = 0; k < j; k++)
  212. {
  213. double dx2 = ptr[k].x - ptr[i].x;
  214. double dy2 = ptr[k].y - ptr[i].y;
  215. if (fabs(dx2*dy1 - dy2*dx1) <= FLT_EPSILON*(fabs(dx1) + fabs(dy1) + fabs(dx2) + fabs(dy2)))
  216. break;
  217. }
  218. if (k < j)
  219. break;
  220. }
  221. if (j < i)
  222. break;
  223. }
  224. return i >= i1;
  225. }
  226. Affine2DEstimator0::Affine2DEstimator0() : modelPoints(3), modelSize(cvSize(3, 2)), maxBasicSolutions(1)
  227. {
  228. checkPartialSubsets = true;
  229. rng = cvRNG(-1);
  230. }