为了账号安全,请及时绑定邮箱和手机立即绑定

cv2.estimateRigidTransform 最小点数?

cv2.estimateRigidTransform 最小点数?

红颜莎娜 2021-09-11 19:38:42
最少需要多少分cv2.estimateRigidTransform?据我了解,fullAffine=False它有 4 个自由度,所以 2 点就足够了。然而:使用 2 numpy 数组作为输入:src_pts_subset.shape (2, 2)tgt_pts_subset.shape (2, 2)type(src_pts_subset) <class 'numpy.ndarray'>type(tgt_pts_subset) <class 'numpy.ndarray'>src_pts_subset.dtype int64tgt_pts_subset.dtype int64到m = cv2.estimateRigidTransform(src_pts, tgt_pts, fullAffine=False)给我None。
查看完整描述

1 回答

?
湖上湖

TA贡献2003条经验 获得超2个赞

理论上,非完全仿射设置只需要 2 对点,正如 ngia ho所解释的那样。但是,在检查 openCV 中的源代码时,该函数至少需要 3 个对点才能返回由 RANSAC 计算的值。


我在下面包含了相应的功能供您参考。它位于 openCV 源文件中的 lkpyramid.cpp 文件中。


cv::Mat cv::estimateRigidTransform( InputArray src1, InputArray src2, bool fullAffine )

{

    return estimateRigidTransform(src1, src2, fullAffine, 500, 0.5, 3);

}


cv::Mat cv::estimateRigidTransform( InputArray src1, InputArray src2, bool fullAffine, int ransacMaxIters, double ransacGoodRatio,

                                    const int ransacSize0)

