Opencv暑期历程--Day6 (仿射变换)

仿射变换介绍

仿射变换是指在向量空间中进行一次线性变换(乘以一个矩阵)并加上一个平移(加上一个向量),变换为另一个向量空间的过程。在有限维的情况下,每个仿射变换可以由一个矩阵A和一个向量b给出,它可以写作A和一个附加的列b。一个仿射变换对应于一个矩阵和一个向量的乘法,而仿射变换的复合对应于普通的矩阵乘法,只要加入一个额外的行到矩阵的底下,这一行全部是0除了最右边是一个1,而列向量的底下要加上一个1.
Affine Transform描述了一种二维仿射变换的功能,它是一种二维坐标之间的线性变换,保持二维图形的“平直性”(即变换后直线还是直线,圆弧还是圆弧)和“平行性”(其实是保持二维图形间的相对位置关系不变,平行线还是平行线,而直线上的点位置顺序不变,另特别注意向量间夹角可能会发生变化)。仿射变换可以通过一系列的原子变换的复合来实现包括:平移(Translation)、缩放(Scale)、翻转(Flip)、旋转(Rotation)和错切(Shear).
事实上,仿射变换代表的是两幅图之间的关系,我们通常使用2x3矩阵来表示仿射变换如下:
这里写图片描述

考虑到我们要使用矩阵A和B对二维向量这里写图片描述做变换,所以也能表示为下列形式:
这里写图片描述这里写图片描述
得到如下结果:
这里写图片描述

三种常见形式:

  • 旋转,rotation(线性变换)
  • 平移,translation(向量加)
  • 缩放,scale(线性变换)

现在有两幅图像(如下图),图像二是图像一经过放射变化得来的。那问题来了,我们怎么从这两个图像信息里挖掘出两图之间的映射关系?

很简单,只要在图像一种拿出三个点(1,2,3),图像二也拿出对应的三个点(1,2,3),就可以求出两图间的映射关系!

接下来用代码实现一下。

OpenCV通过两个函数的组合使用来实现仿射变换:

  • 使用warpAffine来实现简单重映射
  • 使用getRotationMatrix2D来获得旋转矩阵

warpAffine函数

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

参数解释
. src: 输入图像
. dst: 输出图像,尺寸由dsize指定,图像类型与原图像一致
. M: 2X3的变换矩阵
. dsize: 指定图像输出尺寸
. flags: 插值算法标识符,有默认值INTER_LINEAR,如果插值算法为WARP_INVERSE_MAP, warpAffine函数使用如下矩阵进行图像转换
这里写图片描述

 getRotationMatrix2D函数

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

参数解释
. center: Point2f类型,表示原图像的旋转中心
. angle: double类型,表示图像旋转角度,角度为正则表示逆时针旋转,角度为负表示逆时针旋转(坐标原点是图像左上角)
. scale: 缩放系数
函数计算如下矩阵:
这里写图片描述
其中
这里写图片描述

 那么好了,接下来我们就试试吧。

 Opencv里有两个方法,一个是用三点来确定变换矩阵,一种是直接指定旋转的角度和比例来确定变换矩阵。我个人觉得用第二种比较方便与直观。

 

// opencv_day6.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

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

using namespace std;
using namespace cv;
//仿射变换实验
int main()
{
	Mat src = imread("1.jpg");
	Mat dst_warp, dst_warpRotateScale;
	Point2f srcPoints[3];//原图中的三点  
	Point2f dstPoints[3];//目标图中的三点  

	//第一种仿射变换的调用方式:三点法
	//三个点对的值,上面也说了,只要知道你想要变换后图的三个点的坐标,就可以实现仿射变换  
	srcPoints[0] = Point2f(0, 0);
	srcPoints[1] = Point2f(0, src.rows - 1);
	srcPoints[2] = Point2f(src.cols - 1, 0);
	//映射后的三个坐标值
	dstPoints[0] = Point2f(0, src.rows*0.3);
	dstPoints[1] = Point2f(src.cols*0.25, src.rows*0.75);
	dstPoints[2] = Point2f(src.cols*0.75, src.rows*0.25);

	Mat M1 = getAffineTransform(srcPoints, dstPoints);//由三个点对计算变换矩阵  
	warpAffine(src, dst_warp, M1, src.size());//仿射变换  


	//第二种仿射变换的调用方式:直接指定角度和比例                                          
	//旋转加缩放  
	Point2f center(src.cols / 2, src.rows / 2);//旋转中心  
	double angle = 45;//逆时针旋转45度  
	double scale = 0.5;//缩放比例  

	Mat M2 = getRotationMatrix2D(center, angle, scale);//计算旋转加缩放的变换矩阵  
	warpAffine(src, dst_warpRotateScale, M2, src.size());//仿射变换  

	imshow("原始图", src);
	imshow("仿射变换1", dst_warp);
	imshow("仿射变换2", dst_warpRotateScale);
	waitKey(0);

	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值