热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Matrix学习——基础知识

以前在线性代数中学习了矩阵,对矩阵的基本运算有一些了解,前段时间在使用GDI+的时候再次学习如何使用矩阵来变化图像,看了之后在这里总结说明。首先大家看看下面这个3x3的矩阵,这个矩阵被分割

以前在线性代数中学习了矩阵,对矩阵的基本运算有一些了解,前段时间在使用GDI+的时候再次学习如何使用矩阵来变化图像,看了之后在这里总结说明。

首先大家看看下面这个3 x 3的矩阵,这个矩阵被分割成4部分。为什么分割成4部分,在后面详细说明。

首先给大家举个简单的例子:现设点P0(x0, y0)进行平移后,移到P(x,y),其中x方向的平移量为△x,y方向的平移量为△y,那么,点P(x,y)的坐标为:

x = x0  + △x
y = y0  + △y

采用矩阵表达上述如下:
clip_image002

上述也类似与图像的平移,通过上述矩阵我们发现,只需要修改矩阵右上角的2个元素就可以了。

我们回头看上述矩阵的划分:
clip_image003

为了验证上面的功能划分,我们举个具体的例子:现设点P0(x0 ,y0)进行平移后,移到P(x,y),其中x放大a倍,y放大b倍,

矩阵就是:clip_image004,按照类似前面“平移”的方法就验证。

图像的旋转稍微复杂:现设点P0(x0, y0)旋转θ角后的对应点为P(x, y)。通过使用向量,我们得到如下:

x0 = r cosα
y0 = r sinα

x = r cos(α+θ) = x0 cosθ - y0 sinθ
y = r sin(α+θ) = x0 sinθ + y0 cosθ

于是我们得到矩阵:clip_image005

如果图像围绕着某个点(a ,b)旋转呢?则先要将坐标平移到该点,再进行旋转,然后将旋转后的图像平移回到原来的坐标原点,在后面的篇幅中我们将详细介绍。

  Matrix学习——如何使用Matrix

上一篇幅 Matrix学习——基础知识,从高等数学方面给大家介绍了Matrix,本篇幅我们就结合Android 中的android.graphics.Matrix来具体说明,还记得我们前面说的图像旋转的矩阵:

clip_image005[1]

从最简单的旋转90度的是:

clip_image006

在android.graphics.Matrix中有对应旋转的函数:
Matrix matrix = new Matrix();
matrix.setRotate(90);
Test.Log(MAXTRIX_TAG,”setRotate(90):%s” , matrix.toString());

clip_image007

查看运行后的矩阵的值(通过Log输出):

clip_image008

与上面的公式基本完全一样(android.graphics.Matrix采用的是浮点数,而我们采用的整数)。

有了上面的例子,相信大家就可以亲自尝试了。通过上面的例子我们也发现,我们也可以直接来初始化矩阵,比如说要旋转30度:

clip_image010

前面给大家介绍了这么多,下面我们开始介绍图像的镜像,分为2种:水平镜像、垂直镜像。先介绍如何实现垂直镜像,什么是垂直镜像就不详细说明。图像的垂直镜像变化也可以用矩阵变化的表示,设点P0(x0 ,y0 )进行镜像后的对应点为P(x ,y ),图像的高度为fHeight,宽度为fWidth,原图像中的P0(x0 ,y0 )经过垂直镜像后的坐标变为(x0 ,fHeight- y0);
x = x0
y = fHeight – y0
推导出相应的矩阵是:

clip_image011

finalfloatf[] = {1.0F,0.0F,0.0F,0.0F,-1.0F,120.0F,0.0F,0.0F,1.0F};
Matrix matrix = newMatrix();
matrix.setValues(f);

按照上述方法运行后的结果:
clip_image012

至于水平镜像采用类似的方法,大家可以自己去试试吧。

实际上,使用下面的方式也可以实现垂直镜像:
Matrix matrix = newMatrix();
matrix.setScale (1.0,-1.0);
matrix.postTraslate(0, fHeight);

这就是我们将在后面的篇幅中详细说明。

  Matrix学习——图像的复合变化

Matrix学习——基础知识篇幅中,我们留下一个话题:如果图像围绕着某个点P(a,b)旋转,则先要将坐标系平移到该点,再进行旋转,然后将旋转后的图像平移回到原来的坐标原点。

我们需要3步:

1. 平移——将坐标系平移到点P(a,b);

2. 旋转——以原点为中心旋转图像;

3. 平移——将旋转后的图像平移回到原来的坐标原点;

相比较前面说的图像的几何变化(基本的图像几何变化),这里需要平移——旋转——平移,这种需要多种图像的几何变化就叫做图像的复合变化。

