当前位置: 首页 > news >正文

【图像处理基石】图像压缩有哪些经典算法?

在这里插入图片描述

图像压缩是减少图像数据量的技术,主要分为无损压缩(不丢失信息)和有损压缩(允许一定信息损失以换取更高压缩率)。以下是几种经典算法及其Python实现:

一、经典图像压缩算法简介

  1. 行程长度编码(RLE)
    无损压缩,适用于存在连续重复像素的图像(如线条图、图标)。原理是记录"像素值+连续出现次数"替代重复像素。

  2. 哈夫曼编码(Huffman Coding)
    无损压缩,基于像素值出现频率构建变长编码(高频值用短码),广泛用于JPEG、PNG等格式。

  3. 离散余弦变换(DCT)
    有损压缩,JPEG核心算法。将图像分块后转换到频率域,保留低频分量(视觉重要),丢弃高频分量(细节)。

  4. 小波变换(Wavelet Transform)
    有损/无损均可,JPEG 2000采用。相比DCT能更好保留边缘信息,压缩率更高。

二、Python实现示例

1. 行程长度编码(RLE)

适用于简单图像(如二值图),实现简单且压缩效果直观。

import numpy as np
from PIL import Imagedef rle_compress(image):"""将灰度图像压缩为RLE编码(列表形式:[(值, 长度), ...])"""# 将二维图像转为一维数组flat = image.flatten()if len(flat) == 0:return []compressed = []current_val = flat[0]count = 1for val in flat[1:]:if val == current_val:count += 1else:compressed.append((current_val, count))current_val = valcount = 1# 处理最后一组compressed.append((current_val, count))return compresseddef rle_decompress(compressed, shape):"""将RLE编码解压为图像"""flat = []for val, count in compressed:flat.extend([val] * count)# 恢复为原始形状return np.array(flat).reshape(shape)# 测试
if __name__ == "__main__":# 读取图像并转为灰度图img = Image.open("test_image.png").convert("L")  # 替换为你的图像路径img_array = np.array(img)print("原始图像形状:", img_array.shape)print("原始数据量:", img_array.size, "像素")# 压缩compressed = rle_compress(img_array)print("RLE压缩后数据量:", len(compressed), "组")# 解压decompressed = rle_decompress(compressed, img_array.shape)# 验证是否完全恢复(无损压缩)print("解压后与原始是否一致:", np.array_equal(img_array, decompressed))# 保存解压后的图像Image.fromarray(decompressed).save("rle_decompressed.png")
2. 哈夫曼编码(Huffman Coding)

基于频率的变长编码,适合像素值分布不均匀的图像。

import numpy as np
from PIL import Image
import heapq
from collections import defaultdict# 构建哈夫曼树节点
class HuffmanNode:def __init__(self, value, freq):self.value = value  # 像素值self.freq = freq    # 频率self.left = Noneself.right = None# 用于优先队列排序def __lt__(self, other):return self.freq < other.freq# 构建哈夫曼树
def build_huffman_tree(freq_dict):heap = [HuffmanNode(val, freq) for val, freq in freq_dict.items()]heapq.heapify(heap)while len(heap) > 1:left = heapq.heappop(heap)right = heapq.heappop(heap)# 合并节点(值为None表示内部节点)merged = HuffmanNode(None, left.freq + right.freq)merged.left = leftmerged.right = rightheapq.heappush(heap, merged)return heap[0] if heap else None# 生成哈夫曼编码表
def generate_code_table(root):code_table = {}def traverse(node, current_code=""):if node is None:return# 叶子节点(有像素值)if node.value is not None:code_table[node.value] = current_code if current_code else "0"return# 左子树加"0",右子树加"1"traverse(node.left, current_code + "0")traverse(node.right, current_code + "1")traverse(root)return code_table# 哈夫曼压缩
def huffman_compress(image):flat = image.flatten()# 统计频率freq_dict = defaultdict(int)for val in flat:freq_dict[val] += 1# 构建树和编码表root = build_huffman_tree(freq_dict)code_table = generate_code_table(root)# 编码数据(转为二进制字符串)encoded_bits = "".join([code_table[val] for val in flat])return encoded_bits, code_table, image.shape# 哈夫曼解压
def huffman_decompress(encoded_bits, code_table, shape):# 反转编码表(编码->值)reverse_table = {code: val for val, code in code_table.items()}current_code = ""flat = []for bit in encoded_bits:current_code += bitif current_code in reverse_table:flat.append(reverse_table[current_code])current_code = ""return np.array(flat).reshape(shape)# 测试
if __name__ == "__main__":img = Image.open("test_image.png").convert("L")img_array = np.array(img)print("原始图像形状:", img_array.shape)print("原始数据量:", img_array.size * 8, "比特(假设8位灰度)")# 压缩encoded_bits, code_table, shape = huffman_compress(img_array)print("哈夫曼压缩后数据量:", len(encoded_bits), "比特")print("压缩率:", len(encoded_bits)/(img_array.size * 8))# 解压decompressed = huffman_decompress(encoded_bits, code_table, shape)# 验证无损性print("解压后与原始是否一致:", np.array_equal(img_array, decompressed))Image.fromarray(decompressed).save("huffman_decompressed.png")
3. 离散余弦变换(DCT)

