简单来说,在平常的图像处理和机器视觉等应用中,几何变换通常是指不太复杂的线性几何变换,其中主要分仿射变换和投射变换。

许多常见的变换问题都能由仿射变换描述,仿射变换等式如下:

几何变换 -- 仿射变换

等式右边是变换前的图像坐标点,左边是变换后的图像坐标点。针对不同的变换问题,通过选择适当的变换对应点,解决这6个变换相关系数。

几何变换 -- 仿射变换

在OpenCV中,进行仿射变换可用warpAffine函数:

warpAffine(src_image, dst_image, affine_matrix, image.size());

以下是几种已知的仿射变换:

1)平移

几何变换 -- 仿射变换

平移变换矩阵是对角矩阵,因为变换前后不改变尺度。m,n分别表示沿水平方向和沿垂直方向进行平移,取值可正可负。

Mat trans_matrix = Mat::eye(2, 3, CV_32FC1);
*(((float*)(trans_matrix.data)) + 2) = 30;
warpAffine(image, dst_image, trans_matrix, image.size());

几何变换 -- 仿射变换几何变换 -- 仿射变换

*(((float*)(trans_matrix.data)) + 2) = 30;
*(((float*)(trans_matrix.data)) + 5) = 30;
warpAffine(image, dst_image, trans_matrix, image.size());

上面的代码是进行两个方向的平移,效果如下:

几何变换 -- 仿射变换

2)尺度缩放

几何变换 -- 仿射变换

a,b分别表示在水平和垂直方向的尺度缩放,只能取正值,取值大于1表示拉伸,取值小于1表示压缩。

Mat scale_matrix = Mat::zeros(2, 3, CV_32FC1);
*(((float*)(scale_matrix.data))) = 0.5;
*(((float*)(scale_matrix.data)) + 4) = 1.0;
warpAffine(image, dst_image, scale_matrix, image.size());
以上代码表示保持垂直方向不变,即不被压缩与拉伸,水平方向压缩到原来的一半:
几何变换 -- 仿射变换
混合使用平移和尺度缩放后的效果如下:
Mat scale_matrix = Mat::zeros(2, 3, CV_32FC1);
*(((float*)(scale_matrix.data))) = 0.5;
*(((float*)(scale_matrix.data)) + 4) = 1.0;
*(((float*)(scale_matrix.data)) + 2) = 30;
*(((float*)(scale_matrix.data)) + 5) = 30;
warpAffine(image, dst_image, scale_matrix, image.size());
几何变换 -- 仿射变换
3)旋转
几何变换 -- 仿射变换
上面的等式表示将图像绕原点旋转theta角,因为旋转会改变尺度,故仿射变换矩阵的对角元素不在为1。在OpenCV中theta应当为旋转的弧度角。
Mat rotation_mat = Mat::zeros(2, 3, CV_32FC1);
float THETA = -30.0*CV_PI/180.0;
float COS_THETA = cos(THETA);
float SIN_THETA = sin(THETA);
*(((float*)(rotation_mat.data))) = COS_THETA;
*(((float*)(rotation_mat.data)) + 1) = SIN_THETA;
*(((float*)(rotation_mat.data)) + 3) = -SIN_THETA;
*(((float*)(rotation_mat.data))+4) = COS_THETA;
warpAffine(image, dst_image, rotation_mat, image.size());
沿顺时针和逆时针旋转30度的效果如下:

几何变换 -- 仿射变换几何变换 -- 仿射变换
这里均忽略了变换后的图像坐标轴的对齐问题。

相关文章: