1

如何缩放以及通过哪个因子从浮点缩放 dctmtx 系数以获得以下整数值:

浮动 dctmtx:

( (0.3536    0.3536    0.3536    0.3536    0.3536    0.3536    0.3536    0.3536),
    (0.4904    0.4157    0.2778    0.0975   -0.0975   -0.2778   -0.4157   -0.4904),
    (0.4619    0.1913   -0.1913   -0.4619   -0.4619   -0.1913    0.1913    0.4619),
    (0.4157   -0.0975   -0.4904   -0.2778    0.2778    0.4904    0.0975   -0.4157),
    (0.3536   -0.3536   -0.3536    0.3536    0.3536   -0.3536   -0.3536    0.3536),
    (0.2778   -0.4904    0.0975    0.4157   -0.4157   -0.0975    0.4904   -0.2778),
    (0.1913   -0.4619    0.4619   -0.1913   -0.1913    0.4619   -0.4619    0.1913),
    (0.0975   -0.2778    0.4157   -0.4904    0.4904   -0.4157    0.2778   -0.0975)
)

整数 dctmtx:

(( 125,   122,   115,    103,    88,     69,     47,      24  ),
        ( 125,   103,    47,    -24,   -88,   -122,   -115,     -69  ),
        ( 125,    69,   -47,   -122,   -88,     24,    115,     103  ),
        ( 125,    24,  -115,    -69,    88,    103,    -47,    -122  ),
        ( 125,   -24,  -115,     69,    88,   -103,    -47,     122  ),
        ( 125,   -69,   -47,    122,   -88,    -24,    115,    -103  ),
        ( 125,  -103,    47,     24,   -88,    122,   -115,      69  ),
        ( 125,  -122,   115,   -103,    88,    -69,     47,     -24  )
    );
4

2 回答 2

1

除了旋转的两个矩阵之一之外,这两个矩阵似乎没有直接的线性关系:

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
int main (int argc, char *argv[])
{
    float dctmtx[8][8] = 
  { 0.3536,   0.3536,   0.3536,   0.3536,   0.3536,   0.3536,   0.3536,   0.3536,
    0.4904,   0.4157,   0.2778,   0.0975,  -0.0975,  -0.2778,  -0.4157,  -0.4904,
    0.4619,   0.1913,  -0.1913,  -0.4619,  -0.4619,  -0.1913,   0.1913,   0.4619,
    0.4157,  -0.0975,  -0.4904,  -0.2778,   0.2778,   0.4904,   0.0975,  -0.4157,
    0.3536,  -0.3536,  -0.3536,   0.3536,   0.3536,  -0.3536,  -0.3536,   0.3536,
    0.2778,  -0.4904,   0.0975,   0.4157,  -0.4157,  -0.0975,   0.4904,  -0.2778,
    0.1913,  -0.4619,   0.4619,  -0.1913,  -0.1913,   0.4619,  -0.4619,   0.1913,
    0.0975,  -0.2778,   0.4157,  -0.4904,   0.4904,  -0.4157,   0.2778,  -0.0975
  };

    int j,k, i;
    float m;
    for ( j = 0; j < 8; j++) {
        for ( k = 0; k < 8; k++) {
            if ( k == 0) 
                m = (dctmtx[k][j] * 354) ;
            else 
                m = (dctmtx[k][j] * 248) ;
            i = lroundf(m);
            printf("%4d ",i);
        }
        printf("\n");
    }   
}

每行中的第一个系数似乎与其余系数的精度不同:

%% convftoi
 125  122  115  103   88   69   47   24
 125  103   47  -24  -88 -122 -115  -69
 125   69  -47 -122  -88   24  115  103
 125   24 -115  -69   88  103  -47 -122
 125  -24 -115   69   88 -103  -47  122
 125  -69  -47  122  -88  -24  115 -103
 125 -103   47   24  -88  122 -115   69
 125 -122  115 -103   88  -69   47  -24

经过一点技巧,找到了匹配的比例因子。

附录

在 LutzL 的回答之后,我通过算法推导出浮点系数矩阵:

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#define PI 3.14159265359

int main (int argc, char *argv[])
{
  float calcmtx[8][8];

    int j,k, i;
    float m;
    printf("float coefficients calculated\n");
    for ( j = 0; j < 8; j++) {
        for ( k = 0; k < 8; k++) {
            if ( j == 0) 
                m = cos(PI*j*(2*k+1)/16)/(sqrt(2)*2) ;
            else 
                m = cos(PI*j*(2*k+1)/16)/2 ;
            calcmtx[k][j] = floorf(m*10000 + 0.5)/10000;
        }
    }

    for ( j = 0; j < 8; j++) {
        for ( k = 0; k < 8; k++) {
            printf("% 2.4f ", calcmtx[k][j]);
        }
        printf("\n");
    }
    printf("\n") ;

    printf("integer coefficients derived\n");
    for ( j = 0; j < 8; j++) {
        for ( k = 0; k < 8; k++) {
            if (k == 0)
                m = sqrt(2);
            else
                m = 1;
            i = (int) (calcmtx[j][k] * 250 * m);
            printf("%4d ", i);
        }
        printf("\n");
    }
    printf("\n") ;

    printf("approximated integer coefficients\n");
    for ( j = 0; j < 8; j++) {
        for ( k = 0; k < 8; k++) {
            if ( k == 0) 
                m = calcmtx[j][k] * 354 ;
            else 
                m = calcmtx[j][k] * 248 ;
            i = lroundf(m);
            printf("%4d ", i);
        }
        printf("\n");
    }   
}

