【从零学习OpenCV 4】图像仿射变换

重磅干货,第一时间送达

经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍《从零学习OpenCV 4》。为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通,提前在公众号上连载部分内容,请持续关注小白。

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

代码清单3-31 getRotationMatrix2D()函数原型
1.  Mat cv::getRotationMatrix2D (Point2f center,
2.                                    double  angle,
3.                                    double  scale
4.                                    )
  • center:图像旋转的中心位置。

  • angle:图像旋转的角度,单位为度,正值为逆时针旋转。

  • scale:两个轴的比例因子,可以实现旋转过程中的图像缩放,不缩放输入1。

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

(3.11)

其中:

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

代码清单3-32 warpAffine()函数原型
1.  void cv::warpAffine(InputArray src,
2.                          OutputArray dst,
3.                          InputArray M,
4.                          Size dsize,
5.                          int  flags = INTER_LINEAR,
6.                          int  borderMode = BORDER_CONSTANT,
7.                          const Scalar& borderValue = Scalar()
8.                         )
  • src:输入图像。

  • dst:仿射变换后输出图像,与src数据类型相同,但是尺寸与dsize相同。

  • M:2×3的变换矩阵。

  • dsize:输出图像的尺寸。

  • flags:插值方法标志,可选参数及含义在表3-3和表3-4中给出。

  • borderMode:像素边界外推方法的标志。

  • borderValue:填充边界使用的数值,默认情况下为0。

该函数拥有多个参数,但是多数都与前面介绍的图像尺寸变换具有相同的含义。函数中第三个参数为前面求取的图像旋转矩阵,第四个参数是输出图像的尺寸。函数第五个参数是仿射变换插值方法的标志,这里相比于图像尺寸变换多增加了两个类型,可以与其他插值方法一起使用,这两种类型在表3-4中给出。函数第六个参数为像素边界外推方法的标志,其可以的标志和对应的方法在表3-5中给出。第七个参数是外推标志选择BORDER_CONSTANT时的定值,默认情况下为0。

表3-4 图像仿射变换中的补充插值方法

标志参数

简记

作用

WARP_FILL_OUTLIERS

8

填充所有输出图像的像素,如果部分像素落在输入图像的边界外,那么他们的值设定为fillval

WARP_INVERSE_MAP

16

表示M为输出图像到输入图像的反变换。

表3-5 边界填充方法和对应标志

标志参数

简记

作用

BORDER_CONSTANT

0

用特定值填充,如iiiiii|abcdefgh|iiiiiii

BORDER_REPLICATE

1

两端复制填充,如aaaaaa|abcdefgh|hhhhhhh

BORDER_REFLECT

2

倒叙填充,如fedcba|abcdefgh|hgfedcb

BORDER_WRAP

3

正序填充,如cdefgh|abcdefgh|abcdefg

BORDER_REFLECT_101

4

不包含边界值倒叙填充,如gfedcb|abcdefgh|gfedcba

BORDER_TRANSPARENT

5

随机填充,uvwxyz|abcdefgh|ijklmno

BORDER_REFLECT101

4

与BORDER_REFLECT_101相同

BORDER_DEFAULT

4

与BORDER_REFLECT_101相同

BORDER_ISOLATED

16

不关心感兴趣区域之外的部分

在了解函数每个参数的含义之后,为了更好的理解函数作用,需要介绍一下仿射变换的概念。仿射变换就是图像的旋转、平移和缩放操作的统称,可以表示为线性变换和平移变换的叠加。仿射变换的数学表示是先乘以一个线形变换矩阵再加上一个平移向量,其中线性变换矩阵为2×2的矩阵,平移向量为2×1的向量,至此你可能理解了为什么函数需要输入一个2×3的变换矩阵。假设我们存在一个线性变换矩阵和平移矩阵,两者与输入的矩阵之间的关系如式(3.13)中所示。

(3.13)

根据旋转矩阵和平移矩阵以及图像像素值,仿射变换的数学原理可以用式(3.14)来表示。

(3.14)

仿射变换又称为三点变换,如果知道变换前后两张图像中三个像素点坐标的对应关系,就可以求得仿射变换中的变换矩阵,OpenCV 4提供了利用三个对应像素点来确定矩阵的函数getAffineTransform(),该函数的函数原型在代码清单3-33中给出。

代码清单3-33 getAffineTransform()函数原型
1.  Mat cv::getAffineTransform(const Point2f src[],
2.                     const Point2f dst[]
3.                    )
  • src[]:原图像中的三个像素坐标。

  • dst[]:目标图像中的三个像素坐标。

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

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

