转:http://zensheno.blog.51cto.com/2712776/513652

Matrix学习——基础知识

以前在线性代数中学习了矩阵,对矩阵的基本运算有一些了解,前段时间在使用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

采用矩阵表达上述如下: 

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

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

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

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

图像的旋转稍微复杂:现设点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θ

于是我们得到矩阵:

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

Matrix学习——如何使用Matrix

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

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

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

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

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

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

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

final float f[] = {1.0F,0.0F,0.0F,0.0F,-1.0F,120.0F,0.0F,0.0F,1.0F}; 
Matrix matrix = new Matrix(); 
matrix.setValues(f);

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

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

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

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

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

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

我们需要3步:

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

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

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

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

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

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

按照上面的公式,我们列举一个简单的例子:围绕(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); 
旋转后的图像如下:

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

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

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

Matrix学习——Preconcats or Postconcats?

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

还有2种常见的矩阵:

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

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

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

上一篇幅中,我们说到:

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

Matrix学习——错切变换

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

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

x = x0 + b*y0;

y = d*x0 + y0;

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

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

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

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

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

当前矩阵输出是:

图像变换的效果如下:

 

附:三角函数公式

两角和公式

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)

Android Matrix理论与应用详解的更多相关文章

  1. Android图片缓存之Bitmap详解

    前言: 最近准备研究一下图片缓存框架,基于这个想法觉得还是先了解有关图片缓存的基础知识,今天重点学习一下Bitmap.BitmapFactory这两个类. 图片缓存相关博客地址: Android图片缓 ...

  2. Android中Canvas绘图基础详解(附源码下载) (转)

    Android中Canvas绘图基础详解(附源码下载) 原文链接  http://blog.csdn.net/iispring/article/details/49770651   AndroidCa ...

  3. Android App优化之ANR详解

    引言 背景:Android App优化, 要怎么做? Android App优化之性能分析工具 Android App优化之提升你的App启动速度之理论基础 Android App优化之提升你的App ...

  4. Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)

    Android XML shape 标签使用详解   一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...

  5. Android Design Support Library使用详解

    Android Design Support Library使用详解 Google在2015的IO大会上,给我们带来了更加详细的Material Design设计规范,同时,也给我们带来了全新的And ...

  6. Android 之窗口小部件详解--App Widget

    Android 之窗口小部件详解--App Widget  版本号 说明 作者 日期  1.0  添加App Widge介绍和示例  Sky Wang 2013/06/27        1 App ...

  7. Android不规则点击区域详解

    Android不规则点击区域详解 摘要 今天要和大家分享的是Android不规则点击区域,准确说是在视觉上不规则的图像点击响应区域分发. 其实这个问题比较简单,对于很多人来说根本不值得做为一篇博文写出 ...

  8. [Android新手区] SQLite 操作详解--SQL语法

    该文章完全摘自转自:北大青鸟[Android新手区] SQLite 操作详解--SQL语法  :http://home.bdqn.cn/thread-49363-1-1.html SQLite库可以解 ...

  9. Android中Service的使用详解和注意点(LocalService)

    Android中Service的使用详解和注意点(LocalService) 原文地址 开始,先稍稍讲一点android中Service的概念和用途吧~ Service分为本地服务(LocalServ ...

随机推荐

  1. 读书笔记---《Docker 技术入门与实践》---为镜像添加SSH服务

    之前说到可以通过attach和exec两个命令登陆容器,但是如果遇到需要远程通过ssh登陆容器的场景,就需要手动添加ssh服务. 下面介绍两种方法创建带有ssh服务的镜像,commit命令创建和通过D ...

  2. VMWare 禁用虚拟内存文件(*.vmem)

    1.使用 VMWare 虚拟机,虚拟机启动后,会在虚拟机目录下建立一个与虚拟内存大小相同的 .vmem文件,例如:564db13c-c92d-3d3a-41a0-f62af7536fda.vmem. ...

  3. 去sqlserver日志

    USE [master] GO ALTER DATABASE DNName SET RECOVERY SIMPLE WITH NO_WAIT GO ALTER DATABASE DNName SET  ...

  4. leetcood学习笔记-83-删除链表中的重复元素

    题目描述: 第一次提交: class Solution: def deleteDuplicates(self, head: ListNode) -> ListNode: if head==Non ...

  5. 简单介绍下怎么在spring中使用RabbitMQ

    这篇文章主要介绍了简单了解如何在spring中使用RabbitMQ,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 常见的消息中间件产品: (1)Ac ...

  6. 「题解」:y

    问题 B: y 时间限制: 1 Sec  内存限制: 256 MB 题面 题面谢绝公开. 题解 考虑双向搜索. 定义$cal_{i,j,k}$表示当前已经搜索状态中是否存在长度为i,终点为j,搜索过边 ...

  7. Delphi中关于菜单的几个技巧

    -- 1将菜单项移到菜单栏的最右边 在一些应用程序中,常把一些特殊的菜单项放在菜单栏的最右边(如WPS2000 中的"定制界面"菜单,一些应用程序的帮助菜单),这些菜单项放在菜单栏 ...

  8. HDU6315 Naive Operations 线段树

    目录 Catalog Solution: (有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 Catalog Problem:Portal传送门  原题目描述在最下面. Solution ...

  9. bash字符串前导美元符号的作用

    problem bash内置变量IFS作为内部单词分隔符,其默认值为<space><tab><newline>, 我想设置它仅为\n,于是: OLD_IFS=$IF ...

  10. HtmlCleanner结合xpath用法(转载)

    HtmlCleaner cleaner = new HtmlCleaner(); TagNode node = cleaner.clean(new URL("http://finance.s ...