我们看到整数矩阵的第一个系数乘以两个的平方根:

%% gencoeffi
float coefficients calculated
 0.3536  0.3536  0.3536  0.3536  0.3536  0.3536  0.3536  0.3536
 0.4904  0.4157  0.2778  0.0975 -0.0975 -0.2778 -0.4157 -0.4904
 0.4619  0.1913 -0.1913 -0.4619 -0.4619 -0.1913  0.1913  0.4619
 0.4157 -0.0975 -0.4904 -0.2778  0.2778  0.4904  0.0975 -0.4157
 0.3536 -0.3536 -0.3536  0.3536  0.3536 -0.3536 -0.3536  0.3536
 0.2778 -0.4904  0.0975  0.4157 -0.4157 -0.0975  0.4904 -0.2778
 0.1913 -0.4619  0.4619 -0.1913 -0.1913  0.4619 -0.4619  0.1913
 0.0975 -0.2778  0.4157 -0.4904  0.4904 -0.4157  0.2778 -0.0975

integer coefficients derived
 125  122  115  103   88   69   47   24
 125  103   47  -24  -88 -122 -115  -69
 125   69  -47 -122  -88   24  115  103
 125   24 -115  -69   88  103  -47 -122
 125  -24 -115   69   88 -103  -47  122
 125  -69  -47  122  -88  -24  115 -103
 125 -103   47   24  -88  122 -115   69
 125 -122  115 -103   88  -69   47  -24

approximated integer coefficients
 125  122  115  103   88   69   47   24
 125  103   47  -24  -88 -122 -115  -69
 125   69  -47 -122  -88   24  115  103
 125   24 -115  -69   88  103  -47 -122
 125  -24 -115   69   88 -103  -47  122
 125  -69  -47  122  -88  -24  115 -103
 125 -103   47   24  -88  122 -115   69
 125 -122  115 -103   88  -69   47  -24

当浮点精度有限时,它与近似值匹配。

于 2014-05-24T11:23:29.037 回答
0

如果您阅读离散余弦变换,您会发现基本系数是

cos(pi*i*(2*j+1)/16),  i,j=0..7

然后第一个表由这些值按 0.5 缩放,但第一行/列除外,它按 0.25*sqrt(2)=1/sqrt(8) 缩放。这是获得正交矩阵的正确方法。第一列的平方和为 8,其他为 4。

第二个表是余弦值乘以 125 时的四舍五入结果。在使用转置矩阵计算逆变换时,必须注意正确地重新调整向量。


复制了第一个表,除了第一列:

> [[ Cos(pi*i*(2*j+1)/16)/2 : i in [0..7] ]: j in [0..7] ];        
[
    [ 0.5, 0.49039264, 0.46193977, 0.41573481, 0.35355339, 0.27778512, 0.19134172, 0.09754516 ],
    [ 0.5, 0.41573481, 0.19134172, -0.09754516, -0.35355339, -0.49039264, -0.46193977, -0.27778512 ],
    [ 0.5, 0.27778512, -0.19134172, -0.49039264, -0.35355339, 0.09754516, 0.46193977, 0.41573481 ],
    [ 0.5, 0.09754516, -0.46193977, -0.27778512, 0.35355339, 0.41573481, -0.19134172, -0.49039264 ],
    [ 0.5, -0.09754516, -0.46193977, 0.27778512, 0.35355339, -0.41573481, -0.19134172, 0.49039264 ],
    [ 0.5, -0.27778512, -0.19134172, 0.49039264, -0.35355339, -0.09754516, 0.46193977, -0.41573481 ],
    [ 0.5, -0.41573481, 0.19134172, 0.09754516, -0.35355339, 0.49039264, -0.46193977, 0.27778512 ],
    [ 0.5, -0.49039264, 0.46193977, -0.41573481, 0.35355339, -0.27778512, 0.19134172, -0.09754516 ]
]

第二个表,整数舍入前

> [[ Cos( pi*i*(2*j+1)/16 ) *125 : i in [0..7] ]: j in [0..7] ];       
[
    [ 125, 122.5982, 115.4849, 103.9337, 88.3883, 69.4463, 47.8354, 24.3863 ],
    [ 125, 103.9337, 47.8354, -24.3863, -88.3883, -122.5982, -115.4849, -69.4463 ],
    [ 125, 69.4463, -47.8354, -122.5982, -88.3883, 24.3863, 115.4849, 103.9337 ],
    [ 125, 24.3863, -115.4849, -69.4463, 88.3883, 103.9337, -47.8354, -122.5982 ],
    [ 125, -24.3863, -115.4849, 69.4463, 88.3883, -103.9337, -47.8354, 122.5982 ],
    [ 125, -69.4463, -47.8354, 122.5982, -88.3883, -24.3863, 115.4849, -103.9337 ],
    [ 125, -103.9337, 47.8354, 24.3863, -88.3883, 122.5982, -115.4849, 69.4463 ],
    [ 125, -122.5982, 115.4849, -103.9337, 88.3883, -69.4463, 47.8354, -24.3863 ]
]
于 2014-05-24T18:05:05.733 回答