我尝试使用Numpy在Python中压缩灰度图像。我尝试了两种不同的量化方法:应用遮罩并按预定义的权重进行划分,但在这两种情况下,压缩图像的值都太高了。
原始图像和处理过的图像在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()