JPEG2000中图像单元的定义
JPEG2000 中包括许多既定义的单元,主要有:
1. 画布
2. 分片( Tile )
3. 子带( Subband )
4. 分辨率层( Resolution )
5. 分区 (Precinct)
6. 分区分割( Precinct partition, 在 kakadu 中叫 precinct band )
7. 码块( code block )
8. 包 (packet
9. 层( layer )
10. 分量( Component )
11. 区域( Region )
12. 渐进性( Progressive )
下面来一一解释这些概念。
画布
画布是整个图像的参考网格,可以想象我们的图像就在这张画布上显示的;但必须明确一点就是,图像的原点未必就正好在画布的原点。可以形象的描述画布为许多网格,如下:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
这里需要注意的另一个问题是:图像的值并不是正好填充在每个网格上,可能以一定的间隔填充的。
在这里假设所有的分量采样间隔 S 都是 1 。
分量
这里的分量与我们通常所说的颜色分量是相同的,例如:对于 RGB 表示的像素值图像,有三个分量,如果是 24bit 的 RGB ,那么每个分量使用 8bit 来表示。当然整个图像是由三个分量组成,因此每个分量都在画布上,而分量的填充间隔可以不一样。例如:
上图中包含两个分量的图像,但第一个分量(红色)的采样间隔是 4 ,第二个是 2 。对于我们常用的图像,分量采样的间隔( Subsampling )是一样的。
图像的在画布中使用两对坐标来表示位置:( E1 , F1 );( E2 , F2 )
由于分量的采样因子(间隔)不一样,所以每个分量的区域界限是不同的,一般可表示为:
Ec = Ei/Si
贴片(分片)
JPEG2000 引入分片这个概念是为了处理复合文档,因为有些区域包含图形,有些区域包含文字,分片之后对不同的区域采用不同的处理方法。例如:文字区域不需要 DWT ,直接压缩等。
对于一般压缩自然图像采用一个分片就足够了。
这里的分片与图像并非是坐标对齐的,其用 O1 和 O2 来表示原点在画布上的位置,用 T1 和 T2 表示每个分片的大小;每个分片必须与图像的区域有重叠。
使用 N1 和 N2 来表示分片的 Y 方向和 X 的数量,使用 t1 和 t2 来表示坐标,
其中 0<=t1<N1, 并且 0<=t2<N2 。
每个贴片在都有一个唯一的标示符号,其通过 t 来表示,计算如下:
t = t2+t1N2
注意:非 0 原点的目的方便于图像的裁剪处理。
贴片在画布中的区域
每个贴片在画布中对应的区域为:
E1_t = max (E1, O1+t1*T1); F1_t = min (F1, O1+t1*T1)
E2_t = max (E2, O2+t2*T2) F2_t = min (F2, O2+t2*T2)
O = ( 0 , 0 )
如果 E1 = 100 , E2 = 100 , F1 = 1000 , F2 = 1000
O1 = 10 , O2 = 10 , T1 = 100 , T2 = 100
因此:
N1 = ( F1-O1 ) /100 = 9 , N2 = 9
那么 E1_t = max(100,10+t1*100), F1_t = min(1000,10+t2*100)
如果 t1 = 2, t2 = 3; 那么
该贴片的唯一表示为: t = t2+t1*N2 = 3+2*9= 21
E1_t = max (100, 10+2*100) = 210 F 1_t = min (1000, 10+3*100) = 310
E2_t = max (100, 10+2*100) = 210 F 2_t = min (1000, 10+3*100) = 310
当然,如果每个贴片对应到分量上时情况有所不同,因为不同分量的采样间隔不一样导致有的贴片并不包含分量值。
JPEG2000 中, DWT 变换是针对每个贴片分量的,如果有三个分量,那么每个分量调用 DWT 变换。
子带
子带是进行 DWT 子带变换的产物,这里以 2D 树结构为例来说明子带变换产生的子带。图中的每次 DWT 变换在 LLn 子带上进行,最初的图像可以认为是 LL0 子带,对 LL(n-1) 子带进行变化得到 n 级别的子带 4 个,分别是 LLn, HLn, LHn, HHn 。
HL 子带是水平高通滤波器产生的结果,因此水平方向上高频图像区域被保存了下来。
LH 子带是垂直高通滤波器产生的结果,因此垂直方向上高频图像区域被保存下来。
HH 是垂直和水平方向上都是高通的结果,因此是对角线方向的图像特性被保存下来。
LL 是图像的低频部分,也是图像的低分辨率版本。
LL3 |
HL3 |
HL2 |
HL1 |
|
LH3 |
HH3 |
|||
LH2 |
HH2 |
|||
LH1 |
HH1 |
|||
子带在画布中的区域
E1_t_b = (E1_t – 2 d-1 b1)/2 d E2_t_b = (E2_t – 2 d-1 b2)/2 d
F1_t_b = (F1_t- 2 d-1 b1)/2 d F2_t_b = (F2_t- 2 d-1 b2)/2 d
其中 d 的取值范围是 1 到 D ( DWT LEVEL );而 b1 和 b2 的取值由子带决定:
LL 子带中: b1= b2= 0
HL 子带中: b1= 0 ; b2= 1
LH 子带中: b1= 1 ; b2= 0
HH 子带中: b1= 1 ; b2= 1
这里按照上面贴片的位置来计算子带在画布中区域。这里假设是 DWT 的 LEVEL 2 ,也就是 d 等于 2 。
由于 E1_t = E2_t = 210, F1_t = F2_t = 310 ,那么对于 LL 子带:
E1_t_b_LL = (210-2 2-1 *0)/2 2 = 210/4 = 53
E2_t_b_LL = 53
F1_t_b_LL = (310-2 2-1 *0)/2 2 = 78
F2_t_b_LL = 78
对于 HL 子带:
E1_t_b_HL= (210-2 2-1 *0/2 2 = 210/4 = 53
E2_t_b_HL= (210-2 2-1 *1)2 2 = 208/4 = 52
F1_t_b_HL = (310-2 2-1 *0)/2 2 = 78
F2_t_b_HL = (310-2 2-1 *1)/2 2 = 77
对于 LH 子带:
E1_t_b_LH= (210-2 2-1 *1/2 2 = 210/4 = 52
E2_t_b_ LH = (210-2 2-1 *0)2 2 = 208/4 = 53
F1_t_b_ LH = (310-2 2-1 *1)/2 2 = 77
F2_t_b_HL = (310-2 2-1 *0)/2 2 = 78
对于 HH 子带:
E1_t_b_ HH = (210-2 2-1 *1/2 2 = 210/4 = 52 E2_t_b_HH = 52
F1_t_b_ HH = (310-2 2-1 *1)/2 2 = 77 F2_t_b_ HH = (310-2 2-1 *1)/2 2 = 77
上面的数都是取整数的结果,超出的部分取 1 。
实际上我们可以计算 d=1 时的 LL 子带边界就知道了:
E1_t_b_LL = (210-2 1-1 *0)/2 1 = 210/2 = 105
E2_t_b_LL = 105
F1_t_b_LL = (310-2 1-1 *0)/2 1 = 155
F2_t_b_LL = 155
可以看到 d=2 的子带和 d=1 的各子带之间的关系:
W_HL= F2_t_b_HL - E2_t_b_HL = 77-52 = 25
H_HL= F1_t_b_HL – E1_t_b_HL = 78-53 = 25
W_LH = F2_t_b_LH - E2_t_b_LH = 78-53 = 25
H_ LH = F1_t_b_ LH – E1_t_b_ LH = 77-52 = 25
W_HH = F2_t_b_HH –E2_t_b_HH = 77-52 = 25
H_HH = F1_t_b_HH – E1_t_b_HH = 77-52 = 25
W_LL = 78-53 = 25 H_LL = 78-53 = 25
我可以看到对于 d= 1 的 LL 子带宽度与 d=2 的 W_LL+W_HL 以及 W_LH+W_HH; 高度也是同样的。
下面来看 d= 3 的各子带参数:
对于 LL 子带有:
E1_t_b_LL = (210-2 3-1 *0)/2 3 = 210/8 = 27
E2_t_b_LL = 27
F1_t_b_LL = (310-2 3-1 *0)/2 3 = 39
F2_t_b_LL = 39
对于 HL 子带:
E1_t_b_HL= (210-2 3-1 *0/2 3 = 210/8 = 27
E2_t_b_HL= (210-2 3-1 *1)2 3 = 206/8 = 26
F1_t_b_HL = (310-2 3-1 *0)/2 3 = 39
F2_t_b_HL = (310-2 3-1 *1)/2 3 = 39
对于 LH 子带:
E1_t_b_LH= (210-2 3-1 *1/2 3 = 206/8 = 26
E2_t_b_ LH = (210-2 3-1 *0)2 3 = 210/4 = 27
F1_t_b_ LH = (310-2 3-1 *1)/2 3 = 39
F2_t_b_ LH = (310-2 3-1 *0)/2 3 = 39
对于 HH 子带:
E1_t_b_ HH = (210-2 3-1 *1/2 3= 210/4 = 26 E2_t_b_HH = 26
F1_t_b_ HH = (310-2 3-1 *1)/2 3 = 39 F2_t_b_ HH = (310-2 2-1 *1)/2 2 = 39
从这里我可以看到各子带不在一样大了:
LL 子带是: 12*12 , HL 子带是 12*13 , LH 是 13*12 , HH 是 13*13 (高度先)。
他们的宽和高的和与 d=2 上的 LL 子带是相等的。
由于 LL_2 上的宽度和高度是 25 (奇数),所以导致这种情况,基本的过滤是:如果计算中的贴片坐标 E i _t 是偶数,那么最终低通部分比高通部分多一个样本,如果是奇数,那么高通子带比低通子带多 1 个样本。
另外一个问题必须注意:计算过后的子带边界比原来的贴片小,实际上由于每次子带变换,图像的分辨率都要缩小 1/2 ,所以在 d 级子带变化后,上得到的边界,必须乘上 2 d 才能与原贴片中的位置对应。那么对于 d=2 的情况,必须乘上 4 ,因此对于 d=2 的各子带在原图像中的实际位置为:
LL 子带的位置为:( 212 , 312 ) X ( 212 , 312 )
HL 子带的位置为:( 212 , 312 ) X ( 208 , 308 )
LH 子带的位置为:( 208 , 308 ) X ( 212 , 312 )
HH 子带的位置为:( 208 , 208 ) X ( 208 , 308 )
上面的表示方式是高度优先。
这里可以理解为 d 级上的子带是由原图中的 2 d 个样本变换得到。
分辨率层
上图显示的子带变换过程由 DWT LEVEL 来决定,而每个级别都是图像的低分辨率层。分辨率的级别与 DWT Level 的值相反, Level 最的时候,分辨率级别为 0 ,而原图像对应分辨率的最高级别。
每个分辨率级别包含 3 个子带,分别是 HL , HH 和 LH ; 0 层包括一个子带 LL 。
分辨率的区域边界
假设分辨率用 r 表示,总的 DWT 变换次数用 D 表示,那么对于每个分辨率的边界可表示为:
E i _R = E i _t/2 D-r
F i _R = F i _t/2 D-r
如果 D=3 , r=2 ;那么按照上面的计算( E1_t=E2_t = 210, F1_t=F2_t = 310 ),分辨率层 2 的边界为:
E1_R_2 = 210/2 3-2 = 105 F1_R_2 = 310/2 3-2 = 155
E2_R_2 = 105 F2_R_2 = 155
如果 r=0 ,那么该分辨层的边界为:
E1_R_2 = 210/2 3-0 = 27 F1_R_2 = 310/2 3-0 = 39
E2_R_2 = 27 F2_R_2 = 39
每个分辨率级别的原点也是贴边的原点乘上: 2 -(D-r)
分区
为了提供渐进性, JPEG2000 提供了分区和分区分割的概念。
分区与贴片不同的地方在于分区不影响 DWT 变化,甚至不影响编码。另外分区的大小必须是 2 的 POWER ,而贴片的大小可以是任意的。
其将某个指定的分辨率层上进行分割,当然要求分区的每个块必须与图像的区域重叠。
一般某个分辨率层上有 3 个子带,这三个子带都是通过分区网格来划分的,当然每个子带
分区的大小用 P1 和 P2 来表示, P1 是高度, P2 是宽度。
N1_P :表示垂直方向分区的数量。
N2_P :表示水平方向分区的数量。
分区的原点用 O1_P,O2_P 表示,其可以不用与分辨率层的原点重叠;分区用垂直和水平方向的索引( p1,p2 )来表示;并且:
0<=p1<N1_P 0<= p2<N2_P
而 N1_P 和 N2_P 有下面计算得到:
N1_P = (F1_R-O1_P)/P1
N2_P = (F2_R-O1_P)/P2
F1_R 和 F2_R 表示当前分辨率层的右和下边界。如果他们是 0 ,那么 N1_P 和 N2_P 必须是 0 。
分区的区域
分区的区域用下面的表达式计算出来:
E1_P = max (E1_R, O1_P+P1*p1)
F1_P = min (F1_R, O1_P+P1*(p1+1))
E2_P = max (E2_R, O2_P+P2*p2)
F2_P = min (F2_R, O2_P+P2*(p2+1))
下面计算上面对于 D=3 , r=2 分辨率上的分区( 1,3 )的边界;这里假设 O1_P = 90,O2_P = 100 ,并且 P1=8 , P2=4
前面的计算中有 E1_R_2 = 105 F1_R_2 = 155 E2_R_2 = 105 F2_R_2 = 155
E1_P = max(105 , 90+1*8)= 105
F1_P = min (155,100+1*8) = 108
E2_P =max (105, 90+3*4) = 105
F2_P = min (155,100+3*4) = 112
分区分割
分区分割是将同一个分辨率层上三个子代( LL 子带外)上同一个位置的分区合并到一起的总称。实际上可以看出,这三块上的信息合并到一起在加上 LL 子带当前块,就可以恢复上一个分辨率级别上 LL 子带该位置的样本。当然映射到上一个分辨率层的时候需要将区域扩展。
对于特定的 r 分辨率级别上分区,对应到 r-1 分辨率级别上的的三个子带的区域为:
Ei_R-1_b = (Ei_R – bi)/2 Sr
Fi_R-1_b = (Fi_R – bi)/2 Sr
其中 i 等于 1 和 2 ,而 bi 分别是 0 和 1 。其组合得到四个子带。
Sr 在 r=0 的时候为 0 , r 大于 0 的时候为 1 。如果是 0 表示最低分辨率层也就是最终的 LL 子带,那么其没有映射,而对于其他的分辨率层上的映射是其下一级别的三个子带,因此区域标记需要减少 1/2 。这里的关系同前面子带的映射关系相似,这里不在详细介绍。
另外,新映射的三个子带的原点坐标需要按照下面表达式计算:
Oi_R-1 = (Oi_R –bi)/2 Sr
而分区划分的大小为:
P1_R-1 = 2 -Sr *P1_R
P2_R-1 = 2 -S r*P2_R
码块
编码块是对每个子带中分区的进一步划分;编码块划分具有与同一个子带中分区划分同样的原点 (O1_P,O2_P) 。
每个码块的大小为 J1_BC*J2_BC 。默认是 64 ,他们必须是 2 的 POWER ,并且不能小于 4 ,大于 1024 。
默认值 J1_BC_D,J2_BC_D 从 COD 参数的 CBLK 中获得,因此 J1_BC,J2_BC 可以通过下面的表达式来计算:
J1_BC = MIN (J1_BC_D, 2 -Sr *P1_R)
J2_BC = MIN (J2_BC_D, 2 -Sr *P2_R)
P1_R 和 P2_R 表示 r 分辨率上的分区大小。如果 2 -Sr *Pi_R 比 Ji_BC_D 要小,说明一个分区只能有一个码块。
每个分区上的垂直和水平方向码块的数目为: N1_BC,N2_BC 。
N1_BC = (F1_R-1_b – O1_P)/J1_BC
N2_BC = (F2_R-1_b – O2_P)/J2_BC
F1_R-1_b 和 F2_R-1_b 表示分区在子带上的下边界和右边界。
码块的编码
如果一个分区有多个码块,需要进行编码,编码的顺序是从左到右,从上到下。 HL 子带码块先出现,最后是 HH 子带。
注意:码块是进行编码的基本单元。所有数据在进行 DWT 之后,然后将对应子带上的系数按照分区来划分,并最终组织成码块,然后将得到的码块数据进行编码。
包
为了能够是压缩在质量方面采用渐进性,采用包这种结构。包实际上是码块编码的集合;最简单的码块组合方式是顺序的;例如:
每个码块的全部按照长度 + 内容(长度个字节)连续在一起,叫组合流。但这种方式不能够提供失真的伸缩性,但他们也是嵌入式的编码。
为了达到失真伸缩性,需要将码块的编码分为多次(或多个过程),每次为图象质量贡献一部分字节,如下图描述:
这里的 Qi 表示质量层,码块为每层提供一定的长度用 L 表示。这里只描述了两层,因此对于每个码块来说,整体的编码被分配到各质量层上,当然有的码块可能对某些质量层没有任何贡献,也就是空的。另外图中的箭头表示码块组织的方式。在位流中,其需要为每个码块增加一个标志头。
按照上面这种方式组织码流可以达到率失真的伸缩性,这种组织方式下位于某层的码块编码组合就形成一个包,当然这些码块应该是相关的, JPEG2000 中规定这些码块应该在同一个分区内。
例如:上面图中有两个分区, B0-B3 是分区 1 , B4-B7 是分区 2 ,那么 B0-B3 的 Q0 层编码流组合就是一个包。
JPEG2000 中有一个要求就是,将每个码块的头放在一起,组成包头,然后是码块的系数编码流。
层(质量层)
层是一个包的集合;每个分区为层贡献一个包,而分区是按照分辨率层来进行划分的。
但它与分辨率层不同的概率,它的每个层都是全分辨率的,也就是说,如果按照层来查看样本,那么每个层的大小都和原来图像是一样大小的。
层的数量并不固定,主要有采用的应用类型决定。
单一层:如果不需要失真的伸缩性,那么就使用简单的组合流,只需要一层。
按照编码过程进行分层也是一个好办法,每层包含码块样本的一个编码过程,这样有多少个编码过程就有多少层。这也是 EBCOT 中采用三个编码过程的原因所在。
因此,从上面的理解我们可以知道,层是全分辨率的,每层都与原来图像一样大小;如果层不断累加,那么质量不断改善,最终得到原来的图像样本。
区域
到目前,前面的例子已经足够告诉我们区域( Region )的含义了,这里不再介绍。
渐进性
最后看一下渐进性。
JPEG2000 最诱人的一点在于渐进性,随着数据的增加图像按照某种方式改善。
渐进性的四维是:质量、分辨率、空间和分量。
质量渐进性是通过上面介绍的层来实现的,随着层的增加,图像的质量不断改善。可以发现的是,每层实际上包括图像的某些部分,随着层的增加,图像越来越完整。
分辨率渐进性是子带变化过程中产生的各分辨率方式来组织数据。