1. 程式人生 > >【OpenCV3】透視變換——cv::getPerspectiveTransform()與cv::warpPerspective()詳解

【OpenCV3】透視變換——cv::getPerspectiveTransform()與cv::warpPerspective()詳解

透視變換(Perspective Transformation)是將成像投影到一個新的視平面(Viewing Plane),也稱作投影對映(Projective Mapping)。如圖1,通過透視變換ABC變換到A'B'C'。


圖1 透視變換示意圖

透視變換的通用公式為:


變換後的座標x,y分別為:

展開之後即:


其中,稱為透視變換矩陣:表示線性變換,如scaling,shearing和ratotion等;

用於平移,因此此前介紹的仿射變換可以視作一種特殊的透視變換。

如圖2,我們想將傾斜視角拍攝到的道路影象轉換成鳥瞰圖

,即將攝像機的視角轉換到和道路平行。


圖2 傾斜視角


首先,我們需要獲得此次透視變換的變換矩陣,opencv2和opencv3中用於計算透視變換矩陣的函式是cv::getPerspectiveTransform(),C++介面其呼叫形式如下:


  
  1. cv::Mat cv::getPerspectiveTransform( // 返回3x3透視變換矩陣
  2. const cv::Point2f* src, // 源影象四個頂點座標(點陣列)
  3. const cv::Point2f* dst // 目標影象上四個頂點的座標(點陣列)
  4. );

如圖3 ,我們選取道路上的兩條平行分界線上的四個點A(165, 270)、C(360, 125)、D(615, 125)、B(835, 270),對應於鳥瞰圖上的點則分別為A(165, 270)、C'(165, 30)、D'(835, 30)、B(835, 270

)。


圖3 透視變換端點

通過這四對點我們即可計算出透視變換矩陣M。

C++程式碼如下:


  
  1. cv:: Mat get_perspective_mat()
  2. {
  3. cv::Point2f src_points[] = {
  4. cv::Point2f( 165, 270),
  5. cv::Point2f( 835, 270),
  6. cv::Point2f( 360, 125),
  7. cv::Point2f( 615, 125) };
  8. cv::Point2f dst_points[] = {
  9. cv::Point2f( 165, 270),
  10. cv::Point2f( 835, 270),
  11. cv::Point2f( 165, 30),
  12. cv::Point2f( 835, 30) };
  13. cv::Mat M = cv::getPerspectiveTransform(src_points, dst_points);
  14. return M;
  15. }


Python程式碼如下:


  
  1. def get_perspective_mat():
  2. src_points = np.array([[ 165., 270.], [ 835., 270.], [ 360., 125.], [ 615., 125.]], dtype = "float32")
  3. dst_points = np.array([[ 165., 270.], [ 835., 270.], [ 165., 30.], [ 835., 30.]], dtype = "float32")
  4. M = cv2.getPerspectiveTransform(src_points, dst_points)
  5. return M


計算結果如下:


在獲得透視變換矩陣後,即可使用與cv::warpPerspective()進行透視變換,其呼叫形式如下:


  
  1. void cv::warpPerspective(
  2. cv::InputArray src, // 輸入影象
  3. cv::OutputArray dst, // 輸出影象
  4. cv::InputArray M, // 3x3 變換矩陣
  5. cv::Size dsize, // 目標影象大小
  6. int flags = cv::INTER_LINEAR, // 插值方法
  7. int borderMode = cv::BORDER_CONSTANT, // 外推方法
  8. const cv::Scalar& borderValue = cv::Scalar() //常量邊界時使用
  9. );

C++程式碼如下:


  
  1. cv::Mat perspective;
  2. cv::warpPerspective(image, perspective, M, cv::Size( 960, 270), cv::INTER_LINEAR);



Python程式碼如下:

    perspective = cv2.warpPerspective(image, M, (960, 270), cv2.INTER_LINEAR)
  


變換結果如下:



2017.05.19