2016-09-26 161 views

回答

2

cv::estimateRigidTransform。您可以選擇具有6個自由度(旋轉,平移,縮放,剪切)或部分仿射(旋轉,平移,均勻縮放)的完全仿射變換,它具有5個自由度。

你可以計算的相似度由兩個vector<Point> P1和P2與代碼this answer變換:

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()); 

我沒有嘗試,但指的答案它應該工作的罰款。

+1

有點自相矛盾的是,他們選擇調用它是剛性的,當圖6個4 DOF變換是恰恰不是剛性。 –

+0

非常感謝您的回答,爲什麼它有5個自由度而不是4個?根據[他們的公式](http://docs.opencv.org/2.4/_images/math/0a22facbc11cdd0f9b8d4658e0c145da2cb8730b.png)只有4個參數 – dontloo

+0

是啊我很困惑。我知道理論上第五個參數是定向的。但在那裏稱它爲剛性的,所以e應該等於1(保持oriantation)。 – PSchn

1

不知何故,在我使用的opencv版本中使用cv::estimateRigidTransform時出現了一些問題,所以我寫了一個只適用於兩點的函數(對我來說這足夠了,我相信它會更快)。

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