【OpenCV3】透視變換——cv::getPerspectiveTransform()與cv::warpPerspective()詳解
阿新 • • 發佈:2018-11-15
透視變換(Perspective Transformation)是將成像投影到一個新的視平面(Viewing Plane),也稱作投影對映(Projective Mapping)。如圖1,通過透視變換ABC變換到A'B'C'。
圖1 透視變換示意圖
透視變換的通用公式為:
變換後的座標x,y分別為:。
展開之後即:
其中,稱為透視變換矩陣:表示線性變換,如scaling,shearing和ratotion等;
用於平移,因此此前介紹的仿射變換可以視作一種特殊的透視變換。
如圖2,我們想將傾斜視角拍攝到的道路影象轉換成鳥瞰圖 ,即將攝像機的視角轉換到和道路平行。
圖2 傾斜視角
首先,我們需要獲得此次透視變換的變換矩陣,opencv2和opencv3中用於計算透視變換矩陣的函式是cv::getPerspectiveTransform(),C++介面其呼叫形式如下:
-
cv::Mat cv::getPerspectiveTransform(
// 返回3x3透視變換矩陣
-
const cv::Point2f* src,
// 源影象四個頂點座標(點陣列)
-
const cv::Point2f* dst
// 目標影象上四個頂點的座標(點陣列)
-
);
如圖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++程式碼如下:
-
cv::
Mat get_perspective_mat()
-
{
-
cv::Point2f src_points[] = {
-
cv::Point2f(
165,
270),
-
cv::Point2f(
835,
270),
-
cv::Point2f(
360,
125),
-
cv::Point2f(
615,
125) };
-
-
cv::Point2f dst_points[] = {
-
cv::Point2f(
165,
270),
-
cv::Point2f(
835,
270),
-
cv::Point2f(
165,
30),
-
cv::Point2f(
835,
30) };
-
-
cv::Mat M = cv::getPerspectiveTransform(src_points, dst_points);
-
-
return M;
-
-
}
Python程式碼如下:
-
def get_perspective_mat():
-
-
src_points = np.array([[
165.,
270.], [
835.,
270.], [
360.,
125.], [
615.,
125.]], dtype =
"float32")
-
dst_points = np.array([[
165.,
270.], [
835.,
270.], [
165.,
30.], [
835.,
30.]], dtype =
"float32")
-
-
M = cv2.getPerspectiveTransform(src_points, dst_points)
-
-
return M
計算結果如下:
在獲得透視變換矩陣後,即可使用與cv::warpPerspective()進行透視變換,其呼叫形式如下:
-
void cv::warpPerspective(
-
cv::InputArray src,
// 輸入影象
-
cv::OutputArray dst,
// 輸出影象
-
cv::InputArray M,
// 3x3 變換矩陣
-
cv::Size dsize,
// 目標影象大小
-
int flags = cv::INTER_LINEAR,
// 插值方法
-
int borderMode = cv::BORDER_CONSTANT,
// 外推方法
-
const cv::Scalar& borderValue = cv::Scalar()
//常量邊界時使用
-
);
C++程式碼如下:
-
cv::Mat perspective;
-
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