【C++】【Opencv】cv::warpAffine()仿射变换函数详解,实现平移、缩放和旋转等功能

这篇具有很好参考价值的文章主要介绍了【C++】【Opencv】cv::warpAffine()仿射变换函数详解,实现平移、缩放和旋转等功能。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

仿射变换是一种二维变换,它可以将一个二维图形映射到另一个二维图形上,保持了图形的“形状”和“大小”不变,但可能会改变图形的方向和位置。仿射变换可以用一个线性变换矩阵来表示,该矩阵包含了六个参数,可以进行平移、缩放、旋转等操作。通过原理、函数和示例进行解析,帮助大家理解和使用。

下面我们将依次实现平移、旋转、缩放和仿射变换等功能,使用C++语言和OpenCV库。

原理和函数

原理

cv.warpaffine,C、C++日常记录,c++,opencv,webpack,人工智能cv.warpaffine,C、C++日常记录,c++,opencv,webpack,人工智能
由于矩阵A的最后一行为(0,0,1),所以认为A是仿射变换矩阵,变换类型主要包括平移、缩放和旋转。

warpAffine()函数详解

warpAffine() 是 OpenCV 库中的一个函数,用于进行二维仿射变换。该函数将输入图像映射到输出图像,应用仿射变换。

函数原型如下:

void cv::warpAffine(InputArray src, OutputArray dst, InputArray mat, Size dsize = Size(), int flags = INTER_LINEAR, int borderMode = BORDER_CONSTANT, Scalar borderValue = Scalar());

参数详解:

src:输入图像,必须是单通道或三通道的8位或32位浮点型图像。
dst:输出图像,其大小和类型与输入图像相同。
mat:2x3的变换矩阵。
dsize:输出图像的大小,如果这个参数为 Size() ,则输出图像的大小将与输入图像相同。
flags:用于指定插值的方法,默认为线性插值。可用的选项有 INTER_NEAREST, INTER_LINEAR, INTER_CUBIC 等。
borderMode:用于指定如何处理输出图像边缘的像素,默认为常量填充模式。可用的选项有 BORDER_CONSTANT, BORDER_REPLICATE, BORDER_WRAP 等。
borderValue:用于指定填充的边界值,默认为0。

这个函数使用仿射变换来将输入图像映射到输出图像。仿射变换包括旋转、缩放、平移等操作,但不包括扭曲和剪切。这个函数非常有用,特别是在需要将图像映射到另一个大小或以特定方式旋转或倾斜图像时。

示例

平移

原理

平移变换可以用一个3x3的变换矩阵来表示,其中第一行和第二行表示原始图像的行向量和列向量,第三行表示变换后的行向量和列向量,和原理部分类似,但有些版本只需要设置一个2x3的变换矩阵即可,可以省略第三行。在本例中,即定义的是2x3的变换矩阵,我们将原始图像向右移动100个像素,向下移动300个像素。其中,数值为正,则向正方向移,数值为负,则向反向相移。
cv.warpaffine,C、C++日常记录,c++,opencv,webpack,人工智能
如上述矩阵转换矩阵,只需要设置第一行的第三个元素tx和第二行第三列的ty即可,体现在2行3列的矩阵中如下面运行示例中的100和300所示。

运行示例

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
    Mat src = imread("ceshi.jpg");
    if (src.empty()) {
        cout << "Could not read the source image" << endl;
        return -1;
    }

    Mat trans_mat = (Mat_<double>(2, 3) << 1, 0, 100, 0, 1, 300);
    Mat dst;
    warpAffine(src, dst, trans_mat, src.size());
    imshow("Source Image", src);
    imshow("Affine Transformed Image", dst);
    imwrite("pingyi.jpg", dst);
    waitKey(0);
    return 0;
}

