基于python语言的DCT+RLE编码方式的RGB图像编码 - Go语言中文社区

基于python语言的DCT+RLE编码方式的RGB图像编码


      对于三色大数据点图像压缩传输技术,常用的编码有霍夫曼编码、游程编码等,由于图像像素取值为0~255,不具有规律性,拟采用变换得到易于编码的图像。

      

步骤一:色彩转换和重采样

利用图片中亮度信息与色度信息的分辨差异性,对亮度信息进行精细采样,而对色度信息进行粗采样,常用的采样类型有YUV444、YUV420、YUV411,其中数字分别代表相邻四个数据采样的个数。

  

    Y = 0.299 * R + 0.587 * G + 0.144 * B

    U = -0.1687 * R - 0.3313 * G + 0.5 * B +128

    V = 0.5 * R - 0.4187 * G - 0.0813 * B + 128

 

在实际应用中可将0~255的矩阵变为-128~128的矩阵,减小绝对值波动,以降低DCT反变换数值上的损失。

 

步骤二:图像分割

相邻像素点间差异性小,相对整体变换处理而言,分割再拼接处理可以减少量化后的数据损失,通常取8*8大小。

步骤三:DCT变换

DCT变换即离散余弦变换,经过离散余弦变换,将图像数据变至频域数据,通常可以略去高频信息以达到压缩的目的。

对于8*8固定矩阵,可以简化为F(u,v)=Af(x,y)A',系数矩阵A为常值矩阵,可以计算得出,为

 Y = np.empty([8, 8], dtype=double)
    A = [[0.353553390593274,  0.353553390593274,  0.353553390593274,  0.353553390593274,  0.353553390593274,
          0.353553390593274,  0.353553390593274,  0.353553390593274],
         [0.490392640201615,  0.415734806151273,  0.277785116509801,  0.097545161008064, -0.097545161008064,
          -0.277785116509801, -0.415734806151273, -0.490392640201615],
         [0.461939766255643,  0.191341716182545, -0.191341716182545, -0.461939766255643, -0.461939766255643,
          -0.191341716182545,  0.191341716182545,  0.461939766255643],
         [0.415734806151273, -0.097545161008064, -0.490392640201615, -0.277785116509801,  0.277785116509801,
          0.490392640201615,  0.097545161008064, -0.415734806151272],
         [0.353553390593274, -0.353553390593274, -0.353553390593274,  0.353553390593274,  0.353553390593274,
          -0.353553390593273, -0.353553390593274,  0.353553390593273],
         [0.277785116509801, -0.490392640201615,  0.097545161008064,  0.415734806151273, -0.415734806151273,
          -0.097545161008065,  0.490392640201615, -0.277785116509801],
         [0.191341716182545, -0.461939766255643,  0.461939766255643, -0.191341716182545, -0.191341716182545,
          0.461939766255644, -0.461939766255644,  0.191341716182543],
         [0.097545161008064, -0.277785116509801,  0.415734806151273, -0.490392640201615,  0.490392640201615,
          -0.415734806151272,  0.277785116509802, -0.097545161008063]]
    Y = np.dot(np.dot(A, R), np.transpose(A))

 

步骤四:量化

 

量化即将DCT变换后的结果除以各自的量化步长并取整,由于我们需要大量低频数据而降低高频数据,则对高频、低频出数据采用不同步长量化取整即可。比如高频出DCT变换后数值为38,取量化步长为99时,int38/99=0,反量化时0*99=0,即可滤掉高频数据。

低频数据为65,取步长为21,int65/21=3,反量化回去时3*21=63,可以近似的对低频数据进行重现。由于对于亮度和色度的需求量不同,可以分别采用亮度和色度的量化表对应量化。

 

其中亮度量化表为

 

Q=[[  16, 11,  10,  16, 24,   40,  51,  61],

    [ 12,  12,  14, 19,  26,   58, 60,   55],

[ 14,  13,  16, 24,  40,   57, 69,   56],

[ 14,  17,  22, 29,  51,   87, 80,   62],

    [ 18,  22,  37, 56,  68,  109, 103,  77],

    [ 24,  35,  55, 64,  81,  104, 113,  92],

    [ 49,  64,  78, 87, 103,  121,  120, 101],

    [ 72,  92,  95, 98, 112,  100,  103, 99]]

     色度量化表为

 P=[  [17, 18, 24, 47, 99, 99, 99,99],

      [18, 21, 26, 66, 99, 99, 99, 99],

      [24, 26, 56, 99, 99, 99, 99, 99],

      [47, 66, 99, 99, 99, 99, 99, 99],

      [99, 99, 99, 99, 99, 99, 99, 99],

      [99, 99, 99, 99, 99, 99, 99, 99],

      [99, 99, 99, 99, 99, 99, 99, 99],

      [99, 99, 99, 99, 99, 99, 99, 99]]

步骤五:编码

经过上述变换,由于图像亮度在8*8方块内变换较小,一般会变为低频在左上角,以对角线方向梯度下降的右下角几乎为0的方阵,对此采用Z形扫描,使得连续的0尽可能的多,同时将二维信息转化为一维,随后进行RLE编码,即以一对数组(64,0)表示连续的64个相同的0。

def RLEencode(A):
    num = 1
    b = []
    A.append(0)
    for j in range(0, 64):
        if A[j + 1] == A[j] and j != 63:
            num = num + 1
        else:
            b.append(num)
            b.append(A[j])
            num = 1
    return b;

步骤六:解码

RLE反编码,将(64,0)变为64个0组成的行向量,64长度的向量反z字形变为8*8矩阵。

随后进行反量化,也就是对应元素值乘以量化表,依次用上文亮度、色度量化表进行运算即可,最后对数据取整。

IDCT变换:f=A'FA

YUV444转为RGB并拼接:此处由于计算取整的原因反变换后原图像的边缘数值会出现溢出比如1变为-3,252变为270,此时对大于255以及小于0的数分别取255和0 。

 

def RGB(Y,U,V):
    (x, y) = Y.shape
    for i in range(0, x):
        for j in range(0, y):
            Y[i][j] = Y[i][j] + 128
            U[i][j] = U[i][j] + 128
            V[i][j] = V[i][j] + 128
    R = Y + 1.402 * (V - 128)
    G = Y - 0.34414 * (U - 128) - 0.71414 * (V - 128)
    B = Y + 1.772 * (U - 128)
    for i in range(0, x):
        for j in range(0, y):
            if R[i][j] < 0:
                R[i][j] = 0
            elif R[i][j] > 255:
                R[i][j] = 255
            if G[i][j] < 0:
                G[i][j] = 0
            elif G[i][j] > 255:
                G[i][j] = 255
            if B[i][j] < 0:
                B[i][j] = 0
            elif B[i][j] > 255:
                B[i][j] = 255
    R = R.astype(np.int)
    G = G.astype(np.int)
    B = B.astype(np.int)
    return R, G, B;

 

最后得到图像。

 

 

 

 

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_30547827/article/details/80539650
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-04-18 22:14:50
  • 阅读 ( 982 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