OpenCV学习---仿射变换和透视变换

本文深入探讨了图像处理中的仿射变换和透视变换,详细解释了这两种变换的基本原理及其在OpenCV中的应用。仿射变换保持图形的平直性和平行性,而透视变换则提供更大的灵活性,适用于更复杂的图像投影需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:Opencv学习——仿射变换和透视变换,感谢博主分享。

仿射变换是一种二维坐标之间的变换,变换前后保持图形的平直性和平行性。仿射变换可以理解为是向量经过一次线性变换和一次平移变换。 
透视变换可以看做是二维与三维坐标之间的变换,变换前后没有了仿射变换的特性。其实仿射变换是透视变换的一种特殊形式。下图能够展示两种变换的区别:

仿射变换

仿射变换可以表示为一个线性变换加上一个平移变换,所以仿射变换可以用来表示: 
a. 旋转(线性变换) 
b. 平移(向量加) 
c. 缩放操作(线性变换)

通常用2X3矩阵表示仿射变换 

求仿射变换矩阵需要知道变换前后三组对应点的位置。

Opencv中有封装好的仿射变换函数:

void warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())

参数InputArray src:输入变换前图像 

参数OutputArray dst:输出变换后图像,需要初始化一个空矩阵用来保存结果,不用设定矩阵尺寸

参数InputArray M:变换矩阵,用另一个函数getAffineTransform()计算

参数Size dsize:设置输出图像大小

参数int flags=INTER_LINEAR:设置插值方式,默认方式为线性插值

生成变换矩阵的函数getAffineTransform():

Mat getAffineTransform(const Point2f* src, const Point2f* dst)

 

参数const Point2f* src:原图的三个固定顶点

参数const Point2f* dst:目标图像的三个固定顶点

返回值:Mat型变换矩阵,可直接用于warpAffine()函数

注意,顶点数组长度超过3个,则会自动以前3个为变换顶点;数组可用Point2f[]或Point2f*表示

透视变换

透视变换是将图像投影到一个新的视平面,也称作投影映射。透视变换能提供更大的灵活性,但是一个透视投影并不是线性变换,因此其采用的是3X3的映射矩阵,控制点变为4个。 
透视变换矩阵如下:

其中

表示线性变换,比如比例变换、剪切变换、旋转变换。 

Opencv中透视变换的函数为:

void warpPerspective(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())

生成变换矩阵的函数为:

Mat getPerspectiveTransform(const Point2f* src, const Point2f* dst) 

实例代码 

Mat AffineTrans(Mat src, Point2f* scrPts, Point2f* dstPts)
{
    Mat dst;
    Mat Trans = getAffineTransform(scrPts, dstPts);
    warpAffine(src, dst, Trans, Size(src.cols, src.rows), CV_INTER_CUBIC);
    return dst;
}

Mat AffineTrans(Mat src, Point2f* scrPts, Point2f* dstPts)
{
    Mat dst;
    Mat Trans = getAffineTransform(scrPts, dstPts);
    warpAffine(src, dst, Trans, Size(src.cols, src.rows), CV_INTER_CUBIC);
    return dst;
}

int main()
{
    Mat I = imread("..//img.jpg");  //700*438

    Point2f srcPts[4] = { Point2f(100, 50), Point2f(100, 390), Point2f(600, 50), Point2f(600, 390) };
    Point2f dstPts[4] = { Point2f(200, 100), Point2f(200, 330), Point2f(500, 50), Point2f(600, 390) };
    Mat dst_affine = AffineTrans(I, srcPts, dstPts);
    Mat dst_perspective = PerspectiveTrans(I, srcPts, dstPts);

    for (int i = 0; i < 4; i++)
    {
        circle(I, srcPts[i], 2, Scalar(0, 0, 255), 2);
        circle(dst_affine, dstPts[i], 2, Scalar(0, 0, 255), 2);
        circle(dst_perspective, dstPts[i], 2, Scalar(0, 0, 255), 2);
    }

    imshow("origin", I);
    imshow("affine", dst_affine);
    imshow("perspective", dst_perspective);
    waitKey();
    return 0;
}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值