在代码中,Mat trans_mat = (Mat_<double>(2, 3) << 1, 0, 100, 0, 1, 300);是定义的一个2行3列的转换矩阵,第一行是右移100,第二行是下移300。最后,我们使用warpAffine()函数进行仿射变换,将原始图像映射到输出图像中,并显示原始图像和变换后的图像。运行可以看到相应的效果,如下图所示。
cv.warpaffine,C、C++日常记录,c++,opencv,webpack,人工智能
上面为原图,下面为平移后的图像。
cv.warpaffine,C、C++日常记录,c++,opencv,webpack,人工智能

缩放

原理

仿射变换中的缩放指的是对图像进行等比例的放大或缩小。在仿射变换矩阵中,可以通过设置第一行和第二行的元素来控制缩放。
cv.warpaffine,C、C++日常记录,c++,opencv,webpack,人工智能
由上面的平移可知,第一行第三列和第二行第三列的数值是控制平移的,在此处可知,第一行第一列和第二行第二列是用于控制x轴和y轴的缩放比例的,在下面的运行示例中也可以看出缩放因子在的位置与此相对应。

缩小示例

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
    Mat src = imread("ceshi.jpg");
    if (src.empty()) {
        cout << "Could not read the source image" << endl;
        return -1;
    }

    // 设置缩放比例
    double scale = 0.5;

    // 计算缩放矩阵
    Mat scale_mat = (Mat_<double>(2, 3) << scale, 0, 0, 0, scale, 0);

    // 进行仿射变换
    Mat dst;
    warpAffine(src, dst, scale_mat, src.size());

    // 显示原始图像和变换后的图像
    imshow("Source Image", src);
    imshow("Affine Transformed Image", dst);
    imwrite("suoxiao.jpg", dst);
    waitKey(0);
    return 0;
}

在上面的代码中,我们首先读取一张名为“ceshi.jpg”的图像,然后设置缩放比例为0.5。接着,我们计算缩放矩阵,其中第一行和第二行的前两个元素分别表示水平方向和垂直方向的缩放比例,第三行和第四行的前两个元素为0,表示不进行平移操作。最后,我们使用warpAffine()函数进行仿射变换,将原始图像映射到输出图像中,并显示原始图像和变换后的图像。变换后的效果如下图所示。
cv.warpaffine,C、C++日常记录,c++,opencv,webpack,人工智能

放大示例

此处,我们把缩放因子设置为1.5,即放大,

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
    Mat src = imread("ceshi.jpg");
    if (src.empty()) {
        cout << "Could not read the source image" << endl;
        return -1;
    }

    // 设置缩放比例
    double scale = 1.5;

    // 计算缩放矩阵
    Mat scale_mat = (Mat_<double>(2, 3) << scale, 0, 0, 0, scale, 0);

    // 进行仿射变换
    Mat dst;
    warpAffine(src, dst, scale_mat, src.size());

    // 显示原始图像和变换后的图像
    imshow("Source Image", src);
    imshow("Affine Transformed Image", dst);
    imwrite("fangda.jpg", dst);
    waitKey(0);
    return 0;
}

放大的效果如下图所示。
cv.warpaffine,C、C++日常记录,c++,opencv,webpack,人工智能
相当于把图像一部分放大,但显示的内容比原图就少了很多,因为图像的总体大小没有改变。

旋转

原理

cv.warpaffine,C、C++日常记录,c++,opencv,webpack,人工智能
cv.warpaffine,C、C++日常记录,c++,opencv,webpack,人工智能

此处,以原点(0,0)坐标为中心进行,α 是旋转角度。
旋转矩阵的元素是由旋转角度和旋转中心计算得出的。假设我们有一个二维坐标系,其中原点是旋转中心,x轴正方向是右方,y轴正方向是上方。现在我们要将点 (x, y) 绕原点逆时针旋转θ角度,那么旋转矩阵可以表示为:

[ cosα, -sinα, 0 ]
[ sinα,  cosα, 0 ]
其中,cosθ 和 sinθ 是使用弧度值计算得出的。

