文章目录
前言
图像压缩是一种减少描绘一幅图像所需数据量的技术和科学。
8.1 基础知识
1.数据压缩:减少表示给定信息量所需数据量的处理(数据是信息的传输手段)。
2.如果我们令b和
b
’
b^’
b’代表相同信息的两种表示中的比特数(或信息携带单元),那么用b比特表示的相对数据冗余R是
R
=
1
−
1
/
C
R=1-1/C
R=1−1/C
其中C通常成为压缩率,定义为
C
=
b
/
b
′
C=b/b'
C=b/b′
8.1.1 编码冗余
存储图像时我们会将其编码,如果编码所包括的比特数比图片本身比特数还要多,就说它是编码冗余的,例如当用自然二进吗表示一幅图像灰度时,编码冗余几乎总是存在的。
8.1.2 空间和时间冗余
空间冗余图像中出现许多相同的部分,或者一个像素可由其相邻像素推断出来,那么它的视觉贡献的大多是就是冗余的;时间冗余视频中不同时间出现的帧相同,这里都说它信息重复,出现冗余。
8.1.3不相关信息
对人类的视觉系统来说有些信息无法被识别或者与用途无关,从没有被利用的意义上来看,它就是冗余的。
8.1.4 图像信息的度量
1.概率为P(E)的随机事件E包含
I
(
E
)
=
log
1
P
(
E
)
=
−
log
P
(
E
)
I(E)=\log\frac{1}{P(E)}=-\log P(E)
I(E)=logP(E)1=−logP(E)
单位的信息,式子中对数的底决定了度量信息所用的单位,如果
P
(
E
)
=
1
/
2
P(E)=1/2
P(E)=1/2,由式子可知
I
(
E
)
=
1
I(E)=1
I(E)=1,即当两个概率相等的事件发生时,传达的信息量为1比特。
2.从一个可能事件的离散集合{a1,a2,…,aj},给定一个统计独立随机事件的信源,与该集合相联系的概率为{P(a1),P(a2),…,P(aj)},则每个信源输出的平均信息称为该信源的熵,即
H
=
−
∑
j
=
1
j
P
(
a
j
)
log
P
(
a
j
)
H=-\sum_{j=1}^{j}P(a_j)\log P(a_j)
H=−j=1∑jP(aj)logP(aj)
一幅图像中熵的数量和信息与直觉相差甚远。
3.山农第一定理(无噪声编码定理):
山农使用一个单一码字(而不是每个信源符号一个码字)考察了n个连续信号源符号表示的组合,并证明了
lim
n
→
∞
[
L
a
v
g
.
n
n
]
=
H
\lim\limits_{n\to\infty}\bigg[\frac{L_{avg.n}}{n}\bigg]=H
n→∞lim[nLavg.n]=H
式中
L
a
v
g
,
n
L_{avg,n}
Lavg,n是表示所有n重符号组所需编码符号的平均数。式子告诉我们,
L
a
v
g
,
n
L_{avg,n}
Lavg,n可用单一符号源的无限扩展编码任意接近H。也就是,用每信源符号H信息单位的平均来表示零记忆信源的输出是可能的。
8.1.5 保真度准则
评估图像信息丢失的两类准则:
(1)客观保真度准则:当信息损失可以表示为压缩处理的输入和输出的数学函数时,用均方根误差度量,可写为
e
rms
=
[
1
M
N
∑
x
=
0
M
−
1
∑
y
=
0
N
−
1
[
f
^
(
x
,
y
)
−
f
(
x
,
y
)
]
2
]
1
/
2
e_{\text{rms}}=\bigg[\frac{1}{MN}\sum_{x=0}^{M-1}\sum_{y=0}^{N-1}\bigg[\hat{f}(x,y)-f(x,y)\bigg]^{2}\bigg]^{1/2}
erms=[MN1x=0∑M−1y=0∑N−1[f^(x,y)−f(x,y)]2]1/2
(2)主观保真度准则:向观察者显示的压缩图像,并将他们的评估结果进行平均。
8.1.6 图像压缩模型
图像压缩系统是由两个不同的功能部分组成的一个编码器和 一个解码器,编码器执行压缩操作.解码器执行解压缩的互补操作
1.编码或压缩过程:
(1)映射器把 f(x,…)变换为设计来降低空间和时间冗余的形式(通常不可见),该操作通常是可逆的,并且可能会也可能不会直接减少表示图像所需的数据量(处理时间冗余和空间冗余)。
(2)量化器根据预设的保真度准则来降低映射器输出的精度,其目的是排除压缩表示的无关信息,该操作是不可逆的(去除不相关信息)。
(3)信源编码处理最后的阶段,符号编码器生成一个定长编码或变长编码
来表示盘化器的输出,并根据该编码来变换输出,该操作是可逆的(处理编码冗余)。
2.解码或解压缩过程:解码器包括一个符号解码器和一个反映射器,它们以相反的顺序执行编码器的符号编码器和映射器的反操作。
8.1.7 图像格式、容器和压缩标准
1.图像格式:组织和存储图像数据的标准方法。
2.容器:类似于文件格式,但处理多种类型的图像数据。
3.压缩标准:对压缩和解压缩图像定义了过程,也就是定义减少一幅图像所需数据量的过程。
8.2 一些基本压缩方法
8.2.1 霍夫曼编码
1.过程:
(1)通过对所考虑符号的概率进行排序,并将具有最小概率的符号合并为符号来替代下次信源化简过程中的符号。
(2)对每个化简后的信源进行编码,从最小的信源开始,并直到遍历原始信源。
2.特点:
(1)瞬时的:编码符号串中的每个码字无需参考后续符号就可以进行编码。
(2)唯一可解码的:任何编码符号串只能以一种方式进行解码。
8.2.2 Golomb编码
给定一个非负整数n和一个正整数除数m>0后,表示为Gm(n)的n关于m的Golomb编码是商[n/m]的一元编码和n modm的二进制表示的一个合并。G(n)的构建如下:
(1)形成商⌊n/m⌋的一元编码(整数q的一元编码定义为q个1紧跟着一个0)。
(2)令
k
=
⌈
l
o
g
2
m
⌉
,
c
=
2
k
−
m
,
r
=
n
m
o
d
m
k = ⌈ log_2 m ⌉ , c = 2^k − m , r = nmod m
k=⌈log2m⌉,c=2k−m,r=nmod m,并计算截短的余数r’,例如,使其满足
r
′
=
{
r
截短之
k
−
1
比特
,
0
⩽
r
<
c
r
+
c
截
短至
k
比特
,
其他
r'=\left\{\begin{array}{ll}r截短之k-1比特\mathbb,\quad0\leqslant r<c\\ r+c\mathbb截短至k比特,\quad\mathbb{其他}\\ \end{array}\right.
r′={r截短之k−1比特,0⩽r<cr+c截短至k比特,其他
(3)连接步骤1和步骤2的结果。
Golomb编码只能用于非负整数,当被表示的整数具有概率质量函数的几何分布时为最佳
8.2.3 算术编码
算术编码生成的是非快码,信源符号与码字之间不存在一一对应的关系,这个码字本身定义了一个介于0和1之间的实数间隔。当消息中的符号数量增加时,用于表示消息的间隔会变小,而表示该间隔所需的信息单位(假设为比特)的数量则会变大。消息的每个符号根据其出现的概率来减小该区间的大小。
算术编码器在要求表示被编码符号平均码字符号数最小的情形下是最佳的
8.2.4 LZW编码
LZW编码将定长码字分配给变长信源符号,不需要编码符号出现的概率和先验知识,在编码过程的开始阶段,先构造一个包含被编码信源符号的码书或字典,当编码器顺序的地分析图像像素时,不在字典中的灰度序列被放置在算法确定的位置(即下一个未用的位置)。
8.2.5 行程编码
行程编码技术是沿其行(或列)重复灰度的图像,通常可用相同灰度的行程表示为行程对来压缩,其中每个行程对指定一个新灰度的开始和具有该灰度的连续像素的数量。
实验:行程编码图像压缩
代码:
import numpy as np
import matplotlib.pyplot as plt
import cv2 as cv
def show(img):
if img.ndim == 2:
plt.imshow(img, cmap='gray')
else:
img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
plt.imshow(img)
plt.show()
##彩色图像灰度化
image = cv.imread('pic/sea.jpg')
show(image)
grayimg = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
show(grayimg)
rows, cols = grayimg.shape
image1 = grayimg.flatten() #把灰度化后的二维图像降维为一维列表
#print(len(image1))
#二值化操作
for i in range(len(image1)):
if image1[i] >= 127:
image1[i] = 255
if image1[i] < 127:
image1[i] = 0
data = []
image2 = []
count = 1
#行程压缩编码
for i in range(len(image1)-1):
if (count == 1):
image2.append(image1[i])
if image1[i] == image1[i+1]:
count = count + 1
if i == len(image1) - 2:
image2.append(image1[i])
data.append(count)
else:
data.append(count)
count = 1
if(image1[len(image1)-1] != image1[-1]):
image2.append(image1[len(image1)-1])
data.append(1)
#压缩率
ys_rate = len(image2)/len(image1)*100
print('压缩率为' + str(ys_rate) + '%')
#行程编码解码
rec_image = []
for i in range(len(data)):
for j in range(data[i]):
rec_image.append(image2[i])
rec_image = np.reshape(rec_image,(rows,cols))
show(rec_image)
原图:
原图灰度图:
形成编码压缩后二值图像:
对比图像可以看出,压缩后图像的大致轮廓还是可以看出。
8.2.6 基于符号的编码
在基于符号或记号的编码中,图像被表示为多幅频繁发生的子图像的一个集合,称为符号。每个这样的符号都存储在一个符号字典中,且该图像以一个三元组{(x1,y1,t1),(x2,y2,t2),…}的集合来编码,其中每个(xi,yi)对规定了图像中的一个符号的位置,而记号ti是该符号或子图像在字典中的地址。
8.2.7 比特平面编码
比特平面编码把一幅多级的(彩色或单色)图像分解为一系列二值图像,并使用几种熟知的二值压缩方法之一来压缩每幅二值图像。
比特平面编码通常限于6比特/像素或更少比特/像素的图像,它的唯一特性是连续码字只有一个比特位不同
8.2.8 块变换编码
1.块变换编码技术将图像分成大小相等且不重叠的小块,并使用二维变换单独处理这些块。
变换处理的目的是对每幅子图像中的像素进行去相关,或用最少的数量的变换系数包含尽可能多的信息。在量化阶段,以一种预定义的方式有选择性地消除或更粗略地量化那些携带最少信息的系数,这些系数对重建子图像信息的质量影响最小。
2.变换的选择:WHT、DCT、DFT、KLT变换。DCT的信息携带能力要比DFT和WHT的信息携带能力强,用单片集成电路就可实现,可将最多信息装入最小系数中,并且在子图像的边界变得可见时,可使出现的成为块缺陷的块效应最小化,最佳的变换是KLT变换,但是KLT变换时依赖于数据的,
3.子图像尺寸选择:随着子图像尺寸的增加,结果中普遍存在的快效应减少了。
4.比特分配:区域编码(保留的系数根据最大方差选择)、阈值编码(保留的系数根据最大幅度选择)
8.2.9 预测编码
预测编码不需要较大的计算开销就可实现较好的压缩效果,并且可以是无误差的或有损的压缩。
预测编码通过消除紧邻像素在空间和时间上的冗余来实现,仅对每个像素中的新信息进行提取和编码,一个像素的新信息定义为该像素的实际值与预测值之间的差。
8.2.10 小波编码
小波编码基于以下概念:对图像像素解除相关的变换系数进行编码,比对原图像像素本身进行编码的效率更高。如果变换的基函数(此时为小波函数)将大多数重要的可视信息包装到少量系数中,则剩下的系数可被粗略地量化或截取为零,而图像几乎没有失真。
8.3 数字图像水印
水印分为可见水印和不可见水印,水印在版权识别、用户识别或指纹、著作权认定等方法有很重要的作用,现在水印技术正变得越来越重要。
实验:添加水印
代码:
import cv2
import matplotlib.pyplot as plt
import numpy as np
img = cv.imread('pic/sea.jpg')
show(img)
img = img[:, :, [2, 1, 0]]
img_water = cv.imread('pic/shuiyin.png')# 添加的水印
img_water = img_water[:, :, [2, 1, 1]]
img_ = img.copy()
for x in range(img_water.shape[0]):
for y in range(img_water.shape[1]):
img_[x][y][0:3] = 0.3 * img_[x][y][0:3] + 0.7 * img_water[x][y][0:3]
plt.figure(dpi = 120)
plt.subplot(121)
plt.imshow(img)
plt.title("Origin picture")
plt.subplot(122)
plt.imshow(img_)
plt.title("Digital Watermark(α=0.7)")
plt.tight_layout()
plt.show()
原图:
水印:
添加后效果:
我们可以通过调节参数大小来设置可见水印透明度。