static Mat endpointError( const Mat_<Point2f>& flow1, const Mat_<Point2f>& flow2 ) { Mat result(flow1.size(), CV_32FC1); for ( int i = 0; i < flow1.rows; ++i ) { for ( int j = 0; j < flow1.cols; ++j ) { const Point2f u1 = flow1(i, j); const Point2f u2 = flow2(i, j); if ( isFlowCorrect(u1) && isFlowCorrect(u2) ) { const Point2f diff = u1 - u2; result.at<float>(i, j) = sqrt((float)diff.ddot(diff)); //distance } else result.at<float>(i, j) = std::numeric_limits<float>::quiet_NaN(); } } return result; }
static int intersectConvexConvex_( const Point2f* P, int n, const Point2f* Q, int m, Point2f* result, float* _area ) { Point2f* result0 = result; // P has n vertices, Q has m vertices. int a=0, b=0; // indices on P and Q (resp.) Point2f Origin(0,0); tInFlag inflag=Unknown; // {Pin, Qin, Unknown}: which inside int aa=0, ba=0; // # advances on a & b indices (after 1st inter.) bool FirstPoint=true;// Is this the first point? (used to initialize). Point2f p0; // The first point. *result++ = Point2f(FLT_MAX, FLT_MAX); do { // Computations of key variables. int a1 = (a + n - 1) % n; // a-1, b-1 (resp.) int b1 = (b + m - 1) % m; Point2f A = P[a] - P[a1], B = Q[b] - Q[b1]; // directed edges on P and Q (resp.) int cross = areaSign( Origin, A, B ); // sign of z-component of A x B int aHB = areaSign( Q[b1], Q[b], P[a] ); // a in H(b). int bHA = areaSign( P[a1], P[a], Q[b] ); // b in H(A); // If A & B intersect, update inflag. Point2f p, q; int code = segSegInt( P[a1], P[a], Q[b1], Q[b], p, q ); if( code == '1' || code == 'v' ) { if( inflag == Unknown && FirstPoint ) { aa = ba = 0; FirstPoint = false; p0 = p; *result++ = p; } inflag = inOut( p, inflag, aHB, bHA, result ); } //-----Advance rules----- // Special case: A & B overlap and oppositely oriented. if( code == 'e' && A.ddot(B) < 0 ) { addSharedSeg( p, q, result ); return (int)(result - result0); } // Special case: A & B parallel and separated. if( cross == 0 && aHB < 0 && bHA < 0 ) return (int)(result - result0); // Special case: A & B collinear. else if ( cross == 0 && aHB == 0 && bHA == 0 ) { // Advance but do not output point. if ( inflag == Pin ) b = advance( b, &ba, m, inflag == Qin, Q[b], result ); else a = advance( a, &aa, n, inflag == Pin, P[a], result ); } // Generic cases. else if( cross >= 0 ) { if( bHA > 0) a = advance( a, &aa, n, inflag == Pin, P[a], result ); else b = advance( b, &ba, m, inflag == Qin, Q[b], result ); } else { if( aHB > 0) b = advance( b, &ba, m, inflag == Qin, Q[b], result ); else a = advance( a, &aa, n, inflag == Pin, P[a], result ); } // Quit when both adv. indices have cycled, or one has cycled twice. } while ( ((aa < n) || (ba < m)) && (aa < 2*n) && (ba < 2*m) ); // Deal with special cases: not implemented. if( inflag == Unknown ) { // The boundaries of P and Q do not cross. // ... } int i, nr = (int)(result - result0); double area = 0; Point2f prev = result0[nr-1]; for( i = 1; i < nr; i++ ) { result0[i-1] = result0[i]; area += (double)prev.x*result0[i].y - (double)prev.y*result0[i].x; prev = result0[i]; } *_area = (float)(area*0.5); if( result0[nr-2] == result0[0] && nr > 1 ) nr--; return nr-1; }
bool CV_OptFlowTest::runSparse() { Mat prev = imread(string(ts->get_data_path()) + "optflow/rock_1.bmp", 0); Mat next = imread(string(ts->get_data_path()) + "optflow/rock_2.bmp", 0); if (prev.empty() || next.empty()) { ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA ); return false; } Mat cprev, cnext; cvtColor(prev, cprev, CV_GRAY2BGR); cvtColor(next, cnext, CV_GRAY2BGR); vector<Point2f> prev_pts; vector<Point2f> next_ptsOpt; vector<Point2f> next_ptsAff; vector<uchar> status_Opt; vector<uchar> status_Aff; vector<float> error; vector<float> matrices; Size netSize(10, 10); Point2f center = Point(prev.cols/2, prev.rows/2); for(int i = 0 ; i < netSize.width; ++i) for(int j = 0 ; j < netSize.width; ++j) { Point2f p(i * float(prev.cols)/netSize.width, j * float(prev.rows)/netSize.height); prev_pts.push_back((p - center) * 0.5f + center); } calcOpticalFlowPyrLK( prev, next, prev_pts, next_ptsOpt, status_Opt, error ); calcAffineFlowPyrLK ( prev, next, prev_pts, next_ptsAff, status_Aff, error, matrices); const double expected_shift = 25; const double thres = 1; for(size_t i = 0; i < prev_pts.size(); ++i) { circle(cprev, prev_pts[i], 2, CV_RGB(255, 0, 0)); if (status_Opt[i]) { circle(cnext, next_ptsOpt[i], 2, CV_RGB(0, 0, 255)); Point2f shift = prev_pts[i] - next_ptsOpt[i]; double n = sqrt(shift.ddot(shift)); if (fabs(n - expected_shift) > thres) { ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH); return false; } } if (status_Aff[i]) { circle(cnext, next_ptsAff[i], 4, CV_RGB(0, 255, 0)); Point2f shift = prev_pts[i] - next_ptsAff[i]; double n = sqrt(shift.ddot(shift)); if (fabs(n - expected_shift) > thres) { ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH); return false; } } } /*namedWindow("P"); imshow("P", cprev); namedWindow("N"); imshow("N", cnext); waitKey();*/ return true; }