也可以是如下公式:
cv.warpaffine,C、C++日常记录,c++,opencv,webpack,人工智能

若为上述A变换矩阵,则当α 为正时,旋转方向为顺时针;当 α 为负时,旋转方向为逆时针。
同时,另外一种情况与此相反,如变换矩阵为:

[ cosα, sinα, 0 ]
[ -sinα,  cosα, 0 ]

cv.warpaffine,C、C++日常记录,c++,opencv,webpack,人工智能
则当α 为正时,旋转方向为逆时针;当 α 为负时,旋转方向为顺时针。
此外,也可以控制α 的值,如α 为45和为-45逆顺情况是相反的。

下面进行两个示例,分别进行顺时针和逆时针旋转。

顺时针示例

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
    Mat src = imread("ceshi.jpg");
    if (src.empty()) {
        cout << "Could not read the source image" << endl;
        return -1;
    }

    // 设置旋转角度
    double angle = 45;

    // 计算旋转矩阵
    Mat rot_mat = (Mat_<double>(2, 3) << cos(angle), -sin(angle), sin(angle), cos(angle), 1, 0);
    cout<< cos(angle) <<endl;
    cout << -sin(angle) << endl;
    cout << sin(angle) << endl;
    //rot_mat = rot_mat * 100; // 设置旋转中心点,这里将图像中心设置为旋转中心

    // 进行仿射变换
    Mat dst;
    warpAffine(src, dst, rot_mat, src.size());

    // 显示原始图像和变换后的图像
    imshow("Source Image", src);
    imshow("Affine Transformed Image", dst);
    imwrite("shunshizhen.jpg", dst);

    waitKey(0);
    return 0;
}

上述代码中设置的double angle = 45;为旋转角度,45为正数,所以是逆时针旋转,同时,(Mat_<double>(2, 3) << cos(angle), -sin(angle), sin(angle), cos(angle), 1, 0);转换矩阵表示当α 为正时,旋转方向为顺时针;当 α 为负时,旋转方向为逆时针。
旋转结果为:
cv.warpaffine,C、C++日常记录,c++,opencv,webpack,人工智能

逆时针示例

(1)通过改变 α的值,如将上面顺时针的45变为-45.
(2)改变变换矩阵的顺序,如使用Mat rot_mat = (Mat_<double>(2, 3) << cos(angle), sin(angle), -sin(angle), cos(angle), 1, 0);替换上面代码中的转换矩阵。
以原点(0,0)为中心,逆时针旋转45度效果图如下:
cv.warpaffine,C、C++日常记录,c++,opencv,webpack,人工智能

总结

我们可以看出,在使用warpAffine()函数是比较方便的,通过使用定义2行3列和通过上面的例子,可以快速高效的实现平移、缩放和旋转等功能。文章来源地址https://www.toymoban.com/news/detail-751793.html

