1、概述
在日常生活中,我们有很多信息要处理,因为计算机中的存储空间是有限的,那么为了存储更多的内容,就要求我们用尽可能小的数据量来表达信息。这时候,图像压缩这一技术就显得尤为重要。
1.1 冗余
图像的数据表达之间存在着冗余,主要表现为图像中相邻像素间的相关性引起的空间冗余;图像序列中不同帧之间存在相关性引起的时间冗余;不同彩色平面或频谱带的相关性引起的频谱冗余等等。那么通过减小数据冗余,我们就可以达到图像压缩的目的。
1.2 图像压缩分类
图像压缩方法可分为有损图像压缩和无损图像压缩两种。
有损图像压缩:是对图像本身的改变,在保存图像时保留了较多的亮度信息,而将色相和色纯度的信息和周围的像素进行合并,合并的比例不同,压缩的比例也不同,由于信息量减少了,所以压缩比可以很高,图像质量也会相应的下降。典型的编码方式有有损预测编码、变换编码、小波编码等。
无损图像压缩:是对文件本身的压缩,和其它数据文件的压缩一样,是对文件的数据存储方式进行优化,采用某种算法表示重复的数据信息,文件可以完全还原,不影响文件内容,对于数字图像而言,也不会使图像细节有任何损失。主要的方法有行程编码、算数编码、无损预测编码等。
2 图像冗余
图像冗余类型可具体分为以下几种:
1、编码冗余 2、像素间相关性冗余 3、视觉冗余
2.1 编码冗余
2.1.1 定义
编码冗余:当所用码字大于最佳编码,我们就说它存在编码冗余。
2.2.2 变长编码
为了消除编码冗余,比较有用的操作是在编码时采用变长编码。
变长编码的原则:将高频率的图像值用低字长的码来表示,以此来可以减少图像的数据量。
•哈夫曼编码
哈夫曼编码是经常被用到的一种变长编码方式,其编码过程可以用下图来说明:
1)将信号按照出现的概率从大到小排序。
2)将概率最小的两个符号的概率相加,再次进行排序。
3)重复2)过程,直至只剩两个信号。
4)在线路的上方写1,下方写0,为信号编码。
from heapq import heapify, heappush, heappop
from itertools import count
def huffman(seq, frq):
num = count()
trees = list(zip(frq, num, seq))
heapify(trees)
while len(trees) > 1:
fa, _, a = heappop(trees)
fb, _, b = heappop(trees)
n = next(num)
heappush(trees, (fa+fb, n, [a, b]))
return trees[0][-1]
if __name__ == "__main__":
seq = "abcdefghi"
frq = [4, 5, 6, 9, 11, 12, 15, 16, 20]
print(huffman(seq,frq))
通过结果,我们可以简单的了解哈夫曼编码的过程。
2.2 像素间相关性冗余
像素间相关性冗余又称为空间冗余,是静态图像中存在的最主要的一种数据冗余。解决它的方法主要有行程编码、预测编码、变换域表达等。
● 行程编码的原理很简单:将一行中颜色值相同的相邻像素用一个计数值和该颜色值来代替。如aaaabbcddddd就可以写为4a2b1c5d。
● 预测编码是根据信号中存在的关联性,利用前一个或多个信号来预测下一个信号的值,然后对实际值和预测值的差进行编码。
2.3 视觉冗余
人类的视觉系统由于受到生理特征的限制,对图像的一些细微变化是看不到的,忽略这些变化后,图像仍被视为是完好的,把这些超出人类视觉范围的数据称为视觉冗余。
一般,我们减少视觉冗余的方法主要是对图像进行有损处理,在不影响视觉体验的前提下减少图像的数据。
3 压缩方法评价
为评价压缩方法的优劣,我们一般要有一个统一的评价标准。图像的还原度是评价压缩方法极为重要的标准之一。即将压缩后的图像进行还原,在压缩比相同时,原图像与还原图像之间的误差越小,压缩方法越好。
当进行无损压缩时,有时可以简单的采用压缩比这一标准对压缩方法进行评价。但当压缩方法是有损压缩时,很明显,这时候,我们就要对图像失真的程度进行评估,对图像的均方误差、信噪比等数据进行计算,全面的对压缩方法进行评估。
4 实例
import cv2
import matplotlib as mpl
import numpy as np
import matplotlib.pyplot as plt
def restore1(u, sigma, v, k):
m = len(u)
n = len(v)
a = np.zeros((m, n))
a = np.dot(u[:, :k], np.diag(sigma[:k])).dot(v[:k, :])
a[a < 0] = 0
a[a > 255] = 255
return np.rint(a).astype('uint8')
def SVD(frame, K=10):
a = np.array(frame)
# 由于是彩色图像,所以3通道。a的最内层数组为三个数,分别表示RGB,用来表示一个像素
u_r, sigma_r, v_r = np.linalg.svd(a[:, :, 0])
u_g, sigma_g, v_g = np.linalg.svd(a[:, :, 1])
u_b, sigma_b, v_b = np.linalg.svd(a[:, :, 2])
R = restore1(u_r, sigma_r, v_r, K)
G = restore1(u_g, sigma_g, v_g, K)
B = restore1(u_b, sigma_b, v_b, K)
I = np.stack((R, G, B), axis=2)
return I
if __name__ == "__main__":
mpl.rcParams['font.sans-serif'] = [u'simHei']
mpl.rcParams['axes.unicode_minus'] = False
frame = cv2.imread('d:/imdata/onion.png')
plt.subplot(121)
plt.imshow(frame)
I = SVD(frame, 10)
plt.subplot(122)
plt.imshow(I)
plt.show()
可以看出,当压缩比例较大时,压缩后图像就会变得模糊
5 总结
本章学习了图像压缩的原理,即图像中存在冗余,对不同的冗余种类及其压缩方法进行了介绍。图像压缩是我们日常信息传输过程中经常要用到的一种技术,是未来科技中不可缺少的一种技术。