C++版本OpenCv教程(十六)图像仿射变换

本文介绍了在OpenCV 4中实现图像旋转的方法,通过图像的仿射变换实现旋转,需确定旋转角度、中心和矩阵,利用getRotationMatrix2D()计算旋转矩阵,warpAffine()实现仿射变换。还介绍了仿射变换概念,以及用getAffineTransform()根据三点对应关系求变换矩阵。

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

介绍完图像的缩放和翻转后,接下来将要介绍图像的旋转,但是在OpenCV 4中并没有专门用于图像旋转的函数,而是通过图像的仿射变换实现图像的旋转。实现图像的旋转首先需要确定旋转角度和旋转中心,之后 确定旋转矩阵,最终通过仿射变换实现图像旋转。针对这个流程,OpenCV 4提供了getRotationMatrix2D()函数用于计算旋转矩阵warpAffine()函数用于实现图像的仿射变换。首先介绍计算旋转矩阵getRotationMatrix2D()函数,该函数的函数原型在代码清单3-31中给出。

Mat cv::getRotationMatrix2D (Point2f center,double  angle,double  scale)
  • center:图像旋转的中心位置。
  • angle:图像旋转的角度,单位为度,正值为逆时针旋转。
  • scale:两个轴的比例因子,可以实现旋转过程中的图像缩放,不缩放输入1。

该函数输入旋转角度和旋转中心,返回图像旋转矩阵,该返回值得数据类型为Mat类,是一个2×3的矩阵。如果我们已知图像旋转矩阵,可以自己生成旋转矩阵而不调用该函数。该函数生成的旋转矩阵与旋转角度和旋转中心的关系如式(3.11)所示。
在这里插入图片描述
其中:
在这里插入图片描述

warpAffine()函数进行仿射变换,就可以实现图像的旋转,在代码清单3-32中给出了warpAffine()函数的函数原型。

void cv::warpAffine(InputArray src,
                    OutputArray dst,
                    InputArray M,
                    Size dsize,
                    int  flags = INTER_LINEAR,
                    int  borderMode = BORDER_CONSTANT,
                    const Scalar& borderValue = Scalar()
)
  • src:输入图像。
  • dst:仿射变换后输出图像,与src数据类型相同,但是尺寸与dsize相同。
  • M:2×3的变换矩阵。
  • dsize:输出图像的尺寸。
  • flags:插值方法标志,可选参数及含义在表3-3和表3-4中给出。
  • borderMode:像素边界外推方法的标志。
  • borderValue:填充边界使用的数值,默认情况下为0。

该函数拥有多个参数,但是多数都与前面介绍的图像尺寸变换具有相同的含义。函数中第三个参数为前面求取的图像旋转矩阵,第四个参数是输出图像的尺寸。函数第五个参数是仿射变换插值方法的标志,这里相比于图像尺寸变换多增加了两个类型,可以与其他插值方法一起使用,这两种类型在表3-4中给出。函数第六个参数为像素边界外推方法的标志,其可以的标志和对应的方法在表3-5中给出。第七个参数是外推标志选择BORDER_CONSTANT时的定值,默认情况下为0。
在这里插入图片描述在这里插入图片描述
在了解函数每个参数的含义之后,为了更好的理解函数作用,需要介绍一下仿射变换的概念。仿射变换就是图像的旋转、平移和缩放操作的统称,可以表示为线性变换和平移变换的叠加。仿射变换的数学表示是先乘以一个线形变换矩阵再加上一个平移向量,其中线性变换矩阵为2×2的矩阵,平移向量为2×1的向量,至此你可能理解了为什么函数需要输入一个2×3的变换矩阵。假设我们存在一个线性变换矩阵和平移矩阵,两者与输入的矩阵之间的关系如式(3.13)中所示。
在这里插入图片描述

根据旋转矩阵和平移矩阵以及图像像素值,仿射变换的数学原理可以用式(3.14)来表示。
在这里插入图片描述
仿射变换又称为三点变换,如果知道变换前后两张图像中三个像素点坐标的对应关系,就可以求得仿射变换中的变换矩阵,OpenCV 4提供了利用三个对应像素点来确定矩阵的函数getAffineTransform(),该函数的函数原型在代码清单3-33中给出。

Mat cv::getAffineTransform(const Point2f src[],const Point2f dst[])
  • src[]:原图像中的三个像素坐标。
  • dst[]:目标图像中的三个像素坐标。

该函数两个输入量都是存放浮点坐标的数组,在生成数组的时候像素点的输入顺序无关,但是需要保证像素点的对应关系,函数的返回值是一个2×3的变换矩阵。

有了前面变换矩阵的求取,就可以利用warpAffine()函数实现矩阵的仿射变换,我们在代码清单3-34的例程中实现了图像的旋转以及图像三点映射的仿射变换,最终结果在图3-23中给出。

#include<iostream>
#include<vector>
#include<string>
#include <opencv2/opencv.hpp>
#include "opencv/highgui.h"

using namespace std;
using namespace cv;

int main(int argc,char** argv) {
    cout<<"OpenCv Version: "<<CV_VERSION<<endl;
    Mat img=imread("699342568.jpg");
    if(img.empty()){
        cout<<"请确认输入的图像;路径是否正确"<<endl;
        return -1;
    }
    Mat img_;
    resize(img,img_,Size(img.rows/2,img.cols/2));
    imshow("src",img_);
    Mat rotation0,rotation1,img_warp0,img_warp1;
    double angle=30;//设置图像旋转的角度
    Size dst_size(img_.rows,img_.cols);//设置输出图像的尺寸
    Point2f center(img_.rows/2.0,img_.cols/2.0);//设置图像的旋转中心
    rotation0=getRotationMatrix2D(center,angle,1);//计算放射变换矩阵
    warpAffine(img_,img_warp0,rotation0,dst_size);//进行仿射变换
    imshow("img_warp0",img_warp0);
    //根据定义的三个点进行仿射变换
    Point2f src_points[3];
    Point2f dst_points[3];
    src_points[0]=Point2f(0,0);//原始图像的三个点
    src_points[1]=Point2f(0,(float)(img_.cols-1));
    src_points[2]=Point2f((float)(img_.rows-1),(float)(img_.cols-1));
    //仿射变换后图像中的三个点
    dst_points[0]=Point2f((float)(img_.rows)*0.11,(float)(img_.cols)*0.20);
    dst_points[1]=Point2f((float)(img_.rows)*0.15,(float)(img_.cols)*0.70);
    dst_points[0]=Point2f((float)(img_.rows)*0.81,(float)(img_.cols)*0.85);
    rotation1=getAffineTransform(src_points,dst_points);//根据对应点求取放射变换矩阵
    warpAffine(img_,img_warp1,rotation1,dst_size);//进行放射变换
    imshow("img_warp1",img_warp1);
    waitKey(0);
    return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值