主成分分析实现的一个心得

作者:朱金灿

来源:blog.csdn.net/clever101

 

     主成份分析(Principal Component AnalysisPCA)也叫做主成份变换、主分量分析或 —L(KarhunenLoeve)变换,是建立在统计特征基础上的多维(如多波段)正交线

性变换。它是遥感图像处理中最常用也是最有用的变换算法之一。

 

      这次我要实现一个主成分分析算法,图是做出来了,但是和著名的遥感软件PCIENVI的效果比起来很差。如第一主成分的图如下:

 

 

   

上面噪音极多,而且看起来不合谐。我知道自己的算法有问题,在排除了自己的读取图像的问题后。我考虑到是不是求取特征矩阵时出了问题,因为主成分的输出数据是Y=X*A

其中X为原图像,Y为目标图像,A为特征向量矩阵。由此我怀疑我的特征矩阵求取有问题。后来从网上找了一种求特征矩阵的办法,进行主成分分析的效果。下面是具体的实现代码:

 

 

  

  1.     //计算特征向量
  2. /*
  3. pdblCof    [in][out]----- 协方差矩阵
  4. lChannelCount  [in] ------  图像的输入波段数
  5. pdblVects  [out] ---- 特征向量矩阵
  6. dblEps  [in] ---- 误差范围,我取为0.0000001
  7. Ljt   [in] ----- 循环次数,我取为1000000
  8. */
  9. static int iJcobiMatrixCharacterValue(double** pdblCof, long lChannelCount, std::vector<double>& pdblVects, double dblEps,long ljt)
  10. {
  11.     long i,j,p,q,u,w,t,s,l;
  12.     double fm,cn,sn,omega,x,y,d;
  13.     l = 1;
  14.     for(i = 0; i < lChannelCount; i ++)
  15.     {    
  16.         pdblVects[i * lChannelCount + i] = 1.0;
  17.         for(j = 0; j < lChannelCount; j ++)
  18.             if(i != j) pdblVects[i * lChannelCount + j] = 0.0;
  19.     }
  20.     while(1){
  21.         fm = 0.0;
  22.         for(i = 0; i < lChannelCount; i ++)
  23.             for(j = 0; j < lChannelCount; j ++)
  24.             {
  25.                 d = fabs(pdblCof[i][j]);
  26.                 if((i != j)&&(d > fm))
  27.                 { fm = d; p = i;  q = j;}
  28.             }
  29.             if(fm < dblEps) return 1;
  30.             if(l > ljt)   return 0;
  31.             l += 1;
  32.             u = p * lChannelCount + q;   w = p * lChannelCount + p; t = q * lChannelCount + p;  s = q * lChannelCount + q;
  33.             x = -pdblCof[p][q];
  34.             y = (pdblCof[q][q] - pdblCof[p][p])/2.0;
  35.             omega = x / sqrt(x * x + y * y);
  36.             if(y < 0) omega = -omega;
  37.             sn = 1.0 + sqrt(1.0 - omega * omega);
  38.             sn = omega / sqrt(2.0 * sn);
  39.             cn = sqrt(1.0 - sn * sn);
  40.             fm = pdblCof[p][p];
  41.             pdblCof[p][p] = fm * cn * cn + pdblCof[q][q] * sn * sn + pdblCof[p][q] * omega;
  42.             pdblCof[q][q] = fm * sn * sn + pdblCof[q][q] * cn * cn - pdblCof[p][q] * omega;
  43.             pdblCof[p][q] = 0.0;
  44.             pdblCof[q][p] = 0.0;
  45.             for(j = 0;j < lChannelCount ; j++)
  46.                 if((j != p) && (j != q))
  47.                 { 
  48.                     fm = pdblCof[p][j];
  49.                     pdblCof[p][j] = fm * cn + pdblCof[q][j] * sn;
  50.                     pdblCof[q][j] =-fm * sn + pdblCof[q][j] * cn;
  51.                 }
  52.                 for(i = 0; i < lChannelCount; i++)
  53.                     if((i != p) && ( i != q)){  
  54.                         fm = pdblCof[i][p];
  55.                         pdblCof[i][p] = fm * cn + pdblCof[i][q] * sn;
  56.                         pdblCof[i][q] =-fm * sn + pdblCof[i][q] * cn;
  57.                     }
  58.                     for(i = 0; i < lChannelCount; i++)
  59.                     {
  60.                         fm = pdblVects[i * lChannelCount + p];
  61.                         pdblVects[i * lChannelCount + p] = fm * cn + pdblVects[i * lChannelCount + q] * sn;
  62.                         pdblVects[i * lChannelCount + q] =-fm * sn + pdblVects[i * lChannelCount + q] * cn;
  63.                     }
  64.     }
  65.     return 1;
  66. }
  67. // 根据特征值从大到小排列特征向量矩阵
  68. /*
  69. pfMatrix [in][out]----- 上一步输出的协方差矩阵
  70. nBandNum [in] ------  图像的输入波段数
  71. pdblVects  [out] ---- 上一步输出的特征向量矩阵
  72. */
  73.     static void SortEigenvector(double** pfMatrix,int nBandNum,std::vector<double> &pfVector)
  74. {
  75.     long p;
  76.     double f;
  77.     double T;
  78.     int count = nBandNum;
  79.     for(int i = 0; i < count ; i ++)
  80.     {
  81.         T = pfMatrix[i][i];
  82.         p = i;
  83.         for(int j = i; j < count; j ++)
  84.             if(T < pfMatrix[j][j])
  85.             {                   
  86.                 T = pfMatrix[j][j];
  87.                 p = j;
  88.             }
  89.             if(p != i)
  90.             {
  91.                 f = pfMatrix[p][p];
  92.                 pfMatrix[p][p] = pfMatrix[i][i];
  93.                 pfMatrix[i][i] = f;
  94.                 for(int j = 0; j < count; j ++)
  95.                 {
  96.                     f = pfVector[j * count +p];
  97.                     pfVector[j * count + p] = pfVector[j * count + i];
  98.                     pfVector[j * count + i] = f;
  99.                 }
  100.             }
  101.     }
  102. }

 

      

执行上面两步之后,所得到的特征矩阵为用于和原图像相乘的矩阵A.

 

对一幅TM图像的第123457通道执行PCA操作,效果图如下:

第一主成分:

 

   

 

 

第二主成分:

 

 

   

 

 

第三主成分:

 

 

   

 

 

第四主成分:

 

 

   

 

 

第五主成分:

 

   

 

 

第六主成分:

 

  

   

 

 

   

    从上面可以看出,正确的图像看起来视觉非常和谐,毫无刺目的感觉。

你可能感兴趣的:(算法,图像处理)