到了这里,关于【C++】【Opencv】cv::warpAffine()仿射变换函数详解,实现平移、缩放和旋转等功能的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【OpenCV • c++】图像几何变换 | 图像仿射变换

    🚀 个人简介:CSDN「 博客新星 」TOP 10 , C/C++ 领域新星创作者 💟 作    者: 锡兰_CC ❣️ 📝 专    栏: 【OpenCV • c++】计算机视觉 🌈 若有帮助,还请 关注➕点赞➕收藏 ,不行的话我再努努力💪💪💪

    2024年02月16日
    浏览(25)
  • 【C++ OpenCV】图像变换:连接、尺寸、翻转、旋转、仿射变换

    目录 图像缩放变换 图像翻转 图像拼接 纵向拼接 横向拼接 图像插值原理 作用 单线性插值 双线性插值的公式 双线性插值的例子 双线性插值的直观展示 意义 仿射变换 图像旋转 实操 一、实现图像旋转 二、根据定义的三个点实现仿射变换,并且求取仿射变换矩阵 源码 src -

    2024年01月18日
    浏览(31)
  • OPENCV C++(六)canny边缘检测+仿射变换+透射变换

    图像的缩放  输入图像 输出图像 大小变换 canny边缘算子的使用  必须先转化为灰度图,作为输入 超过100是真的边缘 低于40是确定不是边缘 在中间若连接边缘 则为边缘  普通旋转缩放变换(仿射变换) 获取仿射变换的矩阵 中心点 旋转角度 大小是否变换 -10是顺时针转 输入

    2024年02月14日
    浏览(35)
  • opencv实现仿射变换和透射变换

    OpenCV中的仿射变换和透视变换是常用的图像几何变换方法,可以用于实现图像的旋转、缩放、平移、扭曲等操作。这两种变换方式在计算机视觉、图像处理以及计算机图形学等领域广泛应用。 仿射变换 仿射变换是一种保持直线平行性质的线性变换,它可以对图像进行平移、

    2024年02月07日
    浏览(28)
  • OpenCV中关于二维仿射变换函数estimateAffinePartial2D的源码分析

    关于二维仿射变化的介绍:https://www.cnblogs.com/yinheyi/p/6148886.html OpenCV3.4.1 中提供的接口为:estimateAffinePartial2D(),用于计算两个2D点集之间具有4个自由度的最优有限仿射变换。 其函数具体实现位于: ./opencv/sources/modules/calib3d/src/ptsetreg.cpp 函数原型: 函数具体实现: 数据准备工

    2024年02月08日
    浏览(25)
  • 【CV & Unity】仿射变换原理

    仿射变换(Affine Transformation)是空间直角坐标系的变换,从一个二维坐标变换到另一个二维坐标,仿射变换是一个线性变换,他保持了图像的“平行性”和“平直性”,即图像中原来的直线和平行线,变换后仍然保持原来的直线和平行线,仿射变换比较常用的特殊变换有平移

    2024年02月07日
    浏览(20)
  • 【C++】【Opencv】cv::Canny()边缘检测函数详解和示例

    Canny边缘检测是一种流行的边缘检测算法,由John F. Canny在1986年开发。它是一种多阶段过程,包括噪声滤波、计算图像强度的梯度、非最大值抑制以及双阈值检测。本文通过函数原型解读和示例对cv::Canny()函数进行详解,以帮助大家理解和使用。 Canny边缘检测的步骤如下: (

    2024年02月04日
    浏览(35)
  • 【C++】【Opencv】cv::GaussianBlur、cv::filter2D()函数详解和示例

    本文通过函数详解和运行示例对cv::GaussianBlur和cv::filter2D()两个函数进行解读,最后综合了两个函数的关系和区别,以帮助大家理解和使用。 cv::GaussianBlur 是 OpenCV 库中的一个函数,用于对图像进行高斯模糊。高斯模糊是一种常见的图像降噪技术,它通过使用高斯函数对图像进

    2024年02月04日
    浏览(26)
  • opencv-26 图像几何变换04- 重映射-函数 cv2.remap()

    重映射(Remapping)是图像处理中的一种操作,用于将图像中的像素从一个位置映射到另一个位置。重映射可以实现图像的平移、旋转、缩放和透视变换等效果。它是一种基于像素级的图像变换技术,可以通过定义映射关系来改变图像的几何形状和外观。 在重映射中,我们需要

    2024年02月15日
    浏览(27)
  • 【opencv】几何变换——仿射变换(4 计算仿射矩阵getAffineTransform(src, ds)

    对于空间变换的仿射矩阵有两种计算方式: 仿射变换矩阵有六个未知数,需要三组对应位置坐标,构造出由六个方程组成的方程组即可解六个未知数; 函数getAffineTransform();通过方程法计算参数src到dst的对应仿射变换矩阵; 头文件:#includeopencv2/imgproc.hpp 函数getAffineTransform()输

    2024年02月12日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包