zoukankan      html  css  js  c++  java
  • 主成分分析实现的一个心得

    作者:朱金灿

    来源: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操作,效果图如下:

    第一主成分:

     

       

     

     

    第二主成分:

     

     

       

     

     

    第三主成分:

     

     

       

     

     

    第四主成分:

     

     

       

     

     

    第五主成分:

     

       

     

     

    第六主成分:

     

      

       

     

     

       

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

  • 相关阅读:
    linux zip命令 tar命令 【压缩、解压缩】参数列表:
    理解 uptime 的:“平均负载”? 如何模拟测试
    mark_Linux_wc
    我应该怎么学习SAP?
    SAP 销售订单交货对成本中心记账
    从华为“鸿蒙”备胎看IT项目建设
    什么样的系统算是坑
    写在Logg SAP项目上线之际
    SAP系统邮件功能配置
    警惕SAP项目被“中间商赚差价”
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6471185.html
Copyright © 2011-2022 走看看