Fonctionnement de JPEG

par Joseph Razik, le 2019-10-18
Jpeg
InĀ [1]:
%pylab inline
Populating the interactive namespace from numpy and matplotlib
InĀ [2]:
import scipy.misc
from scipy.fftpack import dct, idct
InĀ [3]:
def decoupe_bloc(image, N = 8):
    l, c = image.shape
    
    # dƩcoupage en blocs de 8x8 pixels
    # tant pis pour les bords si la taille n'est pas multiple de 8
    # blocs = [image[i*8:(i+1)*8, j*8:(j+1)*8] for i in xrange(0, l/8) for j in xrange(0, c/8)]
    blocs = []
    for i in range(0,l//N):
        for j in range(0,c//N):
            blocs.append(image[i*N:(i+1)*N, j*N:(j+1)*N])

    return blocs, l//N, c//N
InĀ [4]:
def do_jpg(image, N = 32):
    l, c = image.shape
    
    # dƩcoupage en blocs de 8x8 pixels
    blocs, nb_bl, nb_bc = decoupe_bloc(image)

    # on fait la dct de chaque bloc
    dct_blocs = [dct(b, norm='ortho') for b in blocs]
    
    # quantification
    quantized_blocs = [((b//N).astype(int)*N).astype(float) for b in dct_blocs]
    
    return quantized_blocs, l//8, c//8    
    #return dct_blocs, l/8, c/8
    
InĀ [5]:
def invert_jpg(q_blocs, nb_bl, nb_bc):
    # dct inverse
    dct_blocs = [idct(b, norm='ortho') for b in q_blocs]
    
    # reconstruction de l'image
    image = reshape_im(dct_blocs, nb_bl, nb_bc)
    
    return image
InĀ [6]:
def reshape_im(blocs, nb_bl, nb_bc, N = 8):
    image = empty((nb_bl*N, nb_bc*N))
    for i in range(0, nb_bl):
        for j in range(0, nb_bc):
            image[i*N:(i+1)*N, j*N:(j+1)*N] = blocs[i*nb_bl + j]
    return image
InĀ [7]:
img = scipy.misc.lena()
print(img.shape)
f = imshow(img, cmap=cm.gray)
(512, 512)
InĀ [8]:
figure(figsize=(10,12))
for i in range(0,4):
    subplot(4, 4, i+1)
    imshow(img[0:8,8*i:8*(i+1)], cmap=cm.gray)
    title(i)
    subplot(4, 4, i+1+4)
    imshow(img[0:8,8*(i+60):8*(i+1+60)], cmap=cm.gray)
    title(i+60)

    subplot(4, 4, i+1+8)
    imshow(img[8:16,8*i:8*(i+1)], cmap=cm.gray)
    title(i+64)
    subplot(4, 4, i+1+4+8)
    imshow(img[8:16,8*(i+60):8*(i+1+60)], cmap=cm.gray)
    title(i+60+64)
InĀ [9]:
print(img.dtype)
img2 = img.astype(float)
print(img2.dtype)
b, nb_bl, nb_bc = decoupe_bloc(img2)
int64
float64
InĀ [10]:
img3 = reshape_im(b, nb_bl, nb_bc)
InĀ [11]:
figure(figsize=(10,12))
for i in range(0,4):
    subplot(4, 4, i+1)
    imshow(img3[0:8,8*i:8*(i+1)], cmap=cm.gray)
    title(i)
    subplot(4, 4, i+1+4)
    imshow(img3[0:8,8*(i+60):8*(i+1+60)], cmap=cm.gray)
    title(i+60)

    subplot(4, 4, i+1+8)
    imshow(img3[8:16,8*i:8*(i+1)], cmap=cm.gray)
    title(i+64)
    subplot(4, 4, i+1+4+8)
    imshow(img3[8:16,8*(i+60):8*(i+1+60)], cmap=cm.gray)
    title(i+60+64)
InĀ [12]:
imshow(img3, cmap=cm.gray)
Out[12]:
<matplotlib.image.AxesImage at 0x7efbfde69278>
InĀ [13]:
img_j, nb_bl, nb_bc = do_jpg(img2)
InĀ [14]:
imshow(reshape_im(img_j, nb_bl, nb_bc), cmap=cm.gray)
Out[14]:
<matplotlib.image.AxesImage at 0x7efbfdd94e80>
InĀ [15]:
img4 = invert_jpg(img_j, nb_bl, nb_bl)
InĀ [16]:
imshow(img4, cmap=cm.gray)
Out[16]:
<matplotlib.image.AxesImage at 0x7efbfdf02c18>
InĀ [17]:
from numpy.fft import fft; fft2, ifft2
def do_jpg_fft(image, N=32):
    l, c = image.shape
    
    # dƩcoupage en blocs de 8x8 pixels
    blocs, nb_bl, nb_bc = decoupe_bloc(image)

    # on fait la dct de chaque bloc
    dct_blocs = [fft2(b) for b in blocs]
    
    # quantification
    quantized_blocs = [((b//N).astype(int))*N for b in dct_blocs]
    
    return quantized_blocs, l//8, c//8    
    
InĀ [18]:
img_j_fft, nb_nl, nb_nc = do_jpg_fft(img2)
InĀ [19]:
def invert_jpg_fft(q_blocs, nb_bl, nb_bc):
    # dct inverse
    dct_blocs = [abs(ifft2(b,)) for b in q_blocs]
    
    # reconstruction de l'image
    image = reshape_im(dct_blocs, nb_bl, nb_bc)
    
    return image
InĀ [20]:
img5 = invert_jpg_fft(img_j_fft, nb_bl, nb_bl)
InĀ [21]:
imshow(img5, cmap=cm.gray)
Out[21]:
<matplotlib.image.AxesImage at 0x7efbfdef8a20>
InĀ [22]:
img6 = (img//32)*32
imshow(img6, cmap=cm.gray)
Out[22]:
<matplotlib.image.AxesImage at 0x7efc01ce1b70>
InĀ [23]:
def rgb2ycbcr(image):
    im = empty(image.shape)
    im[:,:,0] = 77*image[:,:,0] + 150*image[:,:,1] + 29*image[:,:,2]
    im[:,:,1] = ((-44*image[:,:,0] - 87*image[:,:,1]  + 131*image[:,:,2])//256 + 0.5)*256
    im[:,:,2] = ((131*image[:,:,0] - 110*image[:,:,1] - 21*image[:,:,3])//256 + 0.5)*256
    return im