设对给定的图像依次进行了基本变化F1、F2、F3…..、Fn,它们的变化矩阵分别为T1、T2、T3…..、Tn,图像复合变化的矩阵T可以表示为:T = TnTn-1…T1。

按照上面的原则,围绕着某个点(a,b)旋转θ的变化矩阵序列是:

clip_image013

按照上面的公式,我们列举一个简单的例子:围绕(100,100)旋转30度(sin 30 = 0.5 ,cos 30 = 0.866)
float f[]= { 0.866F,  -0.5F, 63.4F,0.5F, 0.866F,-36.6F,0.0F,    0.0F,  1.0F };
matrix = new Matrix();
matrix.setValues(f);
旋转后的图像如下:

clip_image014

Android为我们提供了更加简单的方法,如下:
Matrix matrix = new Matrix();
matrix.setRotate(30,100,100);
矩阵运行后的实际结果:
clip_image015
与我们前面通过公式获取得到的矩阵完全一样。

在这里我们提供另外一种方法,也可以达到同样的效果:
float a = 100.0F,b = 100.0F;
matrix = new Matrix();
matrix.setTranslate(a,b);
matrix.preRotate(30);
matrix.preTranslate(-a,-b);
将在后面的篇幅中为大家详细解析

通过类似的方法,我们还可以得到:相对点P(a,b)的比例[sx,sy]变化矩阵

clip_image016

Matrix学习——Preconcats or Postconcats?

从最基本的高等数学开始,Matrix的基本操作包括:+、*。Matrix的乘法不满足交换律,也就是说A*B ≠B*A。

还有2种常见的矩阵:

clip_image017

有了上面的基础,下面我们开始进入主题。由于矩阵不满足交换律,所以用矩阵B乘以矩阵A,需要考虑是左乘(B*A),还是右乘(A*B)。在Android的android.graphics.Matrix中为我们提供了类似的方法,也就是我们本篇幅要说明的Preconcats matrix 与 Postconcats  matrix。下面我们还是通过具体的例子还说明:

clip_image018

通过输出的信息,我们分析其运行过程如下:

clip_image019

看了上面的输出信息。我们得出结论:Preconcats matrix相当于右乘矩阵,Postconcats  matrix相当于左乘矩阵。

上一篇幅中,我们说到:

clip_image020

其晕死过程的详细分析就不在这里多说了。

  Matrix学习——错切变换

 

什么是图像的错切变换(Shear transformation)?我们还是直接看图片错切变换后是的效果:

clip_image021

clip_image022

对图像的错切变换做个总结:

clip_image023

x = x0 + b*y0;

y = d*x0 + y0;

clip_image024

这里再次给大家介绍一个需要注意的地方:

clip_image025

通过以上,我们发现Matrix的setXXXX()函数,在调用时调用了一次reset(),这个在复合变换时需要注意。

  Matrix学习——对称变换(反射)

什么是对称变换?具体的理论就不详细说明了,图像的镜像就是对称变换中的一种。

clip_image026

利用上面的总结做个具体的例子,产生与直线y= – x对称的反射图形,代码片段如下:

clip_image027

当前矩阵输出是:

clip_image028

图像变换的效果如下:

clip_image029


  附:三角函数公式

两角和公式

sin(a+b)=sinacosb+cosasinb

sin(a-b)=sinacosb-sinbcosa 

cos(a+b)=cosacosb-sinasinb

cos(a-b)=cosacosb+sinasinb

tan(a+b)=(tana+tanb)/(1-tanatanb)

tan(a-b)=(tana-tanb)/(1+tanatanb)

cot(a+b)=(cotacotb-1)/(cotb+cota) 

cot(a-b)=(cotacotb+1)/(cotb-cota)

倍角公式

tan2a=2tana/[1-(tana)^2]

cos2a=(cosa)^2-(sina)^2=2(cosa)^2 -1=1-2(sina)^2

sin2a=2sina*cosa

半角公式

sin(a/2)=√((1-cosa)/2) sin(a/2)=-√((1-cosa)/2)

cos(a/2)=√((1+cosa)/2) cos(a/2)=-√((1+cosa)/2)

