概述
无论是在图像处理领域还是数据领域,KL变换或者称PCA都是一种很重要的手段,通过这种方法,我们能把降低数据的维度,保留最重要的信息,从而达到压缩或者减轻数据处理的复杂度。这篇文章主要从图像的角度来解释一下什么是KL变换。首先需要了解一下KL变换的背景知识,block transform
Block Transform
何为Block transform? 首先需要说明,block transform是一种线性变换,( T(v1+v2) = T(v1)+T(v2) \T(alpha v) = alpha T(v) ) 通过block transfom,图像的能量可以集中在最初的几个参数上,这样我们可以把后面的参数置零,从而达到压缩的目的。因为在反变换时用到逆矩阵,而逆矩阵的运算会带来很多麻烦,所以一般block transform的变换矩阵都是酉矩阵。 *T表示共轭转置。 如果A实矩阵那么它的转置即为逆。
酉矩阵有很多好的特点:
(y = Ax spacespace x=A^{-1}y=A^Hy)
(|mathbf{y}|^{2}=mathbf{y}^{H} mathbf{y}=(mathbf{A} mathbf{x})^{H} mathbf{A} mathbf{x}=mathbf{x}^{H} mathbf{A}^{H} mathbf{A} mathbf{x}=mathbf{x}^{H} mathbf{x}=|mathbf{x}|^{2})
对于酉矩阵变换
平均值为
(oldsymbol{mu}_{y}=E[mathbf{y}]=E[mathbf{A} mathbf{x}]=mathbf{A} E[mathbf{x}]=mathbf{A} oldsymbol{mu}_{x})
协方差为
(mathbf{R}_{y y}=Eleft[left(mathbf{y}-oldsymbol{mu}_{y} ight) cdotleft(mathbf{y}-oldsymbol{mu}_{y} ight)^{H} ight]=mathbf{A} mathbf{R}_{x x} mathbf{A}^{H})
通过酉矩阵变换,能量会集中在最前面的几个参数,而能量通过协方差观察到。这里一个例子
当 p = 0.95时,91.1%的能量都集中在第一个参数上。
因为有这种良好的性质,在图像处理中,往往将图像分为很多正方形,对每一个正方形进行block transform,将大部分信息都放在最初的几个参数上,达到图像压缩的目的。
在图像处理中,经常用到的Harr, DCT 变换就运用这种方式,通常有很好的效果。而所有变换都不能完全将能量集中在最开始的几个参数,并且每个维度之间uncorrelate 协方差成为一个对角线矩阵。如果想达到这种目的,只有通过KL变化
KL 变换
KL 变换是最优变化, 通过KL变换,图像成为 Best decoorelation and energy concentration. 那KL变换如何做到呢。
对于一个协方差矩阵来说, 可以将协方差矩阵分解为包含特征值和特征向量的矩阵。 (C_{xx} = UVU^T) 其中(U) 每一列为一个特征向量。(V)是一个对角线矩阵,对角线上对应特征值。得到(U) (V), 对特征值从大到小排序,并且调整特征向量,将(U^T)作为变换矩阵。 (Y=U^TX)。
为什么这样就可以得到最优的(C_yy)呢。
( C_{yy} = A^TC_{xx}A\ Rightarrow C_{yy} = UC_{xx}U^T\ Rightarrow C_{yy} =UUVU^TU = V )
(C_{yy}) 就是特征值矩阵,也就是对角矩阵
对于协方差有一点说明
虽然协方差(C = E[((X-mu)^T(X-mu)]) 由于数据不同,公式也可以变。
如果
每一个小方块对应4个像素 一共有6个方块 每一列相当于一个维度。协方差为(C = E[((X-mu)^T(X-mu)])
1 block | 1 | 2 | 3 | 4 |
2 block | 1 | 2 | 3 | 4 |
3 block | 1 | 2 | 3 | 4 |
4 block | 1 | 2 | 3 | 4 |
5 block | 1 | 2 | 3 | 4 |
6 block | 1 | 2 | 3 | 4 |
如果每一行是一个维度 协方差为(C = E[(X-mu)(X-mu)^T])
1 block | 2 block | 3 block | 4 block | 5 block | 6 block |
1 | 1 | 1 | 1 | 1 | 1 |
2 | 2 | 2 | 2 | 2 | 2 |
3 | 3 | 3 | 3 | 3 | 3 |
4 | 4 | 4 | 4 | 4 | 4 |
代码 matlab
function [blocks , C_im , klt_base ] = compute_klt_basis (im) N=8; % 1. Allocate memory for blocks sz = size (im); x_arr = 1:N:( sz (2) - N+1); y_arr = 1:N:( sz (1) - N+1); blocks = zeros ( length ( x_arr ) * length ( y_arr ), N*N); %2. Regroup the input image into blocks for iy = 1: length ( y_arr ) for ix = 1: length ( x_arr ) x_start = x_arr (ix); y_start = y_arr (iy); block_in = im( y_start : y_start +N -1, x_start : x_start +N -1); blocks ((iy -1)* length ( x_arr ) + ix , :) = block_in (:); end end %3. Compute autocorrelation over all blocks C_im = blocks '* blocks / size (blocks ,1); [ klt_base_v ,ew] = eig( C_im ); [ew , ew_idx ] = sort ( diag (ew), 'descend '); klt_base_v = klt_base_v (:, ew_idx ); klt_base = zeros (N^2); for x = 0:N -1 for y = 0:N -1 idx = x*N+y+1; klt_base (y*N +1:( y+1)*N, x*N +1:( x+1)*N) = ... reshape ( klt_base_v (:, idx ), N, N); end end end