el_i, i*modelSize.height, (i+1)*modelSize.height );
? ?goodCount = findInliers( m1, m2, &model_i, err, tmask, reprojThreshold );
? ?if( goodCount > MAX(maxGoodCount, modelPoints-1) )
? ?{
? ? std::swap(tmask, mask);
? ? cvCopy( &model_i, model );
? ? maxGoodCount = goodCount;
? ? niters = cvRANSACUpdateNumIters( confidence,
? ? ?(double)(count - goodCount)/count, modelPoints, niters );
? ?}
? }
?}
?if( maxGoodCount > 0 )
?{
? if( mask != mask0 )
? ?cvCopy( mask, mask0 );
? result = true;
?}
?return result;
}
Mat getAffineTransform64f( const Point2d src[], const Point2d dst[] )
{
?Mat M(2, 3, CV_64F), X(6, 1, CV_64F, M.data);
?double a[6*6], b[6];
?Mat A(6, 6, CV_64F, a), B(6, 1, CV_64F, b);
?for( int i = 0; i < 3; i++ )
?{
? int j = i*12;
? int k = i*12+6;
? a[j] = a[k+3] = src[i].x;
? a[j+1] = a[k+4] = src[i].y;
? a[j+2] = a[k+5] = 1;
? a[j+3] = a[j+4] = a[j+5] = 0;
? a[k] = a[k+1] = a[k+2] = 0;
? b[i*2] = dst[i].x;
? b[i*2+1] = dst[i].y;
?}
?solve( A, B, X );
?return M;
}
int Affine2DEstimator::runKernel( const CvMat* m1, const CvMat* m2, CvMat* model )
{?
?const Point2d* from = reinterpret_cast(m1->data.ptr);
?const Point2d* to? = reinterpret_cast(m2->data.ptr);
?Mat M0 = cv::cvarrToMat(model);
?Mat M=getAffineTransform64f(from,to);
?CV_Assert( M.size() == M0.size() );
?M.convertTo(M0, M0.type());
?return model!=NULL?1:0;
}
int estimateAffine2D(InputArray _from, InputArray _to,
?OutputArray _out, OutputArray _inliers,
?double param1, double param2)
{
?Mat from = _from.getMat(), to = _to.getMat();
?int count = from.checkVector(2, CV_32F);
?CV_Assert( count >= 0 && to.checkVector(2, CV_32F) == count );
?_out.create(2, 3, CV_64F);
?Mat out = _out.getMat();
?_inliers.create(count, 1, CV_8U, -1, true);
?Mat inliers = _inliers.getMat();
?inliers = Scalar::all(1);
?Mat dFrom, dTo;
?from.convertTo(dFrom, CV_64F);
?to.convertTo(dTo, CV_64F);
?CvMat F2x3 = out;
?CvMat mask? = inliers;
?CvMat m1 = dFrom;
?CvMat m2 = dTo;
?const double epsilon = numeric_limits::epsilon();? ? ? ?
?param1 = param1 <= 0 ? 3 : param1;
?param2 = (param2 < epsilon) ? 0.99 : (param2 > 1 - epsilon) ? 0.99 : param2;
?return Affine2DEstimator().runRANSAC(&m1, &m2, &F2x3, &mask, param1, param2 );? ?
}
bool Affine2DEstimator::getSubset( const CvMat* m1, const CvMat* m2,
?CvMat* ms1, CvMat* ms2, int maxAttempts )
{
?cv::AutoBuffer _idx(modelPoints);
?int* idx = _idx;
?int i = 0, j, k, idx_i, iters = 0;
?int type = CV_MAT_TYPE(m1->type), elemSize = CV_ELEM_SIZE(type);
?const int *m1ptr = m1->data.i, *m2ptr = m2->data.i;
?int *ms1ptr = ms1->data.i, *ms2ptr = ms2->data.i;
?int count = m1->cols*m1->rows;
?assert( CV_IS_MAT_CONT(m1->type & m2->type) && (elemSize % sizeof(int) == 0) );
?elemSize /= sizeof(int);
?for(; iters < maxAttempts; iters++)
?{
? for( i = 0; i < modelPoints && iters < maxAttempts; )
? {
? ?idx[i] = idx_i = cvRandInt(&rng) % count;
? ?for( j = 0; j < i; j++ )
? ? if( idx_i == idx[j] )
? ? ?break;
? ?if( j < i )
? ? continue;
? ?for( k = 0; k < elemSize; k++ )
? ?{
? ? ms1ptr[i*elemSize + k] = m1ptr[idx_i*elemSize + k];
? ? ms2ptr[i*elemSize + k] = m2ptr[idx_i*elemSize + k];
? ?}
? ?if( checkPartialSubsets && (!checkSubset( ms1, i+1 ) || !checkSubset( ms2, i+1 )))
? ?{
? ? iters++;
? ? continue;
? ?}
? ?i++;
? }
? if( !checkPartialSubsets && i == modelPoints &&
? ?(!checkSubset( ms1, i ) || !checkSubset( ms2, i )))
? ?continue;
? break;
?}
?return i == modelPoints && iters < maxAttempts;
}
bool Affine2DEstimator::checkSubset( const CvMat* ms1, int count )
{
?int j, k, i, i0, i1;
?CvPoint2D64f* ptr = (CvPoint2D64f*)ms1->data.ptr;
?assert( CV_MAT_TYPE(ms1->type) == CV_64FC2 );
?if( checkPartialSubsets )
? i0 = i1 = count - 1;
?else
? i0 = 0, i1 = count - 1;
?for( i = i0; i <= i1; i++ )
?{
? // check that the i-th selected point