介绍一下JPEG压缩的原理和步骤,以及块效应的知识和如何消除,最后用Python实现JPEG的手动实现(不调用库函数)和用滤波消除块效应(手动实现,不调用库函数)
时间: 2024-04-29 16:22:20 浏览: 188
JPEG压缩是一种常用的图像压缩方式,其基本原理是利用人眼对图像中高频信息的不敏感性,通过去除图像高频部分信息来实现对图像的压缩。JPEG压缩主要分为以下三步:
1. 采样:将图像从RGB色彩空间转化为YCbCr色彩空间,并对Cb和Cr分量进行降采样(通常为4:2:0或4:2:2),降低无用信息。
2. 变换:利用离散余弦变换(DCT)对每个8x8的图像块进行变换,将空间域中的图像转换为频率域中的图像,这一步可去除冗余信息。
3. 量化:将DCT变换后的系数进行量化,将系数用较少的比特表示,达到压缩的目的。
由于JPEG压缩中采用的是8x8的块处理,因此会出现块效应现象,即在相邻块之间可能会出现明显的颜色差异。解决块效应的方法主要有两种:一是使用窗口函数,对块进行加权平均;二是使用滤波器,对图像进行平滑处理。
下面是用Python手动实现JPEG压缩和解压缩的步骤,以及使用均值滤波消除块效应的代码:
```python
import numpy as np
import cv2
# JPEG压缩过程
def jpeg_compress(img):
# 采样
img_yuv = cv2.cvtColor(img, cv2.COLOR_BGR2YUV)
img_y, img_u, img_v = cv2.split(img_yuv)
img_u = cv2.resize(img_u, (img.shape[1] // 2, img.shape[0] // 2), interpolation=cv2.INTER_AREA)
img_v = cv2.resize(img_v, (img.shape[1] // 2, img.shape[0] // 2), interpolation=cv2.INTER_AREA)
# 变换
img_y_blocks = [np.zeros((8, 8)) for i in range(img_y.shape[0] // 8 * img_y.shape[1] // 8)]
idx = 0
for i in range(0, img_y.shape[0], 8):
for j in range(0, img_y.shape[1], 8):
img_y_blocks[idx] = cv2.dct(img_y[i:i+8, j:j+8].astype(np.float64))
idx += 1
# 量化
q_table = 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]])
for i in range(len(img_y_blocks)):
img_y_blocks[i] = np.round(img_y_blocks[i] / (q_table * 8))
# 返回压缩后的数据
return img_y_blocks, img_u, img_v, q_table
# JPEG解压缩过程
def jpeg_decompress(img_y_blocks, img_u, img_v, q_table):
# 逆量化
for i in range(len(img_y_blocks)):
img_y_blocks[i] = img_y_blocks[i] * (q_table * 8)
# 逆变换
img_y = np.zeros((len(img_y_blocks) * 8, 8))
idx = 0
for i in range(0, img_y.shape[0], 8):
for j in range(0, img_y.shape[1], 8):
img_y[i:i+8, j:j+8] = cv2.idct(img_y_blocks[idx]).astype(np.float64)
idx += 1
# 逆采样
img_u = cv2.resize(img_u, (img_y.shape[1] // 2, img_y.shape[0] // 2), interpolation=cv2.INTER_CUBIC)
img_v = cv2.resize(img_v, (img_y.shape[1] // 2, img_y.shape[0] // 2), interpolation=cv2.INTER_CUBIC)
img_yuv = cv2.merge([img_y, img_u, img_v])
img_bgr = cv2.cvtColor(img_yuv, cv2.COLOR_YUV2BGR)
return img_bgr
# 消除块效应
def remove_block_effect(img):
# 均值滤波
img_u = cv2.blur(img[:, :, 1], (8, 8))
img_v = cv2.blur(img[:, :, 2], (8, 8))
img_yuv = cv2.merge([img[:, :, 0], img_u, img_v])
img_bgr = cv2.cvtColor(img_yuv, cv2.COLOR_YUV2BGR)
return img_bgr
# 测试代码
img = cv2.imread('test.jpg')
img_y_blocks, img_u, img_v, q_table = jpeg_compress(img)
img_decompressed = jpeg_decompress(img_y_blocks, img_u, img_v, q_table)
img_decompressed = remove_block_effect(img_decompressed)
cv2.imwrite('test_decompressed.jpg', img_decompressed)
```
在上面的代码中,我们使用了OpenCV库提供的DCT和IDCT函数,以及均值滤波函数。在实际应用中,为了提高压缩和解压缩的速度,我们可以使用快速DCT算法(如快速傅里叶变换)来代替DCT函数,并使用更高效的滤波算法来去除块效应。
阅读全文