Matrix的数学原理.docx_第1页
Matrix的数学原理.docx_第2页
Matrix的数学原理.docx_第3页
Matrix的数学原理.docx_第4页
Matrix的数学原理.docx_第5页
已阅读5页,还剩33页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Android MatrixMatrix的数学原理平移变换旋转变换缩放变换错切变换对称变换代码验证Matrix的数学原理在Android中,如果你用Matrix进行过图像处理,那么一定知道Matrix这个类。Android中的Matrix是一个3 x 3的矩阵,其内容如下:Matrix的对图像的处理可分为四类基本变换:Translate 平移变换Rotate 旋转变换Scale 缩放变换Skew 错切变换从字面上理解,矩阵中的MSCALE用于处理缩放变换,MSKEW用于处理错切变换,MTRANS用于处理平移变换,MPERSP用于处理透视变换。实际中当然不能完全按照字面上的说法去理解Matrix。同时,在Android的文档中,未见到用Matrix进行透视变换的相关说明,所以本文也不讨论这方面的问题。针对每种变换,Android提供了pre、set和post三种操作方式。其中set用于设置Matrix中的值。pre是先乘,因为矩阵的乘法不满足交换律,因此先乘、后乘必须要严格区分。先乘相当于矩阵运算中的右乘。post是后乘,因为矩阵的乘法不满足交换律,因此先乘、后乘必须要严格区分。后乘相当于矩阵运算中的左乘。除平移变换(Translate)外,旋转变换(Rotate)、缩放变换(Scale)和错切变换(Skew)都可以围绕一个中心点来进行,如果不指定,在默认情况下是围绕(0, 0)来进行相应的变换的。下面我们来看看四种变换的具体情形。由于所有的图形都是有点组成,因此我们只需要考察一个点相关变换即可。一、 平移变换假定有一个点的坐标是 ,将其移动到 ,再假定在x轴和y轴方向移动的大小分别为:如下图所示:不难知道:如果用矩阵来表示的话,就可以写成:二、 旋转变换2.1 围绕坐标原点旋转:假定有一个点 ,相对坐标原点顺时针旋转后的情形,同时假定P点离坐标原点的距离为r,如下图:那么,如果用矩阵,就可以表示为:2.2 围绕某个点旋转如果是围绕某个点顺时针旋转,那么可以用矩阵表示为:可以化为:很显然,1. 是将坐标原点移动到点后, 的新坐标。2. 是将上一步变换后的,围绕新的坐标原点顺时针旋转 。3. 经过上一步旋转变换后,再将坐标原点移回到原来的坐标原点。所以,围绕某一点进行旋转变换,可以分成3个步骤,即首先将坐标原点移至该点,然后围绕新的坐标原点进行旋转变换,再然后将坐标原点移回到原先的坐标原点。三、 缩放变换理论上而言,一个点是不存在什么缩放变换的,但考虑到所有图像都是由点组成,因此,如果图像在x轴和y轴方向分别放大k1和k2倍的话,那么图像中的所有点的x坐标和y坐标均会分别放大k1和k2倍,即用矩阵表示就是:缩放变换比较好理解,就不多说了。四、 错切变换错切变换(skew)在数学上又称为Shear mapping(可译为“剪切变换”)或者Transvection(缩并),它是一种比较特殊的线性变换。错切变换的效果就是让所有点的x坐标(或者y坐标)保持不变,而对应的y坐标(或者x坐标)则按比例发生平移,且平移的大小和该点到x轴(或y轴)的垂直距离成正比。错切变换,属于等面积变换,即一个形状在错切变换的前后,其面积是相等的。比如下图,各点的y坐标保持不变,但其x坐标则按比例发生了平移。这种情况将水平错切。下图各点的x坐标保持不变,但其y坐标则按比例发生了平移。这种情况叫垂直错切。假定一个点经过错切变换后得到,对于水平错切而言,应该有如下关系:用矩阵表示就是:扩展到3 x 3的矩阵就是下面这样的形式:同理,对于垂直错切,可以有:在数学上严格的错切变换就是上面这样的。在Android中除了有上面说到的情况外,还可以同时进行水平、垂直错切,那么形式上就是:五、 对称变换除了上面讲到的4中基本变换外,事实上,我们还可以利用Matrix,进行对称变换。所谓对称变换,就是经过变化后的图像和原图像是关于某个对称轴是对称的。比如,某点 经过对称变换后得到,如果对称轴是x轴,难么,用矩阵表示就是:如果对称轴是y轴,那么,用矩阵表示就是:如果对称轴是y = x,如图:那么,很容易可以解得:用矩阵表示就是:同样的道理,如果对称轴是y = -x,那么用矩阵表示就是:特殊地,如果对称轴是y = kx,如下图:那么,很容易可解得:用矩阵表示就是:当k = 0时,即y = 0,也就是对称轴为x轴的情况;当k趋于无穷大时,即x = 0,也就是对称轴为y轴的情况;当k =1时,即y = x,也就是对称轴为y = x的情况;当k = -1时,即y = -x,也就是对称轴为y = -x的情况。不难验证,这和我们前面说到的4中具体情况是相吻合的。如果对称轴是y = kx + b这样的情况,只需要在上面的基础上增加两次平移变换即可,即先将坐标原点移动到(0, b),然后做上面的关于y = kx的对称变换,再然后将坐标原点移回到原来的坐标原点即可。用矩阵表示大致是这样的:需要特别注意:在实际编程中,我们知道屏幕的y坐标的正向和数学中y坐标的正向刚好是相反的,所以在数学上y = x和屏幕上的y = -x才是真正的同一个东西,反之亦然。也就是说,如果要使图片在屏幕上看起来像按照数学意义上y = x对称,那么需使用这种转换:要使图片在屏幕上看起来像按照数学意义上y = -x对称,那么需使用这种转换:关于对称轴为y = kx 或y = kx + b的情况,同样需要考虑这方面的问题。第二部分 代码验证在第一部分中讲到的各种图像变换的验证代码如下,一共列出了10种情况。如果要验证其中的某一种情况,只需将相应的代码反注释即可。试验中用到的图片:其尺寸为162 x 251。每种变换的结果,请见代码之后的说明。java view plaincopy1. package com.pat.testtransformmatrix; 2.3. import android.app.Activity; 4. import android.content.Context; 5. import android.graphics.Bitmap; 6. import android.graphics.BitmapFactory; 7. import android.graphics.Canvas; 8. import android.graphics.Matrix; 9. import android.os.Bundle; 10. import android.util.Log; 11. import android.view.MotionEvent; 12. import android.view.View; 13. import android.view.Window; 14. import android.view.WindowManager; 15. import android.view.View.OnTouchListener; 16. import android.widget.ImageView; 17.18. public class TestTransformMatrixActivity extends Activity 19. implements 20. OnTouchListener 21. 22. private TransformMatrixView view; 23. Override 24. public void onCreate(Bundle savedInstanceState) 25. 26. super.onCreate(savedInstanceState); 27. requestWindowFeature(Window.FEATURE_NO_TITLE); 28. this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); 29.30. view = new TransformMatrixView(this); 31. view.setScaleType(ImageView.ScaleType.MATRIX); 32. view.setOnTouchListener(this); 33.34. setContentView(view); 35. 36.37. class TransformMatrixView extends ImageView 38. 39. private Bitmap bitmap; 40. private Matrix matrix; 41. public TransformMatrixView(Context context) 42. 43. super(context); 44. bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sophie); 45. matrix = new Matrix(); 46. 47.48. Override 49. protected void onDraw(Canvas canvas) 50. 51. / 画出原图像 52. canvas.drawBitmap(bitmap, 0, 0, null); 53. / 画出变换后的图像 54. canvas.drawBitmap(bitmap, matrix, null); 55. super.onDraw(canvas); 56. 57.58. Override 59. public void setImageMatrix(Matrix matrix) 60. 61. this.matrix.set(matrix); 62. super.setImageMatrix(matrix); 63. 64.65. public Bitmap getImageBitmap() 66. 67. return bitmap; 68. 69. 70.71. public boolean onTouch(View v, MotionEvent e) 72. 73. if(e.getAction() = MotionEvent.ACTION_UP) 74. 75. Matrix matrix = new Matrix(); 76. / 输出图像的宽度和高度(162 x 251) 77. Log.e(TestTransformMatrixActivity, image size: width x height = + view.getImageBitmap().getWidth() + x + view.getImageBitmap().getHeight(); 78. / 1. 平移 79. matrix.postTranslate(view.getImageBitmap().getWidth(), view.getImageBitmap().getHeight(); 80. / 在x方向平移view.getImageBitmap().getWidth(),在y轴方向view.getImageBitmap().getHeight() 81. view.setImageMatrix(matrix); 82.83. / 下面的代码是为了查看matrix中的元素 84. float matrixValues = new float9; 85. matrix.getValues(matrixValues); 86. for(int i = 0; i 3; +i) 87. 88. String temp = new String(); 89. for(int j = 0; j 3; +j) 90. 91. temp += matrixValues3 * i + j + t; 92. 93. Log.e(TestTransformMatrixActivity, temp); 94. 95.96.97. / / 2. 旋转(围绕图像的中心点) 98. / matrix.setRotate(45f, view.getImageBitmap().getWidth() / 2f, view.getImageBitmap().getHeight() / 2f); 99. / 100. / / 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠 101. / matrix.postTranslate(view.getImageBitmap().getWidth() * 1.5f, 0f); 102. / view.setImageMatrix(matrix); 103. / 104. / / 下面的代码是为了查看matrix中的元素 105. / float matrixValues = new float9; 106. / matrix.getValues(matrixValues); 107. / for(int i = 0; i 3; +i) 108. / 109. / String temp = new String(); 110. / for(int j = 0; j 3; +j) 111. / 112. / temp += matrixValues3 * i + j + t; 113. / 114. / Log.e(TestTransformMatrixActivity, temp); 115. / 116.117.118. / / 3. 旋转(围绕坐标原点) + 平移(效果同2) 119. / matrix.setRotate(45f); 120. / matrix.preTranslate(-1f * view.getImageBitmap().getWidth() / 2f, -1f * view.getImageBitmap().getHeight() / 2f); 121. / matrix.postTranslate(float)view.getImageBitmap().getWidth() / 2f, (float)view.getImageBitmap().getHeight() / 2f); 122. / 123. / / 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠 124. / matrix.postTranslate(float)view.getImageBitmap().getWidth() * 1.5f, 0f); 125. / view.setImageMatrix(matrix); 126. / 127. / / 下面的代码是为了查看matrix中的元素 128. / float matrixValues = new float9; 129. / matrix.getValues(matrixValues); 130. / for(int i = 0; i 3; +i) 131. / 132. / String temp = new String(); 133. / for(int j = 0; j 3; +j) 134. / 135. / temp += matrixValues3 * i + j + t; 136. / 137. / Log.e(TestTransformMatrixActivity, temp); 138. / 139.140. / / 4. 缩放 141. / matrix.setScale(2f, 2f); 142. / / 下面的代码是为了查看matrix中的元素 143. / float matrixValues = new float9; 144. / matrix.getValues(matrixValues); 145. / for(int i = 0; i 3; +i) 146. / 147. / String temp = new String(); 148. / for(int j = 0; j 3; +j) 149. / 150. / temp += matrixValues3 * i + j + t; 151. / 152. / Log.e(TestTransformMatrixActivity, temp); 153. / 154. / 155. / / 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠 156. / matrix.postTranslate(view.getImageBitmap().getWidth(), view.getImageBitmap().getHeight(); 157. / view.setImageMatrix(matrix); 158. / 159. / / 下面的代码是为了查看matrix中的元素 160. / matrixValues = new float9; 161. / matrix.getValues(matrixValues); 162. / for(int i = 0; i 3; +i) 163. / 164. / String temp = new String(); 165. / for(int j = 0; j 3; +j) 166. / 167. / temp += matrixValues3 * i + j + t; 168. / 169. / Log.e(TestTransformMatrixActivity, temp); 170. / 171.172.173. / / 5. 错切 - 水平 174. / matrix.setSkew(0.5f, 0f); 175. / / 下面的代码是为了查看matrix中的元素 176. / float matrixValues = new float9; 177. / matrix.getValues(matrixValues); 178. / for(int i = 0; i 3; +i) 179. / 180. / String temp = new String(); 181. / for(int j = 0; j 3; +j) 182. / 183. / temp += matrixValues3 * i + j + t; 184. / 185. / Log.e(TestTransformMatrixActivity, temp); 186. / 187. / 188. / / 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠 189. / matrix.postTranslate(view.getImageBitmap().getWidth(), 0f); 190. / view.setImageMatrix(matrix); 191. / 192. / / 下面的代码是为了查看matrix中的元素 193. / matrixValues = new float9; 194. / matrix.getValues(matrixValues); 195. / for(int i = 0; i 3; +i) 196. / 197. / String temp = new String(); 198. / for(int j = 0; j 3; +j) 199. / 200. / temp += matrixValues3 * i + j + t; 201. / 202. / Log.e(TestTransformMatrixActivity, temp); 203. / 204.205. / / 6. 错切 - 垂直 206. / matrix.setSkew(0f, 0.5f); 207. / / 下面的代码是为了查看matrix中的元素 208. / float matrixValues = new float9; 209. / matrix.getValues(matrixValues); 210. / for(int i = 0; i 3; +i) 211. / 212. / String temp = new String(); 213. / for(int j = 0; j 3; +j) 214. / 215. / temp += matrixValues3 * i + j + t; 216. / 217. / Log.e(TestTransformMatrixActivity, temp); 218. / 219. / 220. / / 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠 221. / matrix.postTranslate(0f, view.getImageBitmap().getHeight(); 222. / view.setImageMatrix(matrix); 223. / 224. / / 下面的代码是为了查看matrix中的元素 225. / matrixValues = new float9; 226. / matrix.getValues(matrixValues); 227. / for(int i = 0; i 3; +i) 228. / 229. / String temp = new String(); 230. / for(int j = 0; j 3; +j) 231. / 232. / temp += matrixValues3 * i + j + t; 233. / 234. / Log.e(TestTransformMatrixActivity, temp); 235. / 236.237. / 7. 错切 - 水平 + 垂直 238. / matrix.setSkew(0.5f, 0.5f); 239. / / 下面的代码是为了查看matrix中的元素 240. / float matrixValues = new float9; 241. / matrix.getValues(matrixValues); 242. / for(int i = 0; i 3; +i) 243. / 244. / String temp = new String(); 245. / for(int j = 0; j 3; +j) 246. / 247. / temp += matrixValues3 * i + j + t; 248. / 249. / Log.e(TestTransformMatrixActivity, temp); 250. / 251. / 252. / / 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠 253. / matrix.postTranslate(0f, view.getImageBitmap().getHeight(); 254. / view.setImageMatrix(matrix); 255. / 256. / / 下面的代码是为了查看matrix中的元素 257. / matrixValues = new float9; 258. / matrix.getValues(matrixValues); 259. / for(int i = 0; i 3; +i) 260. / 261. / String temp = new String(); 262. / for(int j = 0; j 3; +j) 263. / 264. / temp += matrixValues3 * i + j + t; 265. / 266. / Log.e(TestTransformMatrixActivity, temp); 267. / 268.269. / / 8. 对称 (水平对称) 270. / float matrix_values = 1f, 0f, 0f, 0f, -1f, 0f, 0f, 0f, 1f; 271. / matrix.setValues(matrix_values); 272. / / 下面的代码是为了查看matrix中的元素 273. / float matrixValues = new float9; 274. / matrix.getValues(matrixValues); 275. / for(int i = 0; i 3; +i) 276. / 277. / String temp = new String(); 278. / for(int j = 0; j 3; +j) 279. / 280. / temp += matrixValues3 * i + j + t; 281. / 282. / Log.e(TestTransformMatrixActivity, temp); 283. / 284. / 285. / / 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠 286. / matrix.postTranslate(0f, view.getImageBitmap().getHeight() * 2f); 287. / view.setImageMatrix(matrix); 288. / 289. / / 下面的代码是为了查看matrix中的元素 290. / matrixValues = new float9; 291. / matrix.getValues(matrixValues); 292. / for(int i = 0; i 3; +i) 293. / 294. / String temp = new String(); 295. / for(int j = 0; j 3; +j) 296. / 297. / temp += matrixValues3 * i + j + t; 298. / 299. / Log.e(TestTransformMatrixActivity, temp); 300. / 301.302. / / 9. 对称 - 垂直 303. / float matrix_values = -1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f; 304. / matrix.setValues(matrix_values); 305. / / 下面的代码是为了查看matrix中的元素 306. / float matrixValues = new float9; 307. / matrix.getValues(matrixValues); 308. / for(int i = 0; i 3; +i) 309. / 310. / String temp = new String(); 311. / for(int j = 0; j 3; +j) 312. / 313. / temp += matrixValues3 * i + j + t; 314. / 315. / Log.e(TestTransformMatrixActivity, temp); 316. / 317. / 318. / / 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠 319. / matrix.postTranslate(view.getImageBitmap().getWidth() * 2f, 0f); 320. / view.setImageMatrix(matrix); 321. / 322. / / 下面的代码是为了查看matrix中的元素 323. / matrixValues = new float9; 324. / matrix.getValues(matrixValues); 325. / for(int i = 0; i 3; +i) 326. / 327. / String temp = new String(); 328. / for(int j = 0; j 3; +j) 329. / 330. / temp += matrixValues3 * i + j + t; 331. / 332. / Log.e(TestTransformMatrixActivity, temp); 333. / 334.335.336. / / 10. 对称(对称轴为直线y = x) 337. / float matrix_values = 0f, -1f, 0f, -1f, 0f, 0f, 0f, 0f, 1f; 338. / matrix.setValues(matrix_values); 339. / / 下面的代码是为了查看matrix中的元素 340. / float matrixValues = new float9; 341. / matrix.getValues(matrixValues); 342. / for(int i = 0; i 3; +i) 343. / 344. / String temp = new String(); 345. / for(int j = 0; j 3; +j) 346. / 347. / temp += matrixValues3 * i + j + t; 348. / 349. / Log.e(TestTransformMatrixActivity, temp); 350. / 351. / 352. / / 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠 353. / matrix.postTranslate(view.getImageBitmap().getHeight() + view.getImageBitmap().getWidth(), 354. / view.getImageBitmap().getHeight() + view.getImageBitmap().getWidth(); 355. / view.setImageMatrix(matrix); 356. / 357. / / 下面的代码是为了查看matrix中的元素 358. / matrixValues = new float9; 359. / matrix.getValues(matrixValues); 360. / for(int i = 0; i 3; +i) 361. / 362. / String temp = new String(); 363. / for(int j = 0; j 3; +j) 364. / 365. / temp += matrixValues3 * i + j + t; 366. / 367. / Log.e(TestTransformMatrixActivity, temp); 368. / 369.370. view.invalidate(); 371. 372. return true; 373. 374. 下面给出上述代码中,各种变换的具体结果及其对应的相关变换矩阵1. 平移输出的结果:请对照第一部分中的“一、平移变换”所讲的情形,考察上述矩阵的正确性。2. 旋转(围绕图像的中心点)输出的结果:它实际上是matrix.setRotate(45f,view.getImageBitmap().getWidth() / 2f, view.getImageBitmap().getHeight() / 2f);matrix.postTranslate(view.getImageBitmap().getWidth()* 1.5f, 0f);这两条语句综合作用的结果。根据第一部分中“二、旋转变换”里面关于围绕某点旋转的公式,matrix.setRotate(45f,view.getImageBitmap().getWidth() / 2f, view.getImageBitmap().getHeight() / 2f);所产生的转换矩阵就是:而matrix.postTranslate(view.getImageBitmap().getWidth()* 1.5f, 0f);的意思就是在上述矩阵的左边再乘以下面的矩阵:关于post是左乘这一点,我们在前面的理论部分曾经提及过,后面我们还会专门讨论这个问题。所以它实际上就是:出去计算上的精度误差,我们可以看到我们计算出来的结果,和程序直接输出的结果是一致的。3. 旋转(围绕坐标原点旋转,在加上两次平移,效果同2)根据第一部分中“二、旋转变换”里面关于围绕某点旋转的解释,不难知道:matrix.setRotate(45f,view.getImageBitmap().getWidth() / 2f, view.getImageBitmap().getHeight() / 2f);等价于matrix.setRotate(45f);matrix.preTranslate(-1f* view.getImageBitmap().getWidth() / 2f, -1f *view.getImageBitmap().getHeight() / 2f);matrix.postTranslate(float)view.getImageBitmap().getWidth()/ 2f, (float)view.getImageBitmap().getHeight() / 2f);其中matrix.setRotate(45f)对应的矩阵是:matrix.preTranslate(-1f* view.getImageBitmap().getWidth() / 2f, -1f * view.getImageBit

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论