Android中关于矩阵(Matrix)前乘后乘的一些认识

在上一篇文章中,我们讲到,在Android中,scale(缩放),rotation(旋转)和 translation(平移)都是以矩阵(Matrix)的形式定义的,实际上在图形学中,这些平面图形的变换都是以矩阵的形式存在的。先来回顾一下,下面,左中右分别scale(缩放),rotation(旋转)和 translation(平移)在Android中的矩阵表示:


image.png

如果只是单纯的应用某一个变换,我们都知道直接用矩阵去乘上对应的点就可以了。但是对于缩放和旋转来说,它们的轴点是基于原点(0,0)的,如下图,我们将它缩小1倍,代码如下:

	public void onDraw(Canvas canvas){			
		canvas.drawBitmap(bitmap, 0, 0, null);		
		matrix.reset();		
		matrix.postScale(0.5f, 0.5f);
		canvas.drawBitmap(bitmap, matrix, null);			
	}	

则其效果如右图所示:

image.png


那么我们如果想让它基于图片中心缩放,应该该怎么办?我们上一篇文章也说过了,要用到组合变换,

1)先将图片由中心平移到原点,这是应用变换 T

2)对图应用缩放变换 S 

3)再将图片平移回到中心,应用变换 -T

下面给出它们的组合变换的公式:

image.png

在Android中的代码如下:

	public void onDraw(Canvas canvas){			
		canvas.drawBitmap(bitmap, 0, 0, null);		
		matrix.reset();		
		matrix.postScale(0.5f, 0.5f);
		matrix.preTranslate(-pivotX, -pivotY);
		matrix.postTranslate(pivotX, pivotY);
		canvas.drawBitmap(bitmap, matrix, null);			
	}	

我们看一下加上平移之后的效果图(其中pivotX 和 pivotY 是图片的中心):

image.png


我们看到代码中,我们在进行了scale之后呢,还给图片设置了下面两个平移的变换:

matrix.preTranslate(-pivotX, -pivotY);
matrix.postTranslate(pivotX, pivotY);
什么是PreTranlsate呢,什么又是postTranslate呢?我们先来看一下Android中的定义吧。preTranslate
    /**
     * Preconcats the matrix with the specified translation.
     * M' = M * T(dx, dy)
     */
    public boolean preTranslate(float dx, float dy) {
        return native_preTranslate(native_instance, dx, dy);
    }

postTranslate:

    /**
     * Postconcats the matrix with the specified translation.
     * M' = T(dx, dy) * M
     */
    public boolean postTranslate(float dx, float dy) {
        return native_postTranslate(native_instance, dx, dy);
    }

我们可以看到,pre是拿当前的矩阵乘以T,而post是拿T来乘以当前的矩阵,(矩阵的乘法是不满足交换率的,所以这两种乘法的结果是不一样的)

在图形学中,矩阵M右乘A,表示的是  A * M,而矩阵 M 左乘 A,则表示的是 M * A,可以形象地理解为右乘就是从右边乘进来,左乘就是从左边乘进来。


一比较,我们可以看出,pre其实执行的就是右乘的操作,而post执行的就是左乘的操作。


这是因为,在图像处理中,越靠近右边的矩阵越先执行,所以pre(也就是先的意思)所设置的矩阵T(Scale,Rotation也是一样的)就会先于其一开始设置的Scale执行,而post(后的意思)的因为是左乘,所以它会放在最左边,那么就会最后执行。


所以,上面三步的意思其实就是:


1)在当前的矩阵左边加一个Scale的操作,因为之前没有其的操作(reset了),那么当前的矩阵其实就只是 S 了。


2)在当前的矩阵(S)执行前,先执行一个平移到原点的操作(preTranslate),其实也就是进行右乘(S * T)。


3)在当前的矩阵(S * T)执行后,再执行一个从原点平移到中心点的操作(postTranslate),也就是进行一个左乘(-T * S * T)。


这就是Android中矩阵(Matrix)前乘和后乘所对应的图形学中矩阵中右乘和左乘的操作了。


不知道理解有没有错误,如有错误 ,希望有朋友能够指正,谢谢大家,另祝大家新年快乐!


————————————————

版权声明:本文为CSDN博主「linmiansheng」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/linmiansheng/article/details/18820599



本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年3月    »
123
45678910
11121314151617
18192021222324
25262728293031
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864