JPEG核心算法,有损压缩,通过丢弃高频分量减少数据量。

import numpy as np
from PIL import Image
from scipy.fftpack import dct, idct# JPEG标准亮度量化矩阵(用于有损压缩)
QUANTIZATION_MATRIX = 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.float32)def dct_compress(image, quant_matrix=QUANTIZATION_MATRIX):"""DCT压缩:分块->DCT->量化"""h, w = image.shape# 确保尺寸是8的倍数(JPEG分块大小为8x8)h_padded = ((h + 7) // 8) * 8w_padded = ((w + 7) // 8) * 8padded = np.pad(image, ((0, h_padded - h), (0, w_padded - w)), mode='constant')compressed = np.zeros_like(padded, dtype=np.int32)# 对每个8x8块进行处理for i in range(0, h_padded, 8):for j in range(0, w_padded, 8):block = padded[i:i+8, j:j+8]# 转换为[-128, 127](DCT通常基于零均值)block_shifted = block - 128# 2D DCT变换dct_block = dct(dct(block_shifted, axis=0, norm='ortho'), axis=1, norm='ortho')# 量化(除以量化矩阵并取整,核心压缩步骤)quant_block = np.round(dct_block / quant_matrix).astype(np.int32)compressed[i:i+8, j:j+8] = quant_blockreturn compressed, (h, w)  # 保留原始尺寸用于解压def dct_decompress(compressed, original_shape, quant_matrix=QUANTIZATION_MATRIX):"""DCT解压:反量化->IDCT->拼接"""h_padded, w_padded = compressed.shapeh, w = original_shapedecompressed = np.zeros_like(compressed, dtype=np.float32)# 对每个8x8块处理for i in range(0, h_padded, 8):for j in range(0, w_padded, 8):quant_block = compressed[i:i+8, j:j+8]# 反量化dct_block = quant_block * quant_matrix# 逆DCT变换block_shifted = idct(idct(dct_block, axis=0, norm='ortho'), axis=1, norm='ortho')# 恢复到[0, 255]block = np.round(block_shifted + 128).clip(0, 255).astype(np.uint8)decompressed[i:i+8, j:j+8] = block# 裁剪回原始尺寸return decompressed[:h, :w].astype(np.uint8)# 测试
if __name__ == "__main__":img = Image.open("test_image.png").convert("L")img_array = np.array(img)print("原始图像形状:", img_array.shape)# 压缩compressed, original_shape = dct_compress(img_array)# 解压(会有损失)decompressed = dct_decompress(compressed, original_shape)# 保存结果Image.fromarray(decompressed).save("dct_decompressed.png")print("DCT压缩解压完成(有损压缩,可能有画质损失)")

三、算法对比与应用场景