代码清单3-34 myWarpAffine.cpp图像旋转与仿射变换
1.  #include <opencv2\opencv.hpp>
2.  #include <iostream>
3.  #include <vector>
4.  
5.  using namespace std;
6.  using namespace cv;
7.  
8.  int main()
9. {
10.    Mat img = imread("lena.png");
11.    if (img.empty())
12.    {
13.      cout << "请确认图像文件名称是否正确" << endl;
14.      return -1;
15.    }
16.  
17.    Mat rotation0, rotation1, img_warp0, img_warp1;
18.    double angle = 30; //设置图像旋转的角度
19.    Size dst_size(img.rows, img.cols); //设置输出图像的尺寸
20.    Point2f center(img.rows / 2.0, img.cols / 2.0); //设置图像的旋转中心
21.    rotation0 = getRotationMatrix2D(center, angle, 1); //计算放射变换矩阵
22.    warpAffine(img, img_warp0, rotation0, dst_size); //进行仿射变换
23.    imshow("img_warp0", img_warp0);
24.    //根据定义的三个点进行仿射变换
25.    Point2f src_points[3];
26.    Point2f dst_points[3];
27.    src_points[0] = Point2f(0, 0); //原始图像中的三个点
28.    src_points[1] = Point2f(0, (float)(img.cols - 1));
29.    src_points[2] = Point2f((float)(img.rows - 1), (float)(img.cols - 1));
30.       //放射变换后图像中的三个点
31.    dst_points[0] = Point2f((float)(img.rows)*0.11, (float)(img.cols)*0.20);
32.    dst_points[1] = Point2f((float)(img.rows)*0.15, (float)(img.cols)*0.70);
33.    dst_points[2] = Point2f((float)(img.rows)*0.81, (float)(img.cols)*0.85);
34.    rotation1 = getAffineTransform(src_points, dst_points); //根据对应点求取仿射变换矩阵
35.    warpAffine(img, img_warp1, rotation1, dst_size); //进行仿射变换
36.    imshow("img_warp1", img_warp1);
37.    waitKey(0);
38.    return 0;
39.  }

图3-23 mywarpAffine.cpp程序运行结果

(0)

相关推荐

  • python+opencv图像处理(二)

    python+opencv图像处理(二) ----图像变换 自然界中有很多的颜色,红红的花,绿绿的草,蓝蓝的天,白白的云,多姿多彩的世界,美轮美奂的图像. 通过手机,照相机就可以定格每一个美的瞬间. ...

  • [机器学习必知必会]凸优化

    定义 凸优化问题(OPT,convex optimization problem)指定义在凸集中的凸函数最优化的问题.尽管凸优化的条件比较苛刻,但仍然在机器学习领域有十分广泛的应用. 凸优化问题的优势 ...

  • python进阶—OpenCV之常用图像操作函数说明

    文章目录 cv2.threshold cv2.bitwise_and cv2.bitwise_or cv2.bitwise_not cv2.inRange cv2.resize cv2.adaptiv ...

  • python+opencv图像处理(十二)

    图像仿射变换和透视变换 天晴了...... 1.仿射变换 图像的仿射变换就是图像的旋转加上拉升,说直白点,就是把矩形变成平行四边形. 要把矩形变成平行四边行,只需要拉伸其四个角点就行了,事实上,只需要 ...

  • python+opencv图像处理(十)

    图像旋转 本篇主要利用opencv的转换函数warpAffine实现图像的平移和旋转. 1.图像旋转 图像旋转即是根据某个中心点进行旋转. 要进行旋转,要找到中心点,要知道旋转角度,opencv提供了 ...

  • OpenCV-Python图像的缩放、翻转和旋转

    重磅干货,第一时间送达 图像的缩放 opencv中对图像进行放缩[1]有两种方式可以实现,一种是使用指定尺寸放缩:一种是使用缩放比例放缩. 指定尺寸 cv2.resize(image, (1920, ...

  • 【从零学习OpenCV】图像的保存&视频的保存

    重磅干货,第一时间送达 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍<从零学习OpenCV 4>.为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通 ...

  • 【从零学习OpenCV 4】图像修复

    重磅干货,第一时间送达 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍<OpenCV 4开发详解>.为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通 ...

  • 【从零学习OpenCV 4】分割图像——Mean-Shift分割算法

    重磅干货,第一时间送达 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍<从零学习OpenCV 4>.为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通 ...

  • 【从零学习OpenCV 4】分割图像——Grabcut图像分割

    重磅干货,第一时间送达 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍<OpenCV 4开发详解>.为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通 ...

  • 【从零学习OpenCV 4】分割图像——分水岭法

    重磅干货,第一时间送达 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍<OpenCV 4开发详解>.为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通 ...

  • 【从零学习OpenCV 4】图像矩的计算与应用

    重磅干货,第一时间送达 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍<从零学习OpenCV 4>.为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通 ...

  • 【从零学习OpenCV 4】图像膨胀

    重磅干货,第一时间送达 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍<OpenCV 4开发详解>.为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通 ...

  • 【从零学习OpenCV 4】图像距离变换

    重磅干货,第一时间送达 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍<OpenCV 4开发详解>.为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通 ...

  • 【从零学习OpenCV 4】图像中添加高斯噪声

    重磅干货,第一时间送达 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍<从零学习OpenCV 4>.为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通 ...