• 《opencv学习笔记》-- 仿射变换


    仿射变换代表的是两幅图像之间的映射关系

    仿射变换是指在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间的过程。它保持了二维图形的“平直性”(即:直线经过变换之后依然是直线)和“平行性”(即:二维图形之间的相对位置关系保持不变,平行线依然是平行线,且直线上点的位置顺序不变)。

    一个任意的仿射变换都能表示为乘以一个矩阵(线性变换)接着再加上一个向量(平移)的形式   

    仿射变换三种常见的变换形式:

            旋转,rotation (线性变换)

            平移,translation(向量加)

            缩放,scale(线性变换)

    通常使用2 x 3的矩阵来表示仿射变换:

     

    仿射变换的求法:

    使用场景:

    <1> 已知 X和T,而且我们知道他们是有联系的,求出矩阵 M

    <2> 已知 M和X,求 T。用算式T = M·X. 对于这种联系的信息可以用矩阵 M 清晰的表达 (即给出明确的2×3矩阵) 或者也可以用两幅图片点之间几何关系来表达。

    矩阵M 联系着两幅图片,就以 其表示两图中各三 点直接的联系为例。

     

    图中,点1, 2,3与image2中的点一 一映射。
    1. void warpAffine(InputArray src, OutputArray dst, InputArray M,
    2. Size dsize, int flags = INTER_LINEAR,
    3. int borderMode = BORDER_CONSTANT,
    4. const Scalar& borderValue = Scalar())

    对图像做放射变换。

    dst(x, y) = src(M11x + M12y + M13,   M21x + M22y + M23)

    参数1,InputArray类型的src,源图像,Mat类的对象。

    参数2,运算结果,需和源图片有一样的尺寸和类型。

    参数3,InputArray类型的M,2×3的变换矩阵。

    参数4,Size类型的dsize,表示输出图像的尺寸。

    参数5,int类型的flags,插值方法的标识符。参数有默认值INTER_LINEAR(线性插值),可选的插值方式如下:

            INTER_NEAREST            最近邻插值

            INTER_LINEAR                线性插值(默认值)

            INTER_AREA                    区域插值

            INTER_CUBIC                   三次样条插值

            INTER_LANCZOS4            Lanczos插值

            WARP_FILL_OUTLIERS   填充所有输出图像的象素。 如果部分象素落在输入图像的边

                                                        界外,那么它们的值设定为 fillval.

            WARP_INVERSE_MAP    表示M为输出图像到输入图像的反变换,即 因此可以直接用

                                                      来做象素插值。否则, warpAffine函数从M矩阵得到反变换。

    参数6,int类型的borderMode,边界像素模式,默认值为BORDER_CONSTANT。

    参数7,在恒定的边界情况下取的值,默认值为Scalar(),即0。

    计算二维旋转变换矩阵。变换会将旋转中心映射到它自身:

    Mat getRotationMatrix2D(Point2f center, double angle, double scale)

    参数1,表示源图像的旋转中心。

    参数2,旋转角度。角度为正值表示向逆时针旋转(坐标原点是左上角)。

    参数3,缩放系数。

    计算二维三角变换矩阵

    Mat getAffineTransform( InputArray src, InputArray dst );

    参数1,InputArray类型的src,原来三个点的坐标;

    参数2,OutputArray类型的dst,映射后三个点的坐标;

    1. //定义两组点,代表两个三角形
    2. Point2f srcTriangle[3];
    3. Point2f dstTriangle[3];
    4. //定义一些Mat变量
    5. Mat rotMat(2, 3, CV_32FC1);
    6. Mat warpMat(2, 3, CV_32FC1);
    7. Mat srcImage, dstImage_warp, dstImage_warp_rotate;
    8. //加载源图像并作一些初始化
    9. srcImage = imread("1.jpg", 1);
    10. dstImage_warp = Mat::zeros(srcImage.rows, srcImage.cols, srcImage.type());
    11. //设置源图像和目标图像上的三组点以计算仿射变换
    12. srcTriangle[0] = Point2f(0, 0);
    13. srcTriangle[1] = Point2f(static_cast<float>(srcImage.cols - 1), 0);
    14. srcTriangle[2] = Point2f(0, static_cast<float>(srcImage.rows - 1));
    15. dstTriangle[0] = Point2f(static_cast<float>(srcImage.cols*0.0),
    16. static_cast<float> (srcImage.rows*0.33));
    17. dstTriangle[1] = Point2f(static_cast<float>(srcImage.cols*0.65),
    18. static_cast<float>(srcImage.rows*0.35));
    19. dstTriangle[2] = Point2f(static_cast<float>(srcImage.cols*0.15),
    20. static_cast<float>(srcImage.rows*0.6));
    21. //求得仿射变换
    22. warpMat = getAffineTransform(srcTriangle, dstTriangle);
    23. //对源图像应用求得的仿射变换
    24. warpAffine(srcImage, dstImage_warp, warpMat, dstImage_warp.size());
    25. //对图像进行缩放后再旋转
    26. // 计算绕图像中点顺时针旋转50度缩放因子为0.6的旋转矩阵
    27. Point center = Point(dstImage_warp.cols / 2, dstImage_warp.rows / 2);
    28. double angle = -30.0;
    29. double scale = 0.8;
    30. // 通过上面的旋转细节信息求得旋转矩阵
    31. rotMat = getRotationMatrix2D(center, angle, scale);
    32. // 旋转已缩放后的图像
    33. warpAffine(dstImage_warp, dstImage_warp_rotate, rotMat, dstImage_warp.size());

  • 相关阅读:
    如何在C#中解析Excel公式
    腾讯云入侵
    快速基于 ClickHouse + Grafana 搭建可观测性解决方案 - 分布式链路追踪篇(ClickHouse 官方博客)...
    ssm项目布置流程
    RPG Maker MV-场所移动
    【EDA课程设计】FPGA交通信号灯的设计(含动画视频、超详细思路/步骤分析、完整代码与效果详解)
    npm运行报错:无法加载文件 C:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本问题解决
    springboot+nodejs+vue+Elementui在线旅游管理系统
    ssl 层在握手阶段报错 mbedtls_ssl_handshake returned -0xffff8880
    leetcode 90 子集II
  • 原文地址:https://blog.csdn.net/qq_41653875/article/details/125985259