cv2.estimateRigidTransform 最小点数?

最少需要多少分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 int64

tgt_pts_subset.dtype int64


m = cv2.estimateRigidTransform(src_pts, tgt_pts, fullAffine=False)

给我None。


红颜莎娜
浏览 222回答 1
1回答

湖上湖

理论上,非完全仿射设置只需要 2 对点,正如 ngia ho所解释的那样。但是,在检查 openCV 中的源代码时,该函数至少需要 3 个对点才能返回由 RANSAC 计算的值。我在下面包含了相应的功能供您参考。它位于 openCV 源文件中的 lkpyramid.cpp 文件中。cv::Mat cv::estimateRigidTransform( InputArray src1, InputArray src2, bool fullAffine ){&nbsp; &nbsp; return estimateRigidTransform(src1, src2, fullAffine, 500, 0.5, 3);}cv::Mat cv::estimateRigidTransform( InputArray src1, InputArray src2, bool fullAffine, int ransacMaxIters, double ransacGoodRatio,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const int ransacSize0){&nbsp; &nbsp; CV_INSTRUMENT_REGION()&nbsp; &nbsp; Mat M(2, 3, CV_64F), A = src1.getMat(), B = src2.getMat();&nbsp; &nbsp; const int COUNT = 15;&nbsp; &nbsp; const int WIDTH = 160, HEIGHT = 120;&nbsp; &nbsp; std::vector<Point2f> pA, pB;&nbsp; &nbsp; std::vector<int> good_idx;&nbsp; &nbsp; std::vector<uchar> status;&nbsp; &nbsp; double scale = 1.;&nbsp; &nbsp; int i, j, k, k1;&nbsp; &nbsp; RNG rng((uint64)-1);&nbsp; &nbsp; int good_count = 0;&nbsp; &nbsp; if( ransacSize0 < 3 )&nbsp; &nbsp; &nbsp; &nbsp; CV_Error( Error::StsBadArg, "ransacSize0 should have value bigger than 2.");&nbsp; &nbsp; if( ransacGoodRatio > 1 || ransacGoodRatio < 0)&nbsp; &nbsp; &nbsp; &nbsp; CV_Error( Error::StsBadArg, "ransacGoodRatio should have value between 0 and 1");&nbsp; &nbsp; if( A.size() != B.size() )&nbsp; &nbsp; &nbsp; &nbsp; CV_Error( Error::StsUnmatchedSizes, "Both input images must have the same size" );&nbsp; &nbsp; if( A.type() != B.type() )&nbsp; &nbsp; &nbsp; &nbsp; CV_Error( Error::StsUnmatchedFormats, "Both input images must have the same data type" );&nbsp; &nbsp; int count = A.checkVector(2);&nbsp; &nbsp; if( count > 0 )&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; A.reshape(2, count).convertTo(pA, CV_32F);&nbsp; &nbsp; &nbsp; &nbsp; B.reshape(2, count).convertTo(pB, CV_32F);&nbsp; &nbsp; }&nbsp; &nbsp; else if( A.depth() == CV_8U )&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; int cn = A.channels();&nbsp; &nbsp; &nbsp; &nbsp; CV_Assert( cn == 1 || cn == 3 || cn == 4 );&nbsp; &nbsp; &nbsp; &nbsp; Size sz0 = A.size();&nbsp; &nbsp; &nbsp; &nbsp; Size sz1(WIDTH, HEIGHT);&nbsp; &nbsp; &nbsp; &nbsp; scale = std::max(1., std::max( (double)sz1.width/sz0.width, (double)sz1.height/sz0.height ));&nbsp; &nbsp; &nbsp; &nbsp; sz1.width = cvRound( sz0.width * scale );&nbsp; &nbsp; &nbsp; &nbsp; sz1.height = cvRound( sz0.height * scale );&nbsp; &nbsp; &nbsp; &nbsp; bool equalSizes = sz1.width == sz0.width && sz1.height == sz0.height;&nbsp; &nbsp; &nbsp; &nbsp; if( !equalSizes || cn != 1 )&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Mat sA, sB;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( cn != 1 )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Mat gray;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cvtColor(A, gray, COLOR_BGR2GRAY);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; resize(gray, sA, sz1, 0., 0., INTER_AREA);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cvtColor(B, gray, COLOR_BGR2GRAY);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; resize(gray, sB, sz1, 0., 0., INTER_AREA);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; resize(A, sA, sz1, 0., 0., INTER_AREA);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; resize(B, sB, sz1, 0., 0., INTER_AREA);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; A = sA;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; B = sB;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; int count_y = COUNT;&nbsp; &nbsp; &nbsp; &nbsp; int count_x = cvRound((double)COUNT*sz1.width/sz1.height);&nbsp; &nbsp; &nbsp; &nbsp; count = count_x * count_y;&nbsp; &nbsp; &nbsp; &nbsp; pA.resize(count);&nbsp; &nbsp; &nbsp; &nbsp; pB.resize(count);&nbsp; &nbsp; &nbsp; &nbsp; status.resize(count);&nbsp; &nbsp; &nbsp; &nbsp; for( i = 0, k = 0; i < count_y; i++ )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for( j = 0; j < count_x; j++, k++ )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pA[k].x = (j+0.5f)*sz1.width/count_x;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pA[k].y = (i+0.5f)*sz1.height/count_y;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; // find the corresponding points in B&nbsp; &nbsp; &nbsp; &nbsp; calcOpticalFlowPyrLK(A, B, pA, pB, status, noArray(), Size(21, 21), 3,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;TermCriteria(TermCriteria::MAX_ITER,40,0.1));&nbsp; &nbsp; &nbsp; &nbsp; // repack the remained points&nbsp; &nbsp; &nbsp; &nbsp; for( i = 0, k = 0; i < count; i++ )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( status[i] )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( i > k )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pA[k] = pA[i];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pB[k] = pB[i];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; k++;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; count = k;&nbsp; &nbsp; &nbsp; &nbsp; pA.resize(count);&nbsp; &nbsp; &nbsp; &nbsp; pB.resize(count);&nbsp; &nbsp; }&nbsp; &nbsp; else&nbsp; &nbsp; &nbsp; &nbsp; CV_Error( Error::StsUnsupportedFormat, "Both input images must have either 8uC1 or 8uC3 type" );&nbsp; &nbsp; good_idx.resize(count);&nbsp; &nbsp; if( count < ransacSize0 )&nbsp; &nbsp; &nbsp; &nbsp; return Mat();&nbsp; &nbsp; Rect brect = boundingRect(pB);&nbsp; &nbsp; std::vector<Point2f> a(ransacSize0);&nbsp; &nbsp; std::vector<Point2f> b(ransacSize0);&nbsp; &nbsp; // RANSAC stuff:&nbsp; &nbsp; // 1. find the consensus&nbsp; &nbsp; for( k = 0; k < ransacMaxIters; k++ )&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; std::vector<int> idx(ransacSize0);&nbsp; &nbsp; &nbsp; &nbsp; // choose random 3 non-complanar points from A & B&nbsp; &nbsp; &nbsp; &nbsp; for( i = 0; i < ransacSize0; i++ )&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for( k1 = 0; k1 < ransacMaxIters; k1++ )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; idx[i] = rng.uniform(0, count);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for( j = 0; j < i; j++ )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( idx[j] == idx[i] )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // check that the points are not very close one each other&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( fabs(pA[idx[i]].x - pA[idx[j]].x) +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fabs(pA[idx[i]].y - pA[idx[j]].y) < FLT_EPSILON )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( fabs(pB[idx[i]].x - pB[idx[j]].x) +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fabs(pB[idx[i]].y - pB[idx[j]].y) < FLT_EPSILON )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( j < i )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( i+1 == ransacSize0 )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // additional check for non-complanar vectors&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; a[0] = pA[idx[0]];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; a[1] = pA[idx[1]];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; a[2] = pA[idx[2]];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b[0] = pB[idx[0]];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b[1] = pB[idx[1]];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b[2] = pB[idx[2]];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; double dax1 = a[1].x - a[0].x, day1 = a[1].y - a[0].y;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; double dax2 = a[2].x - a[0].x, day2 = a[2].y - a[0].y;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; double dbx1 = b[1].x - b[0].x, dby1 = b[1].y - b[0].y;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; double dbx2 = b[2].x - b[0].x, dby2 = b[2].y - b[0].y;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const double eps = 0.01;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( fabs(dax1*day2 - day1*dax2) < eps*std::sqrt(dax1*dax1+day1*day1)*std::sqrt(dax2*dax2+day2*day2) ||&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fabs(dbx1*dby2 - dby1*dbx2) < eps*std::sqrt(dbx1*dbx1+dby1*dby1)*std::sqrt(dbx2*dbx2+dby2*dby2) )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( k1 >= ransacMaxIters )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if( i < ransacSize0 )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue;&nbsp; &nbsp; &nbsp; &nbsp; // estimate the transformation using 3 points&nbsp; &nbsp; &nbsp; &nbsp; getRTMatrix( a, b, 3, M, fullAffine );&nbsp; &nbsp; &nbsp; &nbsp; const double* m = M.ptr<double>();&nbsp; &nbsp; &nbsp; &nbsp; for( i = 0, good_count = 0; i < count; i++ )&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( std::abs( m[0]*pA[i].x + m[1]*pA[i].y + m[2] - pB[i].x ) +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 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 )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; good_idx[good_count++] = i;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if( good_count >= count*ransacGoodRatio )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; }&nbsp; &nbsp; if( k >= ransacMaxIters )&nbsp; &nbsp; &nbsp; &nbsp; return Mat();&nbsp; &nbsp; if( good_count < count )&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; for( i = 0; i < good_count; i++ )&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; j = good_idx[i];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pA[i] = pA[j];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pB[i] = pB[j];&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; getRTMatrix( pA, pB, good_count, M, fullAffine );&nbsp; &nbsp; M.at<double>(0, 2) /= scale;&nbsp; &nbsp; M.at<double>(1, 2) /= scale;&nbsp; &nbsp; return M;}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python