算法类型压缩率适用场景典型应用
RLE无损连续重复像素多的图像(图标)BMP、Fax格式
哈夫曼编码无损像素分布不均匀的图像JPEG、PNG、ZIP
DCT有损自然图像(人眼对细节不敏感)JPEG
小波变换有损/无损需要高压缩率+保留细节的场景JPEG 2000、医学图像

以上实现均为简化版本,实际工业级压缩(如JPEG)会结合多种算法(如DCT+哈夫曼编码)并优化细节(如色彩空间转换、熵编码)。


文章转载自:

http://1s6SAuvz.zqfks.cn
http://OJOexR4K.zqfks.cn
http://cl03Tf3V.zqfks.cn
http://ih1UzRuk.zqfks.cn
http://GuMtvEds.zqfks.cn
http://PCaL2SrL.zqfks.cn
http://dPzWU71e.zqfks.cn
http://siyCW3By.zqfks.cn
http://mEu2JqvS.zqfks.cn
http://xRzSBNbj.zqfks.cn
http://RoUTvkpC.zqfks.cn
http://OjrqGiYY.zqfks.cn
http://Z9cjadhM.zqfks.cn
http://aAFeozBs.zqfks.cn
http://RBAx0A2u.zqfks.cn
http://XtrWWtKk.zqfks.cn
http://ILNV9AFa.zqfks.cn
http://4DNNyR8i.zqfks.cn
http://O8K0ppnX.zqfks.cn
http://D6jttDR1.zqfks.cn
http://XX4whzrO.zqfks.cn
http://lkDtzOVL.zqfks.cn
http://geo3GDrN.zqfks.cn
http://Xp8k5B4J.zqfks.cn
http://o4BhRYsh.zqfks.cn
http://fWmfFmte.zqfks.cn
http://Q7OisQ89.zqfks.cn
http://BGsyEiQC.zqfks.cn
http://x5O7OIPP.zqfks.cn
http://RRV2vMdr.zqfks.cn
http://www.dtcms.com/a/379803.html

相关文章:

  • C语言实战:简单易懂通讯录
  • youte-agent部署(windows)
  • Python实现点云法向量各种方向设定
  • Linnux IPC通信和RPC通信实现的方式
  • apache实现LAMP+apache(URL重定向)
  • MongoDB 与 GraphQL 结合:现代 API 开发新范式
  • k8s-临时容器学习
  • uni-app 根据用户不同身份显示不同的tabBar
  • ubuntu18.04安装PCL1.14
  • Ubuntu 系统下 Anaconda 完整安装与环境配置指南(附常见问题解决)
  • 网络链路分析笔记mtr/traceroute
  • 在 Ubuntu 系统中利用 conda 创建虚拟环境安装 sglang 大模型引擎的完整步骤、版本查看方法、启动指令及验证方式
  • 基带与射频的区别与联系
  • 《企业安全运营周报》模板 (极简实用版)​
  • opencv基于SIFT特征匹配的简单指纹识别系统实现
  • Node.js 操作 Elasticsearch (ES) 的指南
  • 使用tree命令导出文件夹/文件的目录树( Windows 和 macOS)
  • Spring缓存(二):解决缓存雪崩、击穿、穿透问题
  • LabVIEW加载 STL 模型至 3D 场景 源码见附件
  • Tessent_ijtag_ug——第 4 章 ICL 提取(2)
  • 前端WebSocket实时通信实现
  • 2025年- H133-Lc131. 反转字符串(字符串)--Java版
  • 萨顿四条原则
  • NumPy 2.x 完全指南【三十八】伪随机数生成器
  • GitHub 热榜项目 - 日榜(2025-09-12)
  • O3.3 opencv指纹识别
  • 在线会议系统是一个基于Vue3 + Spring Boot的现代化在线会议管理平台,集成了视频会议、实时聊天、AI智能助手等多项先进技术。
  • 每日一算:打家劫舍
  • MemGPT: Towards LLMs as Operating Systems
  • MySQL与PostgreSQL核心区别对比