在CC的系统芯片中都有数据白化功能.whiting的中文件直译为白化,真实的意思应该是数据加噪.
白化处理主要是为了避免在传输过程中出现过长的连续0或1的位流模式。基带处理器需要从接收到的模拟数据信号中判断数据是0还是1,但过长的连续0或1位流会造成问题。因为在接收到的模拟数据信号中并不存在象直流信号中那样的参考点,因此必须依靠接收到的最后几个传输信号进行校正。任何连续的0或1的长序列位流串都可能导致校正失败。因此需要采用数据白化技术对信号进行扰码处理,以大大降低出现长序列0或1位流串的可能性。
白化的原理:
随机向量的“零均值化”和“空间解相关”(也叫白化)是最常用的两个预处理过程,其中“零均值化”比较简单,而“空间解相关”涉及一些矩阵的知识。
设有均值为零的随机信号向量 x ,其自相关矩阵为
Rx =E[xxT ] ≠ I
很明显, Rx 是对称矩阵,且是非负定的(所有特征值都大于或等于0)。
现在,寻找一个线性变换 B 对 x 进行变换,即 y = Bx ,使得
Ry = B E[xxT ]BT = I
上式的含义是:y的各分量是不相关的,即 E[yi yj ]=δ ij 。通常将这个过程称为“空间解相关”、“空间白化”或“球化”。 B 称为空间解相关矩阵(空间白化矩阵、球化矩阵)。
由 Rx 的性质可知,其存在特征值分解:
Rx = Q Σ QT
Q 是正交矩阵, Σ 是对角矩阵,其对角元素是 Rx 特征值。
令
B = Σ −1/2QT (1)
则有
Ry =(Σ −1/2 QT ) Q Σ QT(Σ −1/2 QT) T = I
因此,通过矩阵 B 线性变换后, y 的各个分量变得不相关了。
对于 Rx 来说,特征值分解和奇异值分解是等价的,而奇异值分解的数值算法比特征值分解的数值算法具有更好的稳定性,因此一般都用奇异值分解来构造白化矩阵 B 。
术语“白”来自于白噪声的能谱在所有频率上是一个常数这一事实,就像含有各种颜色的白光谱一样。白化的本质就是去相关加缩放。从上述原理可以看出,白化的过程跟PCA是一样的,经过PCA处理过之后的数据是不相关的,且具有压缩数据的作用,但只能保证各分量信号之间“不相关”,不能保证的“独立性”,,但它能够简化盲分离算法或改善分离算法的性能。
此外,白化矩阵B 肯定不是唯一的。容易看到,任何矩阵 UB ( U 为正交矩阵)也是白化矩阵。这是因为对 y = UBx ,下式成立:
E[yyT ]=UB E[xxT ]BTUT = UIUT = I
一个重要的例子是矩阵 QΣ −1/2 QT 。这也是一个白化矩阵,因为它是用正交矩阵 Q 左乘式(1) 的 B 得到的。这个矩阵称为 Cx 的逆均方根,并用 Cx −1/2 表示,因为它来自于均方根概念向矩阵的标准推广。
图像数据的白化代码(matlab):
该pca函数接口形式为: [Y,V,E,D] = pca(X)
其中X为输入数据,X的每一列是一个输入样本。返回值Y是对X进行PCA分析后的投影矩阵。V是与X有关的协方差矩阵特征向量的白化矩阵,E是对应的特征向量(列)构成的矩阵,D是对应的特征值构成的对角矩阵(特征值处于对角线上)。返回值中的白化矩阵,特征向量和特征值都是按照对应特征值大小进行排序后了的。
function [Y,V,E,D] = pca(X)
% do PCA on image patches
% INPUT variables:
% X matrix with image patches as columns
% OUTPUT variables:
% Y the project matrix of the input data X without whiting
% V whitening matrix
% E principal component transformation (orthogonal)
% D variances of the principal components
%去除直流成分
X = X-ones(size(X,1),1)*mean(X);
%其中r=size(A,1)该语句返回的时矩阵A的行数,c=size(A,2) 该语句返回的时矩阵A的列%数
% Calculate the eigenvalues and eigenvectors of the new covariance matrix.
covarianceMatrix = X*X'/size(X,2); % 求出其协方差矩阵
%E是特征向量构成,它的每一列是特征向量,D是特征值构成的对角矩阵
%这些特征值和特征向量都没有经过排序
[E, D] = eig(covarianceMatrix);
% Sort the eigenvalues and recompute matrices
% 因为sort函数是升序排列,而需要的是降序排列,所以先取负号,diag(a)是取出a的对角元素构成
% 一个列向量,这里的dummy是降序排列后的向量,order是其排列顺序
[dummy,order] = sort(diag(-D));
E = E(:,order);%将特征向量按照特征值大小进行降序排列,每一列是一个特征向量
Y = E'*X;
d = diag(D); %d是一个列向量
%dsqrtinv是列向量,特征值开根号后取倒,仍然是与特征值有关的列向量
%其实就是求开根号后的逆矩阵
dsqrtinv = real(d.^(-0.5));
Dsqrtinv = diag(dsqrtinv(order));%是一个对角矩阵,矩阵中的元素时按降序排列好了的特征值(经过取根号倒后)
D = diag(d(order));%D是一个对角矩阵,其对角元素由特征值从大到小构成
V = Dsqrtinv*E';%特征值矩阵乘以特征向量矩阵
end
在进行 ICA或者ISA处理之前,首先要对训练样本图像集进行预处理,包括去均值和白化,分为两步进行:首先要对观测数据阵X进行主成分分析,再对X进行白化。
1. 对X进行主成分分析
求X的协方差矩阵,如下式:
C = X * X’;
对C进行奇异值分解,如下式:
C = U*D*U’;
式中D为特征值的对角阵,U为C的奇异值分解中的左奇异阵,U的各个分量u1,u2,...,um为C的特征向量。
2. 对X进行白化
观测数据阵X的白化过程如下:
Z = M * X;
上式中的M为白化矩阵,M = inv(sqrt(D)) * U',其中D极为X的协方差矩阵C的奇异值分解中的特征根对角阵。Z即为白化后的数据阵。
C语言代码:
unsigned short whiting_data(unsigned char *data, unsigned short whiting_pn9){
unsigned char i, c;
*data ^= (whiting_pn9&0xFF);
for(i=0; i<8; i++){
c = whiting_pn9 & 0x21;
whiting_pn9 >>= 1;
if ((c==0x21)||(c==0)){
whiting_pn9 &= 0x0FF;
}else{
whiting_pn9 |= 0x100;
}
}
return whiting_pn9;
}
// 数据串白化处理
void whiting_buff(unsigned char *buff, unsigned short len)
{
unsigned short whiting_pn9;
whiting_pn9 = 0x1FF;
while (len--){
whiting_pn9 = whiting_data(buff++, whiting_pn9);
}
}
#include "albinism.h"
Albinism::Albinism()
{
this->pn9 = 0x21;
}
void Albinism::StatisticsBit(unsigned char *pIn, unsigned int InSLen, unsigned int *Num){
int Max = 0;
/* 循环找相同的bit */
int Cur = 0;
unsigned char CurFlag = 0;
unsigned char MaxCurFlag = 0;
CurFlag = 0x01;
for (unsigned int i=0; i<InSLen; i++) {
for(int j=0; j<8; j++){
CurFlag = pIn[i]&(0x80>>j);
CurFlag >>= (7-j);
if(MaxCurFlag==CurFlag){
Cur ++;
}else{
if(Cur >= Max){
Max = Cur;
}
Cur = 1;
MaxCurFlag = CurFlag;
}
}
}
if(Cur >= Max){
Max = Cur;
}
*Num = Max;
}
void Albinism::SetKey(unsigned char pn9){
this->pn9 = pn9;
}
unsigned char Albinism::GetKey(){
return this->pn9;
}
void PrintfBin(unsigned char *pIn, int InSLen, int Num){
char Temp[InSLen*8/Num+1+InSLen*8];
int ops = 0;
int Tempops = 0;
memset(Temp, 0, sizeof(Temp));
for(int i=0; i<InSLen; i++) {
for (int j=0; j<8; j++) {
if(pIn[i]&(0x80>>j)){
Temp[ops+Tempops] = '1';
}else{
Temp[ops+Tempops] = '0';
}
ops ++;
if((ops>=Num)&&(!(ops%Num))){
Temp[ops+Tempops] = ' ';
Tempops ++;
}
}
}
QString Log(Temp);
qDebug() << Log << "\r\n";
}
unsigned char Albinism::whiting_data(unsigned char *In, unsigned char *Out, unsigned char whiting_pn9){
unsigned char i, c, j=0;
unsigned char y = 0;
c = whiting_pn9;
for(i=0; i<8; i++){
if((c&0xE0) == 0xC0){
c &= (~(0x40));
}else if((c&0xE0) == 0x20){
c |= 0x40;
}
j = (c >> 7)&0x01;
y <<= 1;
y |= j;
c <<= 1;
c += j;
if(c&0x10){
j ^= 0x01;
}else{
j ^= 0x00;
}
j &= 0x01;
j <<= 4;
c &= (~(0x10));
c |= j;
//PrintfBin((char *)&c, 1, 100);
}
// PrintfBin((char *)&c, 1, 100);
PrintfBin(&y, 1, 100);
*Out = *In^(y &0xFF);
whiting_pn9 = c;
#if 0
for(i=0; i<8; i++){
c = (whiting_pn9&0xFF) & this->pn9;
whiting_pn9 >>= 1;
if ((c==this->pn9)||(c==0)){
whiting_pn9 &= 0x0FF;
}else{
whiting_pn9 |= 0x100;
}
}
#endif
return whiting_pn9;
}
unsigned short whiting_data1(unsigned char *In, unsigned char *Out, unsigned char whiting_pn9){
unsigned char i, c, j=0;
*Out = *In^(whiting_pn9&0xFF);
c = *Out;
for(i=0; i<8; i++){
j = 0;
if(c&0x80){
j = 1;
}
if(whiting_pn9&0x80){
j ^= 1;
}else{
j ^= 0;
}
j &= 0x01;
if(whiting_pn9&0x10){
j ^= 1;
}else{
j ^= 0;
}
j &= 0x01;
if(whiting_pn9&0x01){
j ^= 1;
}else{
j ^= 0;
}
j &= 0x01;
whiting_pn9 = (whiting_pn9 << 1) + j;
c <<= 1;
}
#if 0
for(i=0; i<8; i++){
c = (whiting_pn9&0xFF) & this->pn9;
whiting_pn9 >>= 1;
if ((c==this->pn9)||(c==0)){
whiting_pn9 &= 0x0FF;
}else{
whiting_pn9 |= 0x100;
}
}
#endif
return whiting_pn9;
}
void Albinism::Code(unsigned char *pIn, unsigned int InSLen, unsigned char *pOut){
unsigned char whiting_pn9;
whiting_pn9 = 0xFF;
while (InSLen--){
whiting_pn9 = whiting_data(pIn++, pOut++, whiting_pn9);
}
}
void Albinism::Decode(unsigned char *pIn, unsigned int InSLen, unsigned char *pOut){
unsigned char whiting_pn9;
whiting_pn9 = 0xFF;
while (InSLen--){
whiting_pn9 = whiting_data(pIn++, pOut++, whiting_pn9);
}
}