仿射变换算法_相似变换与仿射变换的区别

仿射变换算法_相似变换与仿射变换的区别仿射变换(AffineTransformation)原理及应用文章目录1什么是仿射变换2仿射变换数学表达3仿射变换理解3.1平移变换3.2反射变换3.3旋转变换3.4opencv中的仿射矩

仿射变换(Affine Transformation)原理及应用

1 什么是仿射变换

  • 仿射变换(Affine Transformation)其实是另外两种简单变换的叠加:一个是线性变换,一个是平移变换

  • 仿射变换变化包括缩放(Scale、平移(transform)、旋转(rotate)、反射(reflection,对图形照镜子)、错切(shear mapping,感觉像是一个图形的倒影),原来的直线仿射变换后还是直线,原来的平行线经过仿射变换之后还是平行线,这就是仿射

  • 仿射变换中集合中的一些性质保持不变:
    (1)凸性
    (2)共线性:若几个点变换前在一条线上,则仿射变换后仍然在一条线上
    (3)平行性:若两条线变换前平行,则变换后仍然平行
    (4)共线比例不变性:变换前一条线上两条线段的比例,在变换后比例不变

2 仿射变换数学表达

一个集合 XX 的仿射变换为:
f ( x ) = A x + b , x ∈ X f(x)=Ax+b, \quad x\in X f(x)=Ax+b,xX

仿射变换是二维平面中一种重要的变换,在图像图形领域有广泛的应用,在二维图像变换中,一般表达为:
[ x ′ y ′ 1 ] = [ R 00 R 01 T x R 10 R 11 T y 0 0 1 ] [ x y 1 ] \begin{bmatrix} x' \\ y' \\ 1 \\ \end{bmatrix}= \begin{bmatrix} R_{00}&R_{01}&T_x \\ R_{10}&R_{11}&T_y \\ 0& 0& 1 \\ \end{bmatrix} \begin{bmatrix} x \\ y \\ 1 \\ \end{bmatrix} xy1=R00R100R01R110TxTy1xy1

可以视为线性变换R和平移变换T的叠加

3 仿射变换理解

要熟练应用仿射变换,则需先理解仿射变换,说白了就是要弄清楚上面的R,T矩阵各个参数代表什么含义,用图像来表达:




在这里插入图片描述

3.1 平移变换

不难想象,就是将x,y平移指定值,则R矩阵为单位矩阵,T矩阵为指定值,如上图中,第一行第二列图
M = [ 1 0 T x 0 1 T y 0 0 1 ] M=\begin{bmatrix} 1&0&T_x \\ 0&1&T_y \\ 0& 0& 1 \\ \end{bmatrix} M=100010TxTy1

3.2 反射变换

见图最后一行,如相对x轴放射,则x不变,y变为相反号
M = [ 1 0 0 0 − 1 0 0 0 1 ] M=\begin{bmatrix} 1&0&0 \\ 0&-1&0 \\ 0& 0& 1 \\ \end{bmatrix} M=100010001

3.3 旋转变换

关于旋转矩阵,这里详细来看看,网上博客中,有朋友在疑惑旋转矩阵中, s i n θ sin\theta sinθ的负号位置问题,下面我谈谈我个人想法,若有错误请大家指点。为简单起见,只从一个点的旋转来看

(1) 左下角为坐标原点




在这里插入图片描述

  • 坐标原点为左下角
  • P ( x , y ) P(x,y) P(x,y)为坐标系中一个点,与x轴的夹角为 α \alpha α,假设其到原点的距离为1(方便计算)
  • P ′ ( x ′ , y ′ ) P'(x',y') P(x,y)为P点逆时针旋转 θ \theta θ角度的点
  • P ′ ′ ( x ′ ′ , y ′ ′ ) P''(x'',y'') P(x,y)为P点顺时针旋转 θ \theta θ角度的点

根据简单三角关系,可知
{ x = c o s α y = s i n α \begin{cases} x = cos\alpha\\ y = sin\alpha \end{cases} {
x=cosαy=sinα

逆时针时:
{ x ′ = c o s ( α + θ ) = c o s α ∗ c o s θ − s i n α ∗ s i n θ = x ∗ c o s θ − y ∗ s i n θ y ′ = s i n ( α + θ ) = s i n α ∗ c o s θ + c o s α ∗ s i n θ = y ∗ c o s θ + x ∗ s i n θ \begin{cases} x' = cos(\alpha + \theta) = cos\alpha * cos\theta – sin\alpha*sin\theta = x* cos\theta – y*sin\theta \\ y' = sin(\alpha + \theta) = sin\alpha * cos\theta + cos\alpha*sin\theta = y* cos\theta + x*sin\theta \end{cases} {
x=cos(α+θ)=cosαcosθsinαsinθ=xcosθysinθy=sin(α+θ)=sinαcosθ+cosαsinθ=ycosθ+xsinθ

则,逆时针旋转矩阵 R ′ R' R为:
R ′ = [ c o s θ − s i n θ s i n θ c o s θ ] R'= \begin{bmatrix} cos\theta&-sin\theta\\ sin\theta&cos\theta\\ \end{bmatrix} R=[cosθsinθsinθcosθ]

顺时针时:
{ x ′ ′ = c o s ( α − θ ) = c o s α ∗ c o s θ + s i n α ∗ s i n θ = x ∗ c o s θ + y ∗ s i n θ y ′ ′ = s i n ( α − θ ) = s i n α ∗ c o s θ − c o s α ∗ s i n θ = y ∗ c o s θ − x ∗ s i n θ \begin{cases} x'' = cos(\alpha – \theta) = cos\alpha * cos\theta + sin\alpha*sin\theta = x* cos\theta + y*sin\theta \\ y'' = sin(\alpha – \theta) = sin\alpha * cos\theta – cos\alpha*sin\theta = y* cos\theta – x*sin\theta \end{cases} {
x=cos(αθ)=cosαcosθ+sinαsinθ=xcosθ+ysinθy=sin(αθ)=sinαcosθcosαsinθ=ycosθxsinθ

则,顺时针旋转矩阵 R ′ ′ R'' R为:
R ′ ′ = [ c o s θ s i n θ − s i n θ c o s θ ] R''= \begin{bmatrix} cos\theta&sin\theta\\ -sin\theta&cos\theta\\ \end{bmatrix} R=[cosθsinθsinθcosθ]

从上可以看出,这个负号位置问题,个人认为与旋转方向相关

(2)左上角为坐标原点




在这里插入图片描述

  • 坐标原点为左上角
  • P ( x , y ) P(x,y) P(x,y)为坐标系中一个点,与x轴的夹角为 α \alpha α,假设其到原点的距离为1(方便计算)
  • P ′ ( x ′ , y ′ ) P'(x',y') P(x,y)为P点逆时针旋转 θ \theta θ角度的点
  • P ′ ′ ( x ′ ′ , y ′ ′ ) P''(x'',y'') P(x,y)为P点顺时针旋转 θ \theta θ角度的点

根据简单三角关系,可知
{ x = c o s α y = s i n α \begin{cases} x = cos\alpha\\ y = sin\alpha \end{cases} {
x=cosαy=sinα

逆时针时:
{ x ′ = c o s ( α − θ ) = c o s α ∗ c o s θ + s i n α ∗ s i n θ = x ∗ c o s θ + y ∗ s i n θ y ′ = s i n ( α − θ ) = s i n α ∗ c o s θ − c o s α ∗ s i n θ = y ∗ c o s θ − x ∗ s i n θ \begin{cases} x' = cos(\alpha – \theta) = cos\alpha * cos\theta + sin\alpha*sin\theta = x* cos\theta + y*sin\theta \\ y' = sin(\alpha – \theta) = sin\alpha * cos\theta – cos\alpha*sin\theta = y* cos\theta – x*sin\theta \end{cases} {
x=cos(αθ)=cosαcosθ+sinαsinθ=xcosθ+ysinθy=sin(αθ)=sinαcosθcosαsinθ=ycosθxsinθ

则,逆时针旋转矩阵 R ′ R' R为:
R ′ = [ c o s θ s i n θ − s i n θ c o s θ ] R'= \begin{bmatrix} cos\theta&sin\theta\\ -sin\theta&cos\theta\\ \end{bmatrix} R=[cosθsinθsinθcosθ]

顺时针时:
{ x ′ ′ = c o s ( α + θ ) = c o s α ∗ c o s θ − s i n α ∗ s i n θ = x ∗ c o s θ − y ∗ s i n θ y ′ ′ = s i n ( α + θ ) = s i n α ∗ c o s θ + c o s α ∗ s i n θ = y ∗ c o s θ + x ∗ s i n θ \begin{cases} x'' = cos(\alpha + \theta) = cos\alpha * cos\theta – sin\alpha*sin\theta = x* cos\theta – y*sin\theta \\ y'' = sin(\alpha + \theta) = sin\alpha * cos\theta + cos\alpha*sin\theta = y* cos\theta + x*sin\theta \end{cases} {
x=cos(α+θ)=cosαcosθsinαsinθ=xcosθysinθy=sin(α+θ)=sinαcosθ+cosαsinθ=ycosθ+xsinθ

则,顺时针旋转矩阵 R ′ ′ R'' R为:
R ′ ′ = [ c o s θ − s i n θ s i n θ c o s θ ] R''= \begin{bmatrix} cos\theta&-sin\theta\\ sin\theta&cos\theta\\ \end{bmatrix} R=[cosθsinθsinθcosθ]

从上可以看出,这个负号位置问题,不但与旋转方向有关,还与原点有关

(3)总结

  • 旋转矩阵R中, s i n θ sin\theta sinθ的负号位置与旋转方向和原点相关
  • 当记逆时针为正,左上角为原点时(opencv默认),旋转矩阵为:
    R = [ c o s θ s i n θ − s i n θ c o s θ ] R= \begin{bmatrix} cos\theta&sin\theta\\ -sin\theta&cos\theta\\ \end{bmatrix} R=[cosθsinθsinθcosθ]

3.4 opencv中的仿射矩阵

getRotationMatrix2D函数

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

该函数是来计算仿射矩阵:

[ α β ( 1 − α ) ⋅ center.x − β ⋅ center.y − β α β ⋅ center.x + ( 1 − α ) ⋅ center.y ] \begin{bmatrix} \alpha & \beta & (1- \alpha ) \cdot \texttt{center.x} – \beta \cdot \texttt{center.y} \\ – \beta & \alpha & \beta \cdot \texttt{center.x} + (1- \alpha ) \cdot \texttt{center.y} \end{bmatrix} [αββα(1α)center.xβcenter.yβcenter.x+(1α)center.y]

其中

α = scale ⋅ cos ⁡ angle , β = scale ⋅ sin ⁡ angle \begin{array}{l} \alpha = \texttt{scale} \cdot \cos \texttt{angle} , \\ \beta = \texttt{scale} \cdot \sin \texttt{angle} \end{array} α=scalecosangle,β=scalesinangle

  • center:源图旋转中心

  • angle: 旋转角度,用角度表示;逆时针旋转为正(坐标原点设为左上角)

     Rotation angle in degrees. 
     Positive values mean counter-clockwise rotation (thecoordinate origin is assumed to be the top-left corner).
    
  • scale:各向同比缩放因子

  • 源码

     	cv::Mat cv::getRotationMatrix2D( Point2f center, double angle, double scale )
     	{
     	    CV_INSTRUMENT_REGION();
     	
     	    angle *= CV_PI/180;
     	    double alpha = std::cos(angle)*scale;
     	    double beta = std::sin(angle)*scale;
     	
     	    Mat M(2, 3, CV_64F);
     	    double* m = M.ptr<double>();
     	
     	    m[0] = alpha;
     	    m[1] = beta;
     	    m[2] = (1-alpha)*center.x - beta*center.y;
     	    m[3] = -beta;
     	    m[4] = alpha;
     	    m[5] = beta*center.x + (1-alpha)*center.y;
     	
     	    return M;
     	}
    
  • 矩阵由来:首先将轴心(x,y)移到原点,然后做旋转缩放变换,最后再将图像的左上角转换为原点
    M = [ 1 0 x 0 1 y 0 0 1 ] [ c o s θ s i n θ 0 − s i n θ c o s θ 0 0 0 1 ] [ s 0 0 0 s 0 0 0 1 ] [ 1 0 − x 0 1 − y 0 0 1 ] M= \begin{bmatrix} 1 &amp; 0 &amp;x \\ 0&amp;1 &amp; y\\ 0&amp; 0 &amp;1 \end{bmatrix} \begin{bmatrix} cos\theta &amp;sin\theta &amp;0 \\ -sin\theta &amp; cos\theta &amp; 0\\ 0 &amp; 0 &amp; 1 \end{bmatrix} \begin{bmatrix} s &amp; 0 &amp; 0\\ 0&amp;s &amp; 0\\ 0 &amp;0 &amp; 1 \end{bmatrix} \begin{bmatrix} 1 &amp; 0 &amp; -x\\ 0 &amp; 1 &amp;-y \\ 0&amp; 0 &amp; 1 \end{bmatrix} M=100010xy1cosθsinθ0sinθcosθ0001s000s0001100010xy1

4 参考文献

[1]仿射变换详解 warpAffine :https://www.cnblogs.com/dupuleng/articles/4055020.html
[2]仿射变换(Affine transformation): https://blog.csdn.net/robert_chen1988/article/details/80498805
[3]opencv学习(三十五)之仿射变换warpAffine: https://blog.csdn.net/keith_bb/article/details/56331356

今天的文章仿射变换算法_相似变换与仿射变换的区别分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/73991.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注