图像处理互联网@时事传播想法

【图像处理】OpenCV系列十六 --- 仿射变换warpAff

2019-04-29  本文已影响57人  307656af5a04

上一节我们学习了如何对一幅图像进行放大与缩小(resize函数)以及对插值算的原理进行了分析,相信大家对图像如何进行放大与缩小已经有了清晰的理解,那么我们这节学习OpenCV中比较重要的内容,即仿射变换(warpAffine),仿射变换可以实现对稍微倾斜的图片进行矫正哦!!那么接下来我们就正式进入仿射变换的学习吧!

一、原理

仿射变换的功能是从二维坐标到二维坐标之间的线性变换,且保持二维图形的“平直性”和“平行性”。仿射变换可以通过一系列的原子变换的复合来实现,包括平移,缩放,翻转,旋转和剪切。

这类变换可以用一个3*3的矩阵M来表示,其最后一行为(0,0,1)。该变换矩阵将原坐标为(x,y)变换为新坐标(x',y')

仿射变换

典型的仿射变换
1、平移
将每一点移到到(x+t , y+t),变换矩阵为

平移

2、缩放变换
将每一点的横坐标放大或缩小s_x倍,纵坐标放大(缩小)到s_y倍,变换矩阵为

缩放变换

3、旋转变换原点
目标图形围绕原点顺时针旋转Θ 弧度,变换矩阵为

旋转变换原点

4、旋转变换
目标图形以(x , y )为轴心顺时针旋转θ弧度,变换矩阵为

旋转变换

二、OpenCV中warpAffine()相关函数详解

(一)warpAffine()函数
1、函数原型

void warpAffine(InputArray src, 
    OutputArray dst,
    InputArray M, 
    Size dsize,
    int flags = INTER_LINEAR,
    int borderMode = BORDER_CONSTANT,
    const Scalar& borderValue = Scalar());

2、函数功能
对图像进行仿射变换,当函数的参数flags设置为 WARP_INVERSE_MAP时,函数使用下面的矩阵进行仿射变换:

仿射变换

否则,函数将首先使用逆仿射变换的转置,然后用上面的公式代替M,并且该函数不支持就地操作。

3、参数详解

4、实例

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

using namespace std;
using namespace cv;

//全局变量
String src_windowName = "原图像";
String warp_windowName = "仿射变换";
String warp_rotate_windowName = "仿射旋转变换";
String rotate_windowName = "图像旋转";

int main()
{
    Point2f srcTri[3];
    Point2f dstTri[3];

    Mat rot_mat(2, 3, CV_32FC1);
    Mat warp_mat(2, 3, CV_32FC1);
    Mat srcImage, warp_dstImage, 
        warp_rotate_dstImage, rotate_dstImage;

    //加载图像
    srcImage = imread("lena.png");

    //判断文件是否加载成功
    if (srcImage.empty())
    {
        cout << "图像加载失败!" << endl;
        return -1;
    }
    else
        cout << "图像加载成功!" << endl << endl;

    //创建仿射变换目标图像与原图像尺寸类型相同
    warp_dstImage = Mat::zeros(srcImage.rows, 
        srcImage.cols, srcImage.type());

    //设置三个点来计算仿射变换
    srcTri[0] = Point2f(0, 0);

    srcTri[1] = Point2f(srcImage.cols - 1, 0);

    srcTri[2] = Point2f(0, srcImage.rows - 1);

    dstTri[0] = Point2f(srcImage.cols*0.0, 
        srcImage.rows*0.33);

    dstTri[1] = Point2f(srcImage.cols*0.85, 
        srcImage.rows*0.25);

    dstTri[2] = Point2f(srcImage.cols*0.15, 
        srcImage.rows*0.7);

    //计算仿射变换矩阵
    warp_mat = getAffineTransform(srcTri, dstTri);

    //对加载图形进行仿射变换操作
    warpAffine(srcImage, warp_dstImage, 
        warp_mat, warp_dstImage.size());

    //计算图像中点顺时针旋转90度,缩放因子为0.6的旋转矩阵
    Point center = Point(warp_dstImage.cols / 2, 
        warp_dstImage.rows / 2);

    double angle = -90.0;
    double scale = 0.6;

    //计算旋转矩阵
    rot_mat = getRotationMatrix2D(center, angle, scale);

    //旋转已扭曲图像
    warpAffine(warp_dstImage, warp_rotate_dstImage, 
        rot_mat, warp_dstImage.size());

    //将原图像旋转
    warpAffine(srcImage, rotate_dstImage, 
        rot_mat, srcImage.size());

    //显示变换结果
    namedWindow(src_windowName, WINDOW_AUTOSIZE);

    imshow(src_windowName, srcImage);

    namedWindow(warp_windowName, WINDOW_AUTOSIZE);

    imshow(warp_windowName, warp_dstImage);

    namedWindow(warp_rotate_windowName, WINDOW_AUTOSIZE);

    imshow(warp_rotate_windowName, warp_rotate_dstImage);

    namedWindow(rotate_windowName, WINDOW_AUTOSIZE);

    imshow(rotate_windowName, rotate_dstImage);

    waitKey(0);

    return 0;
}

实验结果

原图
仿射变换、仿射旋转变换、图像旋转90度

(二)getAffineTransform()函数
1、函数原型

Mat getAffineTransform(const Point2f src[], 
    const Point2f dst[]);

2、函数功能
从三对相对应的点计算图像的仿射变换。

3、参数详解

(三)getRotationMatrix2D()函数
1、函数原型

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

2、函数功能
计算二维图像旋转的放射变换。

3、参数详解

三、综合实例

使用findTransformECC()函数实现图像对齐ECC算法

image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png

实验结果

实验结果

好了,今天的学习到这里就结束了,希望大家可以认真学习学习每一节知识,加油,相信大家可以的!喜欢的朋友也可以给我点个赞哦!!

上一篇下一篇

猜你喜欢

热点阅读