透视变换(Perspective Transform)是将图片投影到一个新的视角或平面,变换公式如下。
在之前的章节中我们学习过仿射变换(affine transform) 可以看到,而射变换的变换矩阵是3x2的变换矩阵。和仿射变换不同的是,透视变换的变换矩阵是一个3x3的矩阵。透视变换的作用域是一个三维坐标系(x,y,z), 而仿射变换则是二维(x,y)平面变换。从另一个角度来说,仿射变换也可以看做是一种特殊的透视变换(z轴方向不变)。
透视变换和仿射变换的一个重要区别是,两条平行的线在经过仿射变换之后依然保持平行,但透视变换并不保证这一点。
OpenCV提供了透视变换的函数warpPerspective(). 下面我们来尝试使用warpPerspective()函数将下面的卡片透视变换为鸟瞰图(俯视视角)。原图片的分辨率是320x240,我们在图片中找到卡片四个角的坐标,分别为(0,0),(240,21),(0,240),(240,216)。在最终的鸟瞰图中,我们需要这四个点的坐标分别转换为(0,0),(320,0),(0,240),(320,240)。因此利用这四个点的对应关系,我们可以构建变换矩阵。
Point2f srcTri[4];
Point2f dstTri[4];
Mat warpPerspective_mat( 3, 3, CV_32FC1 );
Mat src, warpPerspective_dst;
src = imread( "card2.jpeg", IMREAD_COLOR );
warpPerspective_dst = Mat::zeros( src.rows, src.cols, src.type() );
/// 设置4组点,求出变换矩阵
srcTri[0] = Point2f( 0,0 );
srcTri[1] = Point2f( 240, 21 );
srcTri[2] = Point2f( 0,src.rows - 1);
srcTri[3] = Point2f( 240, 216);
dstTri[0] = Point2f( 0, 0 );
dstTri[1] = Point2f( src.cols, 0 );
dstTri[2] = Point2f( 0, src.rows );
dstTri[3] = Point2f( src.cols, src.rows );
//计算透视变换矩阵
warpPerspective_mat = getPerspectiveTransform( srcTri, dstTri );
//应用透视变换
warpPerspective( src, warpPerspective_dst, warpPerspective_mat, src.size() );
//显示原图和变换后结果
namedWindow( source_window, WINDOW_AUTOSIZE );
imshow( source_window, src );
namedWindow( warpPerspective_window, WINDOW_AUTOSIZE );
imshow( warpPerspective_window, warpPerspective_dst );
waitKey(0);
最终得到的结果如下。图片被成功转换到了鸟瞰图的视角。