数字图像处理100问—36 JPEG 压缩——第一步:离散余弦变换(Discrete Cosine Transformation)

  • Post author:
  • Post category:其他

提示:内容整理自:https://github.com/gzr2017/ImageProcessing100Wen
CV小白从0开始学数字图像处理

36 JPEG 压缩——第一步:离散余弦变换(Discrete Cosine Transformation)

imori.jpg灰度化之后,先进行离散余弦变换,再进行离散余弦逆变

离散余弦变换(Discrete Cosine Transformation)是一种使用下面式子计算的频率变换:

T = 8
F(u,v) = 1 / T * C(u)C(v) * Sum_{y=0:T-1} Sum_{x=0:T-1} f(x,y) cos((2x+1)u*pi/2T) cos((2y+1)v*pi/2T)

离散余弦逆变换(Inverse Discrete Cosine Transformation)是离散余弦变换的逆变换,使用下式定义:

f(x,y) = 1 / T * C(x)C(y) * Sum_{u=0:T-1} Sum_{v=0:T-1} F(u,v) cos((2x+1)u*pi/2T) cos((2y+1)v*pi/2T)

在这里我们先将图像分割成8x 8的小块,在各个小块中使用离散余弦变换编码,使用离散余弦逆变换解码,这就是 JPEG 的互逆过程。现在我们也同样地,把图像分割成8x 8的小块,然后进行离散余弦变换和离散余弦逆变换。

代码如下:

1.引入库

CV2计算机视觉库

import cv2
import numpy as np
import matplotlib.pyplot as plt

2.读入数据

img = cv2.imread("imori.jpg").astype(np.float32)
H, W, C = img.shape

3.灰度化

gray = 0.2126 * img[..., 2] + 0.7152 * img[..., 1] + 0.0722 * img[..., 0]

4.DCT

T = 8
K = 8
X = np.zeros((H, W), dtype=np.float32)

#indx = np.tile(np.arange(T), (T, 1))
#indy = np.arange(T).repeat(T).reshape(T, -1)
#dct = np.ones_like(indx, dtype=np.float32)
#dct[:, 0] /= np.sqrt(2)
#dct[0] /= np.sqrt(2)

def w(x, y, u, v):
    cu = 1.
    cv = 1.
    if u == 0:
        cu /= np.sqrt(2)
    if v == 0:
        cv /= np.sqrt(2)
    theta = np.pi / (2 * T)
    return (( 2 * cu * cv / T) * np.cos((2*x+1)*u*theta) * np.cos((2*y+1)*v*theta))
    
for yi in range(0, H, T):
    for xi in range(0, W, T):
        for v in range(T):
            for u in range(T):
                for y in range(T):
                    for x in range(T):
                        X[v+yi, u+xi] += gray[y+yi, x+xi] * w(x,y,u,v)
                """
                _x = indx + xi * T
                _y = indy + yi * T
                _u = u + xi * T
                _v = v + yi * T
                X[_v, _u] = np.sum(C * gray[_y, _x] * np.cos((2*indx+1)*u*np.pi/(2*T)) * np.cos((2*indy+1)*v*np.pi/(2*T)))
                """

5.IDCT


out = np.zeros((H, W), dtype=np.float32)

for yi in range(0, H, T):
    for xi in range(0, W, T):
        for y in range(T):
            for x in range(T):
                for v in range(K):
                    for u in range(K):
                        out[y+yi, x+xi] += X[v+yi, u+xi] * w(x,y,u,v)
                """
                _u = indx + xi * T
                _v = indy + yi * T
                _x = x + yi * T
                _y = y + xi * T
                out[_y, _x] = np.sum(C * X[_v, _u] * np.cos((2*x+1)*indx*np.pi/(2*T)) * np.cos((2*y+1)*indy*np.pi/(2*T))) * 4. / (T ** 2)
                """
out[out>255] = 255
out = np.round(out).astype(np.uint8)

6.保存结果

cv2.imshow("result", out)
cv2.waitKey(0)
cv2.imwrite("out.jpg", out)

7.结果

在这里插入图片描述在这里插入图片描述


版权声明:本文为cv_rsrc原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。