import numpy as np
import cv2
from scipy.fft import dct, idct
# ── Chargement Sécurisé de l'Image de la Caméra (skimage) ─────────────────────────
try:
from skimage import data
img_gray = data.camera()
except ImportError:
import subprocess
subprocess.run(["pip", "install", "scikit-image", "-q"])
from skimage import data
img_gray = data.camera()
# Redimensionne légèrement en 256x256 pour maintenir le standard et la vitesse des tests précédents
img_gray = cv2.resize(img_gray, (256, 256))
# ── Table de quantification de luminance (standard JPEG) ────────────────────────────
Q_luma = np.array([
[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]
], dtype=np.float64)
def dct2(bloco):
"""DCT-II 2D orthogonal (séparable)."""
return dct(dct(bloco.T, norm='ortho').T, norm='ortho')
def idct2(coefs):
"""IDCT-II 2D orthogonal."""
return idct(idct(coefs.T, norm='ortho').T, norm='ortho')
def jpeg_compress_block(bloco, Q_table):
"""DCT → quantification → déquantification → IDCT en bloc 8×8."""
C = dct2(bloco.astype(np.float64) - 128)
Cq = np.round(C / Q_table) * Q_table # quantifie et déquantifie
return np.clip(idct2(Cq) + 128, 0, 255)
def jpeg_quality_compress(img, qualidade=50):
"""JPEG simplifié : compresse l'image entière par blocs 8×8."""
if qualidade < 50:
escala = 5000 / qualidade
else:
escala = 200 - 2 * qualidade
# Corrigé de 'scala' à 'escala'
Q = np.clip(np.round(Q_luma * escala / 100), 1, 255)
h, w = img.shape
result = np.zeros_like(img, dtype=np.float64)
for r in range(0, h-7, 8):
for c in range(0, w-7, 8):
result[r:r+8, c:c+8] = jpeg_compress_block(img[r:r+8, c:c+8], Q)
return result.astype(np.uint8)
# ── Comparaison des facteurs de qualité ───────────────────────────────────────
qualidades = [10, 25, 50, 75, 90]
imgs_jpeg = [img_gray]
titles_jpeg = ["Original\n(Cameraman)"]
for q in qualidades:
rec = jpeg_quality_compress(img_gray, qualidade=q)
psnr = cv2.PSNR(img_gray, rec)
imgs_jpeg.append(rec)
titles_jpeg.append(f"Q={q}\nPSNR={psnr:.1f}dB")
mm.show(imgs_jpeg, titles=titles_jpeg, cols=3, figsize=(14, 10))