opencv —— getRotationMatrix2D、warpAffine 仿射变换实现图像旋转缩放
仿射变换的基本概念
仿射变换是一种二维坐标(x, y)到二维坐标(u, v)的线性变换,其数学表达式形式如下:
对应的齐次坐标矩阵表示形式为:
仿射变换保持了二维图形的“平直性”(直线经仿射变换后依然为直线)和“平行性”(直线之间的相对位置关系保持不变,平行线经仿射变换后依然为平行线,且直线上点的位置顺序不会发生变化)。
非共线的三对对应点可以确定一个唯一的仿射变换。
几种常见的仿射变换形式:
-
平移变换
数学形式:
矩阵形式:
-
缩放变换
矩阵形式:
-
旋转变换
矩阵形式:
仿射变换形式汇总图:
OpenCV 中实现仿射变换,一般涉及到 getRotationMatrix2D 和 warpAffine 这两个函数:
计算二维旋转变换矩阵:getRotationMatrix2D 函数
Mat getRotationMatrix2D(Point2f center, double angle, double scale);
- center,源图像的旋转中心。最终旋转中心会映射到输出图像同样位置上,即如果(0,0)是旋转中心,那么输出图像旋转中心同样是(0,0)。
- angle,旋转角度。角度 > 0,表示逆时针旋转(坐标原点是左上角)。
- scale,缩放系数。
进行仿射变换:warpAffine 函数
void warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags = INTER_LINEAR, int borderMode = BORDER_CONSTANT, const Scalar& boederValue = Scalar());
- src,输入图像,即原图像,填 Mat 类对象那个即可。
- dst,输出图像,需要和源图像有一样的类型。
- M,2×3 的变换矩阵。因为变换矩阵第三行形式固定,所以忽略。
- dsize,输出图像的尺寸。
- flags,插值的标识符。默认为 INTER_LINEAR (线性插值)。插值就是根据已知数据点(条件),来预测未知数据点值得方法。在尺寸调整过程中,图像的大小可能发生改变。此时像素与像素之间的关系就不是一一对应关系,因此在尺寸调整过程中,可能会涉及到像素值的插值计算。可选插值方式如下:
INTER_NEAREST(最近邻差值)
INTER_LINEAR(线性插值,默认)
INTER_AREA(区域插值,利用像素区域关系的重采样插值)
INTER_CUBIC(三次样条插值,超过 4×4 像素邻域内的双三次插值)
INTER_LANCZOS4(Lanczos 插值,超过 8×8 像素邻域的 Lanczos 插值)
- borderMode,边界扩展类型。默认值为 BORDER_CONSTANT,详解链接:https://www.cnblogs.com/bjxqmy/p/12306276.html
- borderValue ,只有当 borderMode取值为 BORDER_CONSTANT 时,这个参数才会被使用,边界会被填充成 borderValue 指定的颜色。
代码示例:
#include<opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main() {
Mat src = imread("C:/Users/齐明洋/Desktop/证件照/1.jpg");
imshow("src", src);
//旋转中心为图像中心
Point center = Point(src.cols / 2, src.rows / 2);
Mat M = getRotationMatrix2D(center, 45, 0.2);
Mat dst;
warpAffine(src, dst, M, src.size());
circle(dst, center, 2, Scalar(0, 0, 255), 3);
imshow("dst", dst);
waitKey(0);
}
效果演示:
借鉴博客:https://www.cnblogs.com/shine-lee/p/10950963.html
https://www.cnblogs.com/liekkas0626/p/5238564.html
https://www.cnblogs.com/houkai/p/6660272.html