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.

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

代码实现

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值