2016-09-26 4 views

답변

2

cv::estimateRigidTransform입니다. 6 자유도 (회전, 평행 이동, 스케일링, 전단) 또는 부분 자유도 (회전, 평행 이동, 균일 한 스케일링)가있는 완전한 아핀 변환 중에서 선택할 수 있습니다.이 변환은 5 자유도입니다.

cv::Mat R = cv::estimateRigidTransform(p1,p2,false); 

// extend rigid transformation to use perspectiveTransform: 
cv::Mat H = cv::Mat(3,3,R.type()); 
H.at<double>(0,0) = R.at<double>(0,0); 
H.at<double>(0,1) = R.at<double>(0,1); 
H.at<double>(0,2) = R.at<double>(0,2); 

H.at<double>(1,0) = R.at<double>(1,0); 
H.at<double>(1,1) = R.at<double>(1,1); 
H.at<double>(1,2) = R.at<double>(1,2); 

H.at<double>(2,0) = 0.0; 
H.at<double>(2,1) = 0.0; 
H.at<double>(2,2) = 1.0; 

// compute perspectiveTransform on p1 
std::vector<cv::Point2f> result; 
cv::perspectiveTransform(p1,result,H) 

//warp image with transform 
cv::Mat warped; 
cv::warpPerspective(src,warped,H,src.size()); 

내가 그것을 시도 didnt는하지만, 대답을 다스 려하는 것은 그것을 잘 작동합니다 :

당신은 유사성이 this answer의 코드 두 vector<Point> P1과 P2로 변환 계산할 수 있습니다.

+1

들이 6 개 및 4 DOF 변환 정밀하지 않을 때, 강성를 호출하기로 결정하는 작은 역설적 엄격한. –

+0

답변 해 주셔서 감사합니다. 왜 4 대신 5 자유도가 있습니까? [그들의 수식] (http://docs.opencv.org/2.4/_images/math/0a22facbc11cdd0f9b8d4658e0c145da2cb8730b.png)에 따르면 단지 4 개의 매개 변수가 있습니다 – dontloo

+0

그래, 혼란스러워. 나는 오리엔테이션을위한 이론적으로 다섯 번째 매개 변수 e가 있다는 것을 알고 있습니다. 그러나 그것을 단단한 것으로 부르며, e는 1과 같아야합니다 (oriantation preserving). – PSchn

1

어쨌든 cv::estimateRigidTransform와 함께 사용하고있는 opencv 버전과 관련된 몇 가지 문제가 있습니다. 그래서 나는 2 점으로만 작동하는 함수를 작성했습니다. (충분한 것이고 더 빠를 것이라고 믿습니다).

cv::Mat getSimilarityTransform(const cv::Point2f src[], const cv::Point2f dst[]) 
{ 
    double src_d_y = src[0].y - src[1].y; 
    double src_d_x = src[0].x - src[1].x; 
    double src_dis = sqrt(pow(src_d_y, 2) + pow(src_d_x, 2)); 

    double dst_d_y = dst[0].y - dst[1].y; 
    double dst_d_x = dst[0].x - dst[1].x; 
    double dst_dis = sqrt(pow(dst_d_y, 2) + pow(dst_d_x, 2)); 

    double scale = dst_dis/src_dis; 
    // angle between two line segments 
    // ref: http://stackoverflow.com/questions/3365171/calculating-the-angle-between-two-lines-without-having-to-calculate-the-slope 
    double angle = atan2(src_d_y, src_d_x) - atan2(dst_d_y, dst_d_x); 

    double alpha = cos(angle)*scale; 
    double beta = sin(angle)*scale; 

    cv::Mat M(2, 3, CV_64F); 
    double* m = M.ptr<double>(); 

    m[0] = alpha; 
    m[1] = beta; 
    // tx = x' -alpha*x -beta*y 
    // average of two points 
    m[2] = (dst[0].x - alpha*src[0].x - beta*src[0].y + dst[1].x - alpha*src[1].x - beta*src[1].y)/2; 
    m[3] = -beta; 
    m[4] = alpha; 
    // ty = y' +beta*x -alpha*y 
    // average of two points 
    m[5] = (dst[0].y + beta*src[0].x - alpha*src[0].y + dst[1].y + beta*src[1].x - alpha*src[1].y)/2; 

    return M; 
} 

일부 결과합니다 (LFW 데이터 집합 사진)
enter image description here enter image description here enter image description here enter image description here

관련 문제