tan(a/2)=√((1-cosa)/((1+cosa)) tan(a/2)=-√((1-cosa)/((1+cosa))

cot(a/2)=√((1+cosa)/((1-cosa)) cot(a/2)=-√((1+cosa)/((1-cosa)) 

tan(a/2)=(1-cosa)/sina=sina/(1+cosa)

和差化积

2sinacosb=sin(a+b)+sin(a-b)

2cosasinb=sin(a+b)-sin(a-b) )

2cosacosb=cos(a+b)-sin(a-b)

-2sinasinb=cos(a+b)-cos(a-b)

sina+sinb=2sin((a+b)/2)cos((a-b)/2

cosa+cosb=2cos((a+b)/2)sin((a-b)/2)

tana+tanb=sin(a+b)/cosacosb

积化和差公式

sin(a)sin(b)=-1/2*[cos(a+b)-cos(a-b)]

cos(a)cos(b)=1/2*[cos(a+b)+cos(a-b)]

sin(a)cos(b)=1/2*[sin(a+b)+sin(a-b)]

诱导公式

sin(-a)=-sin(a)

cos(-a)=cos(a)

sin(pi/2-a)=cos(a)

cos(pi/2-a)=sin(a)

sin(pi/2+a)=cos(a)

cos(pi/2+a)=-sin(a)

sin(pi-a)=sin(a)

cos(pi-a)=-cos(a)

sin(pi+a)=-sin(a)

cos(pi+a)=-cos(a)

tga=tana=sina/cosa

万能公式

sin(a)= (2tan(a/2))/(1+tan^2(a/2))

cos(a)= (1-tan^2(a/2))/(1+tan^2(a/2))

tan(a)= (2tan(a/2))/(1-tan^2(a/2))

其它公式

a*sin(a)+b*cos(a)=sqrt(a^2+b^2)sin(a+c) [其中,tan(c)=b/a]

a*sin(a)-b*cos(a)=sqrt(a^2+b^2)cos(a-c) [其中,tan(c)=a/b]

1+sin(a)=(sin(a/2)+cos(a/2))^2

1-sin(a)=(sin(a/2)-cos(a/2))^2

其他非重点三角函数

csc(a)=1/sin(a)

sec(a)=1/cos(a)

双曲函数

sinh(a)=(e^a-e^(-a))/2

cosh(a)=(e^a+e^(-a))/2

tgh(a)=sinh(a)/cosh(a)


推荐阅读
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
  • Android实战——jsoup实现网络爬虫,糗事百科项目的起步
    本文介绍了Android实战中使用jsoup实现网络爬虫的方法,以糗事百科项目为例。对于初学者来说,数据源的缺乏是做项目的最大烦恼之一。本文讲述了如何使用网络爬虫获取数据,并以糗事百科作为练手项目。同时,提到了使用jsoup需要结合前端基础知识,以及如果学过JS的话可以更轻松地使用该框架。 ... [详细]
  • JavaWeb中读取文件资源的路径问题及解决方法
    在JavaWeb开发中,读取文件资源的路径是一个常见的问题。本文介绍了使用绝对路径和相对路径两种方法来解决这个问题,并给出了相应的代码示例。同时,还讨论了使用绝对路径的优缺点,以及如何正确使用相对路径来读取文件。通过本文的学习,读者可以掌握在JavaWeb中正确找到和读取文件资源的方法。 ... [详细]
  • Webpack5内置处理图片资源的配置方法
    本文介绍了在Webpack5中处理图片资源的配置方法。在Webpack4中,我们需要使用file-loader和url-loader来处理图片资源,但是在Webpack5中,这两个Loader的功能已经被内置到Webpack中,我们只需要简单配置即可实现图片资源的处理。本文还介绍了一些常用的配置方法,如匹配不同类型的图片文件、设置输出路径等。通过本文的学习,读者可以快速掌握Webpack5处理图片资源的方法。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • JVM 学习总结(三)——对象存活判定算法的两种实现
    本文介绍了垃圾收集器在回收堆内存前确定对象存活的两种算法:引用计数算法和可达性分析算法。引用计数算法通过计数器判定对象是否存活,虽然简单高效,但无法解决循环引用的问题;可达性分析算法通过判断对象是否可达来确定存活对象,是主流的Java虚拟机内存管理算法。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • Week04面向对象设计与继承学习总结及作业要求
    本文总结了Week04面向对象设计与继承的重要知识点,包括对象、类、封装性、静态属性、静态方法、重载、继承和多态等。同时,还介绍了私有构造函数在类外部无法被调用、static不能访问非静态属性以及该类实例可以共享类里的static属性等内容。此外,还提到了作业要求,包括讲述一个在网上商城购物或在班级博客进行学习的故事,并使用Markdown的加粗标记和语句块标记标注关键名词和动词。最后,还提到了参考资料中关于UML类图如何绘制的范例。 ... [详细]
  • 本文详细介绍了Android中的坐标系以及与View相关的方法。首先介绍了Android坐标系和视图坐标系的概念,并通过图示进行了解释。接着提到了View的大小可以超过手机屏幕,并且只有在手机屏幕内才能看到。最后,作者表示将在后续文章中继续探讨与View相关的内容。 ... [详细]
author-avatar
手机用户2502893987
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有