OpenCV每日函数 几何图像变换模块 (6) invertAffineTransform函数

一、概述

        逆转仿射变换。该函数计算由 2×3 矩阵 M 表示的逆仿射变换:

        结果也是一个与 M 相同类型的 2×3 矩阵。

二、invertAffineTransform函数

1、函数原型

cv::invertAffineTransform (InputArray M, OutputArray iM)

2、参数详解

M 原始仿射变换。
iM 输出反向仿射变换。

三、OpenCV源码 

1、源码路径

opencv\modules\imgproc\src\imgwarp.cpp

2、源码代码

void cv::invertAffineTransform(InputArray _matM, OutputArray __iM)
{
    Mat matM = _matM.getMat();
    CV_Assert(matM.rows == 2 && matM.cols == 3);
    __iM.create(2, 3, matM.type());
    Mat _iM = __iM.getMat();

    if( matM.type() == CV_32F )
    {
        const softfloat* M = matM.ptr<softfloat>();
        softfloat* iM = _iM.ptr<softfloat>();
        int step = (int)(matM.step/sizeof(M[0])), istep = (int)(_iM.step/sizeof(iM[0]));

        softdouble D = M[0]*M[step+1] - M[1]*M[step];
        D = D != 0. ? softdouble(1.)/D : softdouble(0.);
        softdouble A11 = M[step+1]*D, A22 = M[0]*D, A12 = -M[1]*D, A21 = -M[step]*D;
        softdouble b1 = -A11*M[2] - A12*M[step+2];
        softdouble b2 = -A21*M[2] - A22*M[step+2];

        iM[0] = A11; iM[1] = A12; iM[2] = b1;
        iM[istep] = A21; iM[istep+1] = A22; iM[istep+2] = b2;
    }
    else if( matM.type() == CV_64F )
    {
        const softdouble* M = matM.ptr<softdouble>();
        softdouble* iM = _iM.ptr<softdouble>();
        int step = (int)(matM.step/sizeof(M[0])), istep = (int)(_iM.step/sizeof(iM[0]));

        softdouble D = M[0]*M[step+1] - M[1]*M[step];
        D = D != 0. ? softdouble(1.)/D : softdouble(0.);
        softdouble A11 = M[step+1]*D, A22 = M[0]*D, A12 = -M[1]*D, A21 = -M[step]*D;
        softdouble b1 = -A11*M[2] - A12*M[step+2];
        softdouble b2 = -A21*M[2] - A22*M[step+2];

        iM[0] = A11; iM[1] = A12; iM[2] = b1;
        iM[istep] = A21; iM[istep+1] = A22; iM[istep+2] = b2;
    }
    else
        CV_Error( CV_StsUnsupportedFormat, "" );
}

四、效果图像示例

        下面代码展示了先计算变换矩阵,然后对RGB图像进行旋转,之后再求逆变换矩阵,之后再应用到已经旋转的图像上。

#include <opencv2\opencv.hpp>
using namespace cv;

int main()
{
    Mat3b RGBsrc = imread("path_to_image");
    double Angle = 30.0;

    // get rotation matrix for rotating the image around its center
    Point2f center22(RGBsrc.cols / 2.0, RGBsrc.rows / 2.0);
    Mat rot = getRotationMatrix2D(center22, Angle, 1.0);

    // determine bounding rectangle
    Rect bbox = RotatedRect(center22, RGBsrc.size(), Angle).boundingRect();

    // adjust transformation matrix
    rot.at<double>(0, 2) += bbox.width / 2.0 - center22.x;
    rot.at<double>(1, 2) += bbox.height / 2.0 - center22.y;
    Mat RotatedRGB;
    warpAffine(RGBsrc, RotatedRGB, rot, bbox.size());

    // Invert the affine transformation
    Mat rotInv;
    cv::invertAffineTransform(rot, rotInv);

    // Get back the original image
    Mat Rotatedback;
    warpAffine(RotatedRGB, Rotatedback, rotInv, Size(RGBsrc.cols, RGBsrc.rows));

    imshow("Original", RGBsrc);
    imshow("Rotated", RotatedRGB);
    imshow("Rotated Back", Rotatedback);
    waitKey();

    return 0;
}
原图

         代码首先定义了旋转矩阵rot,使用此矩阵对图像进行操作。

旋转后的图像

         接着我们还可以使用invertAffineTransform函数计算rot的逆矩阵,得到rotInv,然后对上面的旋转的图像进行操作,得到近乎于原始图片的结果。

经过逆矩阵变换的图像

 五、仿射变换相关参考

Opencv学习笔记 - 仿射变换/透视变换/对数极坐标变换_坐望云起的博客-CSDN博客_对数极坐标变换Opencv学习笔记 - 仿射变换/透视变换/对数极坐标变换https://skydance.blog.csdn.net/article/details/109705939Opencv学习笔记 常用函数、基础知识三 仿射变换_坐望云起的博客-CSDN博客仿射变换代表的是两幅图之间的关系。1、一个任意的仿射变换都能表示为 乘以一个矩阵 (线性变换) 接着再 加上一个向量 (平移).2、用仿射变换来处理,旋转 (线性变换),平移 (向量加),缩放操作 (线性变换)https://skydance.blog.csdn.net/article/details/108885176

猜你喜欢

转载自blog.csdn.net/bashendixie5/article/details/125261168
今日推荐