{

    CV_INSTRUMENT_REGION()


    Mat M(2, 3, CV_64F), A = src1.getMat(), B = src2.getMat();


    const int COUNT = 15;

    const int WIDTH = 160, HEIGHT = 120;


    std::vector<Point2f> pA, pB;

    std::vector<int> good_idx;

    std::vector<uchar> status;


    double scale = 1.;

    int i, j, k, k1;


    RNG rng((uint64)-1);

    int good_count = 0;


    if( ransacSize0 < 3 )

        CV_Error( Error::StsBadArg, "ransacSize0 should have value bigger than 2.");


    if( ransacGoodRatio > 1 || ransacGoodRatio < 0)

        CV_Error( Error::StsBadArg, "ransacGoodRatio should have value between 0 and 1");


    if( A.size() != B.size() )

        CV_Error( Error::StsUnmatchedSizes, "Both input images must have the same size" );


    if( A.type() != B.type() )

        CV_Error( Error::StsUnmatchedFormats, "Both input images must have the same data type" );


    int count = A.checkVector(2);


    if( count > 0 )

    {

        A.reshape(2, count).convertTo(pA, CV_32F);

        B.reshape(2, count).convertTo(pB, CV_32F);

    }

    else if( A.depth() == CV_8U )

    {

        int cn = A.channels();

        CV_Assert( cn == 1 || cn == 3 || cn == 4 );

        Size sz0 = A.size();

        Size sz1(WIDTH, HEIGHT);


        scale = std::max(1., std::max( (double)sz1.width/sz0.width, (double)sz1.height/sz0.height ));


        sz1.width = cvRound( sz0.width * scale );

        sz1.height = cvRound( sz0.height * scale );


        bool equalSizes = sz1.width == sz0.width && sz1.height == sz0.height;


        if( !equalSizes || cn != 1 )

        {

            Mat sA, sB;


            if( cn != 1 )

            {

                Mat gray;

                cvtColor(A, gray, COLOR_BGR2GRAY);

                resize(gray, sA, sz1, 0., 0., INTER_AREA);

                cvtColor(B, gray, COLOR_BGR2GRAY);

                resize(gray, sB, sz1, 0., 0., INTER_AREA);

            }

            else

            {

                resize(A, sA, sz1, 0., 0., INTER_AREA);

                resize(B, sB, sz1, 0., 0., INTER_AREA);

            }


            A = sA;

            B = sB;

        }


        int count_y = COUNT;

        int count_x = cvRound((double)COUNT*sz1.width/sz1.height);

        count = count_x * count_y;


        pA.resize(count);

        pB.resize(count);

        status.resize(count);


        for( i = 0, k = 0; i < count_y; i++ )

            for( j = 0; j < count_x; j++, k++ )

            {

                pA[k].x = (j+0.5f)*sz1.width/count_x;

                pA[k].y = (i+0.5f)*sz1.height/count_y;

            }


        // find the corresponding points in B

        calcOpticalFlowPyrLK(A, B, pA, pB, status, noArray(), Size(21, 21), 3,

                             TermCriteria(TermCriteria::MAX_ITER,40,0.1));


        // repack the remained points

        for( i = 0, k = 0; i < count; i++ )

            if( status[i] )

            {

                if( i > k )

                {

                    pA[k] = pA[i];

                    pB[k] = pB[i];

                }

                k++;

            }

        count = k;

        pA.resize(count);

        pB.resize(count);

    }

    else

        CV_Error( Error::StsUnsupportedFormat, "Both input images must have either 8uC1 or 8uC3 type" );


    good_idx.resize(count);


    if( count < ransacSize0 )

        return Mat();


    Rect brect = boundingRect(pB);


    std::vector<Point2f> a(ransacSize0);

    std::vector<Point2f> b(ransacSize0);


    // RANSAC stuff:

    // 1. find the consensus

    for( k = 0; k < ransacMaxIters; k++ )

    {

        std::vector<int> idx(ransacSize0);

        // choose random 3 non-complanar points from A & B

        for( i = 0; i < ransacSize0; i++ )

        {

            for( k1 = 0; k1 < ransacMaxIters; k1++ )

            {

                idx[i] = rng.uniform(0, count);


                for( j = 0; j < i; j++ )

                {

                    if( idx[j] == idx[i] )

                        break;

                    // check that the points are not very close one each other

                    if( fabs(pA[idx[i]].x - pA[idx[j]].x) +

                        fabs(pA[idx[i]].y - pA[idx[j]].y) < FLT_EPSILON )

                        break;

                    if( fabs(pB[idx[i]].x - pB[idx[j]].x) +

                        fabs(pB[idx[i]].y - pB[idx[j]].y) < FLT_EPSILON )

                        break;

                }


                if( j < i )

                    continue;


                if( i+1 == ransacSize0 )

                {

                    // additional check for non-complanar vectors

                    a[0] = pA[idx[0]];

                    a[1] = pA[idx[1]];

                    a[2] = pA[idx[2]];


                    b[0] = pB[idx[0]];

                    b[1] = pB[idx[1]];

                    b[2] = pB[idx[2]];


                    double dax1 = a[1].x - a[0].x, day1 = a[1].y - a[0].y;

                    double dax2 = a[2].x - a[0].x, day2 = a[2].y - a[0].y;

                    double dbx1 = b[1].x - b[0].x, dby1 = b[1].y - b[0].y;

                    double dbx2 = b[2].x - b[0].x, dby2 = b[2].y - b[0].y;

                    const double eps = 0.01;


                    if( fabs(dax1*day2 - day1*dax2) < eps*std::sqrt(dax1*dax1+day1*day1)*std::sqrt(dax2*dax2+day2*day2) ||

                        fabs(dbx1*dby2 - dby1*dbx2) < eps*std::sqrt(dbx1*dbx1+dby1*dby1)*std::sqrt(dbx2*dbx2+dby2*dby2) )

                        continue;

                }

                break;

            }


            if( k1 >= ransacMaxIters )

                break;

        }


        if( i < ransacSize0 )

            continue;


        // estimate the transformation using 3 points

        getRTMatrix( a, b, 3, M, fullAffine );


        const double* m = M.ptr<double>();

        for( i = 0, good_count = 0; i < count; i++ )

        {

            if( std::abs( m[0]*pA[i].x + m[1]*pA[i].y + m[2] - pB[i].x ) +

                std::abs( m[3]*pA[i].x + m[4]*pA[i].y + m[5] - pB[i].y ) < std::max(brect.width,brect.height)*0.05 )

                good_idx[good_count++] = i;

        }


        if( good_count >= count*ransacGoodRatio )

            break;

    }


    if( k >= ransacMaxIters )

        return Mat();


    if( good_count < count )

    {

        for( i = 0; i < good_count; i++ )

        {

            j = good_idx[i];

            pA[i] = pA[j];

            pB[i] = pB[j];

        }

    }


    getRTMatrix( pA, pB, good_count, M, fullAffine );

    M.at<double>(0, 2) /= scale;

    M.at<double>(1, 2) /= scale;


    return M;

}



查看完整回答
反对 回复 2021-09-11
  • 1 回答
  • 0 关注
  • 195 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信