Python中的JPEG压缩变为负面

时间:2015-12-17 09:21:48

标签: python numpy image-processing jpeg

我尝试使用Numpy在Python中压缩灰度图像。我尝试了两种不同的量化方法:应用遮罩并按预定义的权重进行划分,但在这两种情况下,压缩图像的值都太高了。 This is how it looks with a mask quantisation. Looks similar with weights.

原始图像和处理过的图像在python IDE中的打印输出提供以下内容:

Uncompressed:
[[23 25 26 ..., 17 18 19]
 [23 25 26 ..., 16 17 18]
 [24 25 27 ..., 15 16 16]
 ..., 
 [68 52 45 ..., 20 18 17]
 [66 27 14 ..., 18 17 15]
 [68 29 14 ..., 17 15 14]]

Compressed:
[[ 278.70719913  280.56095939  281.89426619 ...,  273.41847541
   274.41642174  275.11264205]
 [ 279.49137088  281.20996776  282.42671682 ...,  272.37174176
   273.05506856  273.59872544]
 [ 280.26810477  281.7369523   282.73833074 ...,  271.18033959
   271.45606872  271.81185441]
 ..., 
 [ 346.60801656  332.97428913  311.95287258 ...,  275.36547554
   273.90408787  273.14715488]
 [ 326.40626296  308.74082394  285.71491905 ...,  274.10082953
   272.12056066  271.00663571]
 [ 303.05777135  281.42687625  254.22921445 ...,  273.12188339
   270.79982443  269.46372928]]

显然,这会导致图像中应该是暗的区域变亮,反之亦然。我怀疑错误在于计算DCT变换矩阵。

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import matplotlib.cm as cm

def dct_basis():
    """ Calculates matrix with dtc basis vectors. """
    rows = np.arange(1,16,2)
    cols = np.arange(8)
    rows.shape = (1,8)
    cols.shape = (8,1)
    coeffs = np.dot(cols,rows) # param in cos() in dct matrix, without pi/16
    coeffs = coeffs.T
    radians = (np.pi/16) * coeffs  # now make the numbers radians
    dct = np.cos(radians)
    dct = np.sqrt(2./8)*dct
    col0 = np.ones(8)*(1/np.sqrt(8)) 
    col0.shape = (8,1)
    dct[:,0:1] = col0  # first column filled by sqrt(2/width)
    dct = np.matrix(dct)
    return dct

def get_weights(): # commmented out is for quantising w/ weights
##    with open('weights.txt','r') as f:
##        W = f.read()
##    W = weights.split()
##    W = map(float,weights)
##    W = np.asarray(weights)
##    W = np.reshape(weights, (8,8))
##    W = np.matrix(weights)
    a = np.triu([1,1,1,1,1]) # this is for quantising w/ mask
    W = np.zeros((8,8))
    W[:5,3:] = a
    W = np.fliplr(W)
    return W    

def jpeg_encode():
    I = np.matrix(mpimg.imread('uggla2.tif'))
    print "Pre: ",I
    # More effective coding if values are centered around zero.
    # This assumes a resolution of 256 colours.
    I = I - 128
    T = dct_basis()
    W = get_weights()
    blocksize = 8
    size = I.shape
    bx = size[0]/8
    by = size[1]/8
    C = np.matrix(np.zeros(size))
    for x in range(bx):
        for y in range(by):
            tmp = T.T * I[x*blocksize : x*blocksize + blocksize,
                          y*blocksize : y*blocksize + blocksize] * T
            C[x*blocksize : x*blocksize + blocksize,
              y*blocksize : y*blocksize + blocksize] = \
                                          np.around(np.multiply(tmp,W))
    return C

def jpeg_decode():
    C = jpeg_encode()
    T = dct_basis()
    W = get_weights()
    blocksize = 8
    size = C.shape
    bx = size[0]/8
    by = size[1]/8
    I = np.matrix(np.zeros(size))
    for x in range(bx):
        for y in range(by):
            tmp = C[x*blocksize : x*blocksize + blocksize,
                    y*blocksize : y*blocksize + blocksize]
            #tmp = np.multiply(tmp,W)
            I[x*blocksize : x*blocksize + blocksize,
              y*blocksize : y*blocksize + blocksize] = \
                                             T * tmp * T.T
    I = I + 128
    print "Post: ",I
    return I

# Running the module from terminal
if __name__ == '__main__':
    fig = plt.figure()
    a=fig.add_subplot(1,2,1)
    img1 = mpimg.imread('uggla2.tif')
    imgplot =  plt.imshow(img1, cmap = cm.Greys_r)
    a.set_title('Uncompressed')
    img2 = jpeg_decode()
    a=fig.add_subplot(1,2,2)
    imgplot =  plt.imshow(img2, cmap = cm.Greys_r)
    a.set_title('Compressed')
    plt.show()

1 个答案:

答案 0 :(得分:0)

非常感谢Ali M. uint16数据类型一直都是错误的!这是它分别使用掩码和权重进行量化的方式: enter image description here