• Android中的图像矩阵归一化


    前言

    在graphics包下的Matrix是一个3x3的矩阵,按网上的的图是这样的

      MSCALE_X, MSCALE_Y表示缩放;

     MSKEW_X, MSKEW_Y表示错切,与上面两个参数一起达到图像旋转效果;

    MTRANS_X, MTRANS_Y表示平移;

     MPERSP_0, MPERSP_1表示透视;

    MPERSP_2固定为1。

    在把图像矩阵应用到OpenGL中时遇到了问题:glsl中获取到的矩阵是归一化的,需要先把原来的矩阵进行归一化处理。

    推导过程

    按照矩阵乘法规则

    \begin{bmatrix} x\\ y \\ z \end{bmatrix}=\begin{bmatrix} a0 & a1 &a2 \\ a3 & a4 &a5 \\ a6 & a7& a8 \end{bmatrix}\times \begin{bmatrix} x0\\y0 \\ 1 \end{bmatrix}

    x=a_{0}x_{0}+a_{1}y_{0}+a_{2}

    y=a_{3}x_{0}+a_{4}y_{0}+a_{5}

    z=a_{6}x_{0}+a_{7}y_{0}+a_{8}

    如果考虑到透视变换,则最终的坐标X=x/z, Y=y/z;

    设显示目标的尺寸为Tw,Th,归一化的坐标则是x1=X/Tw, y1=Y/Th;

    x1=\frac{a_{0}x_{0}+a_{1}y_{0}+a_{2}}{T_{w}(a_{6}x_{0}+a_{7}y_{0}+a_{8})}  ............①

     y1=\frac{a_{3}x_{0}+a_{4}y_{0}+a_{5}}{T_{w}(a_{6}x_{0}+a_{7}y_{0}+a_{8})}   ............②

    设图像原始宽高为w,h,归一化的矩阵为

    \begin{bmatrix} b0& b1 & b2\\ b3& b4 & b5\\ b6& b7 & b8 \end{bmatrix}

    那么,参照上面的等式,有

    x=b_{0}x_{0}/w+b_{1}y_{0}/h+b_{2}

    y=b_{3}x_{0}/w+b_{4}y_{0}/h+b_{5}

    z=b_{6}x_{0}/w+b_{7}y_{0}/h+b_{8}

    同样,考虑到透视变换,最终的归一化的坐标x1,y1为

    x1=\frac{b_{0}x_{0}/w+b_{1}y_{0}/h+b_{2}}{b_{6}x_{0}/w+b_{7}y_{0}/h+b_{8}}  ............③

     y1=\frac{b_{3}x_{0}/w+b_{4}y_{0}/h+b_{5}}{b_{6}x_{0}/w+b_{7}y_{0}/h+b_{8}}  ............④

    ①③联立并化简可得到

    \frac{a_{0}b_{6}-T_{w}a_{6}b_{0}}{w}x_{0}^{2}+(\frac{a_{0}b_{7}-T_{w}a_{6}b_{1}}{h}+\frac{a_{1}b_{6}-T_{w}a_{7}b_{0}}{w})x_{0}y_{0}+\frac{a_{1}b_{7}-T_{w}a_{7}b_{1}}{h}y_{0}^{2}+(a_{0}b_{8}-T_{w}a_{6}b_{2}+\frac{a_{2}b_{6}-T_{w}a_{8}b_{0}}{w})x_{0}+(a_{1}b_{8}-T_{w}a_{7}b_{2}+\frac{a_{2}b_{7}-T_{w}a_{8}b_{1}}{h})y_{0}+a_{2}b_{8}-T_{w}a_{8}b_{2}=0

    上式的每一项均为0,才能保证结果一定为0,因此有

    a_{0}b_{6}=T_{w}a_{6}b_{0}  (1)    a_{1}b_{7}=T_{w}a_{7}b_{1} (2)   a_{2}b_{8}=T_{w}a_{8}b_{2} (3)

    \frac{a_{0}b_{7}-T_{w}a_{6}b_{1}}{h}+\frac{a_{1}b_{6}-T_{w}a_{7}b_{0}}{w}=0  (4)

    a_{0}b_{8}-T_{w}a_{6}b_{2}+\frac{a_{2}b_{6}-T_{w}a_{8}b_{0}}{w}=0  (5)

    a_{1}b_{8}-T_{w}a_{7}b_{2}+\frac{a_{2}b_{7}-T_{w}a_{8}b_{1}}{h}=0  (6)

    同理,②④联立可得

    a_{3}b_{6}=T_{h}a_{6}b_{3}  (7)  a_{4}b_{7}=T_{h}a_{7}b_{4}  (8)  a_{5}b_{8}=T_{h}a_{8}b_{5}  (9)

    理论上(1)-(9)共9个方程,b0-b8共9个未知数,可以解方程,但其实a8=b8=1,所以上述方程组可以化简,最终结果是

    \left\{\begin{matrix} b_{0}=\frac{w}{T_{w}}a_{0}\\ b_{1}=\frac{h}{T_{w}}a_{1}\\ b_{2}=a_{2}/T_{w}\\ b_{3}=\frac{w}{T_{h}}a_{3}\\ b_{4}=\frac{h}{T_{h}}a_{4}\\ b_{5}=a_{5}/T_{h}\\ b_{6}=wa_{6}\\ b_{7}=ha_{7}\\ b_{8}=1 \end{matrix}\right.

    有兴趣的朋友可以推导验证一下。

    代码实现

    1. /**
    2. * 图像缩放矩阵归一化
    3. *
    4. * @param src 图像裁剪及缩放矩阵,length=9
    5. * @param width 图像原宽度
    6. * @param height 图像原高度
    7. * @param targetWidth 目标图像宽度,即显示的图像宽度,如100像素的宽度拉伸显示在300像素的View中,则应为100
    8. * @param targetHeight 目标图像高度,即显示的图像高度
    9. */
    10. public static float[] normalize(float[] src, int width, int height, int targetWidth, int targetHeight) {
    11. float[] values = new float[9];
    12. values[Matrix.MSCALE_X] = src[0] * width / targetWidth;
    13. values[Matrix.MSKEW_X] = src[1] * height / targetWidth;
    14. values[Matrix.MTRANS_X] = src[2] / targetWidth;
    15. values[Matrix.MSKEW_Y] = src[3] * width / targetHeight;
    16. values[Matrix.MSCALE_Y] = src[4] * height / targetHeight;
    17. values[Matrix.MTRANS_Y] = src[5] / targetHeight;
    18. values[Matrix.MPERSP_0] = src[6] * width;
    19. values[Matrix.MPERSP_1] = src[7] * height;
    20. values[Matrix.MPERSP_2] = src[8];
    21. return values;
    22. }

  • 相关阅读:
    极客范儿的浏览器主页YuIndex
    Mybatis学习笔记-映射文件,标签,插件
    关于对随机森林接口predict_proba()的个人理解
    ES聚合统计
    深度学习笔记_2、多种方法定义神经网络
    C#WPF控件Button详解
    成都榆熙:转化率的定义是什么?如何提升?
    解决hive表新增的字段查询为空null问题
    文件的逻辑结构与物理结构的对比与区别
    生产依赖与开发依赖区别: 前端程序没有区别,后端程序有点区别
  • 原文地址:https://blog.csdn.net/wlxyhy/article/details/126555104