pca主成份分析:将协方差变形: cov(x,y) = 1/(n-1)*( 求和xi*yi - n*x*y)
BSQ格式:
//将协方差变形: cov(x,y) = 1/(n-1)*( 求和xi*yi - n*x*y)
template <typename T>
void BSQCovAndMeanOMP(HANDLE hReadFile,ulong HW,ulong Width,ulong Height,int Bands,double* mean,double* cov,CProgressCtrl* bar)
{
ulong readBytes = 0;
ulong BT = Bands * sizeof(T);
long proSize = SIZE16M;
if(GetMemoryInfoG() >= 2) proSize = SIZE32M;
int kernel = GetKCount();
MALLOC2(double,meanK,kernel,Bands);
MALLOC2(double,covK,kernel,(1 + Bands) * Bands /2); //分配上三角
long k = proSize / BT; //BT比小于16M
ulong offsetT = (HW - k) * sizeof(T);
ulong KT = k * sizeof(T);
T* pTImg = (T*)malloc(Bands * KT);
ulong BenOffset = 0;
ulong HW2 = HW / k;
for (ulong y = 0; y < HW2; y++)
{
bar->SetPos(int(3 + y*1.0/HW2 *80));//设定进度条位置99%
SetFilePointer(hReadFile ,BenOffset,NULL,FILE_BEGIN);
T* pTBuf = pTImg;
//读
for (int i = 0; i < Bands; i++)
{
ReadFile(hReadFile,(LPVOID)pTBuf,KT,&readBytes,NULL);
pTBuf += k;
SetFilePointer(hReadFile ,offsetT,NULL,FILE_CURRENT);
}
#pragma omp parallel for num_threads(kernel)
for (long ik = 0; ik < k; ik++)
{
int kId = omp_get_thread_num();
double* pCovK = covK[kId];
double* pMeanK = meanK[kId];
T* pIBuf = pTImg + ik;
T* pJBuf = NULL;
for (int i = 0; i < Bands; i++)
{
pJBuf = pIBuf;
for (int j = i; j < Bands; j++)
{
*pCovK++ += *pIBuf * *pJBuf;
pJBuf += k;
}
pMeanK[i] += *pIBuf;
pIBuf += k;
}
}
BenOffset += KT;
}
k = HW - k * HW2;
if (k != 0)
{
SetFilePointer(hReadFile ,BenOffset,NULL,FILE_BEGIN);
KT = k * sizeof(T);
offsetT = (HW - k) * sizeof(T);
T* pTBuf = pTImg;
//读
for (int i = 0; i < Bands; i++)
{
ReadFile(hReadFile,(LPVOID)pTBuf,KT,&readBytes,NULL);
pTBuf += k;
SetFilePointer(hReadFile ,offsetT,NULL,FILE_CURRENT);
}
if (k < kernel) kernel = k;
#pragma omp parallel for num_threads(kernel)
for (long ik = 0; ik < k; ik++)
{
int kId = omp_get_thread_num();
double* pCovK = covK[kId];
double* pMeanK = meanK[kId];
T* pIBuf = pTImg + ik;
T* pJBuf = NULL;
for (int i = 0; i < Bands; i++)
{
pJBuf = pIBuf;
for (int j = i; j < Bands; j++)
{
*pCovK++ += *pIBuf * *pJBuf;
pJBuf += k;
}
pMeanK[i] += *pIBuf;
pIBuf += k;
}
}
}
free(pTImg);
//求均值
#pragma omp parallel for
for (int i = 0; i < Bands; i++)
{
double sum = 0;
for (int kid = 0; kid < kernel; kid++) sum += meanK[kid][i];
mean [i] = sum / HW;
}
FREE2(meanK,kernel);
//求协方差
HW2 = HW - 1;
double** pCovK = (double**)malloc(kernel * sizeof(double));
for (int kid = 0; kid < kernel; kid++) pCovK[kid] = covK[kid]; //存放的是地址
double* pCovData = cov;
double* p2CovData = NULL;
for (int i = 0; i < Bands; i++)
{
double sum;
double temp = HW * mean[i];
for (int j = i; j < Bands; j++)
{
sum = 0;
for (int kid = 0; kid < kernel; kid++) sum += *pCovK[kid]++; //求和
*pCovData++ = (sum - temp * mean[j]) / HW2;
}
if (i >= Bands - 1) break;
p2CovData = cov + i + 1;
for (int j = 0; j <= i; j++)
{
*pCovData++ = *p2CovData;
p2CovData += Bands;
}
}
free(pCovK);
FREE2(covK,kernel);
}
template <typename T> //保存pca数据(非ENVI格式)
void BSQSavePcaDataOMP(HANDLE hReadFile,HANDLE hWriteFile,int* BLUT,ulong HW,ulong Width,ulong Height,int Bands,int reductBand,double* eiv)
{
ulong readBytes = 0;
ulong writeBytes = 0;
ulong BT = Bands * sizeof(T);
long proSize = SIZE16M;
if(GetMemoryInfoG() >= 2) proSize = SIZE32M;
int kernel = GetKCount();
MALLOC2(T,KernelR,kernel,Bands);
MALLOC2(float,KernelPcaR,kernel,reductBand);
long k = proSize / BT; //BT比小于16M
ulong offsetT = (HW - k) * sizeof(T);
ulong offsetF = (HW - k) * sizeof(float);
ulong KT = k * sizeof(T);
ulong KF = k * sizeof(float);
ulong BenTOffset = 0;
ulong BenFOffset = 0;
T* pTImg = (T*)malloc(k * BT);
float* pFImg = (float*)malloc(KF * reductBand);
ulong HW2 = HW / k;
for (ulong y = 0; y < HW2; y++)
{
SetFilePointer(hReadFile ,BenTOffset,NULL,FILE_BEGIN);
SetFilePointer(hWriteFile,BenFOffset,NULL,FILE_BEGIN);
T* pTBuf = pTImg;
for (int i = 0; i < Bands; i++)
{
ReadFile(hReadFile,(LPVOID)pTBuf,KT,&readBytes,NULL);
SetFilePointer(hReadFile ,offsetT,NULL,FILE_CURRENT);
pTBuf += k;
}
#pragma omp parallel for num_threads(kernel)
for (long ik = 0; ik < k; ik++)
{
int kId = omp_get_thread_num();
T* r = KernelR[kId];
float* pcaR = KernelPcaR[kId];
T* pIBuf = pTImg + ik;
float* pJBuf = pFImg + ik;
for (int i = 0; i < Bands; i++)
{
r[i] = *pIBuf;
pIBuf += k;
}
ExcetPca<T>(r,eiv,BLUT,pcaR,Bands,reductBand);
for(int i = 0; i < reductBand; i++)
{
*pJBuf = pcaR[i];
pJBuf += k;
}
}
float* pFBuf = pFImg;
for (int i = 0; i < reductBand; i++)
{
WriteFile(hWriteFile,(LPVOID)pFBuf,KF,&writeBytes,NULL);
SetFilePointer(hWriteFile ,offsetF,NULL,FILE_CURRENT);
pFBuf += k;
}
BenTOffset += KT;
BenFOffset += KF;
}
k = HW - k * HW2;
if (k != 0)
{
SetFilePointer(hReadFile ,BenTOffset,NULL,FILE_BEGIN);
SetFilePointer(hWriteFile,BenFOffset,NULL,FILE_BEGIN);
KT = k * sizeof(T);
KF = k * sizeof(float);
offsetT = (HW - k) * sizeof(T);
offsetF = (HW - k) * sizeof(float);
T* pTBuf = pTImg;
for (int i = 0; i < Bands; i++)
{
ReadFile(hReadFile,(LPVOID)pTBuf,KT,&readBytes,NULL);
SetFilePointer(hReadFile ,offsetT,NULL,FILE_CURRENT);
pTBuf += k;
}
if (k < kernel) kernel = k;
#pragma omp parallel for num_threads(kernel)
for (long ik = 0; ik < k; ik++)
{
int kId = omp_get_thread_num();
T* r = KernelR[kId];
float* pcaR = KernelPcaR[kId];
T* pIBuf = pTImg + ik;
float* pJBuf = pFImg + ik;
for (int i = 0; i < Bands; i++)
{
r[i] = *pIBuf;
pIBuf += k;
}
ExcetPca<T>(r,eiv,BLUT,pcaR,Bands,reductBand);
for(int i = 0; i < reductBand; i++)
{
*pJBuf = pcaR[i];
pJBuf += k;
}
}
float* pFBuf = pFImg;
for (int i = 0; i < reductBand; i++)
{
WriteFile(hWriteFile,(LPVOID)pFBuf,KF,&writeBytes,NULL);
SetFilePointer(hWriteFile ,offsetF,NULL,FILE_CURRENT);
pFBuf += k;
}
}
FREE2(KernelR,kernel);
FREE2(KernelPcaR,kernel);
free(pTImg);
free(pFImg);
}
template <typename T> //保存pca数据(ENVI格式数据)
void BSQSaveRMPcaDataOMP(HANDLE hReadFile,HANDLE hWriteFile,int* BLUT,ulong HW,ulong Width,ulong Height,int Bands,int reductBand,double* eiv)
{
ulong readBytes = 0;
ulong writeBytes = 0;
ulong RBD = sizeof(double) * reductBand;
double* mean = (double*)malloc(RBD);
memset(mean,0,RBD);
int kernel = GetKCount();
MALLOC2(T,KernelR,kernel,Bands);
MALLOC2(float,KernelPcaR,kernel,reductBand);
MALLOC2(double,meanK,kernel,reductBand);
ulong BT = Bands * sizeof(T);
long proSize = SIZE16M;
if(GetMemoryInfoG() >= 2) proSize = SIZE32M;
long k = proSize / BT; //BT比小于16M
ulong offsetT = (HW - k) * sizeof(T);
ulong offsetF = (HW - k) * sizeof(float);
ulong KT = k * sizeof(T);
ulong KF = k * sizeof(float);
ulong BenTOffset = 0;
ulong BenFOffset = 0;
T* pTImg = (T*)malloc(k * BT);
float* pFImg = (float*)malloc(KF * reductBand);
ulong HW2 = HW / k;
for (ulong y = 0; y < HW2; y++)
{
SetFilePointer(hReadFile ,BenTOffset,NULL,FILE_BEGIN);
SetFilePointer(hWriteFile,BenFOffset,NULL,FILE_BEGIN);
T* pTBuf = pTImg;
for (int i = 0; i < Bands; i++)
{
ReadFile(hReadFile,(LPVOID)pTBuf,KT,&readBytes,NULL);
SetFilePointer(hReadFile ,offsetT,NULL,FILE_CURRENT);
pTBuf += k;
}
#pragma omp parallel for num_threads(kernel)
for (long ik = 0; ik < k; ik++)
{
int kId = omp_get_thread_num();
T* r = KernelR[kId];
float* pcaR = KernelPcaR[kId];
T* pIBuf = pTImg + ik;
float* pJBuf = pFImg + ik;
for (int i = 0; i < Bands; i++)
{
r[i] = *pIBuf;
pIBuf += k;
}
ExcetPca<T>(r,eiv,BLUT,pcaR,Bands,reductBand,meanK[kId]);
for(int i = 0; i < reductBand; i++)
{
*pJBuf = pcaR[i];
pJBuf += k;
}
}
float* pFBuf = pFImg;
for (int i = 0; i < reductBand; i++)
{
WriteFile(hWriteFile,(LPVOID)pFBuf,KF,&writeBytes,NULL);
SetFilePointer(hWriteFile ,offsetF,NULL,FILE_CURRENT);
pFBuf += k;
}
BenTOffset += KT;
BenFOffset += KF;
}
k = HW - k * HW2;
if (k != 0)
{
SetFilePointer(hReadFile ,BenTOffset,NULL,FILE_BEGIN);
SetFilePointer(hWriteFile,BenFOffset,NULL,FILE_BEGIN);
KT = k * sizeof(T);
KF = k * sizeof(float);
offsetT = (HW - k) * sizeof(T);
offsetF = (HW - k) * sizeof(float);
T* pTBuf = pTImg;
for (int i = 0; i < Bands; i++)
{
ReadFile(hReadFile,(LPVOID)pTBuf,KT,&readBytes,NULL);
SetFilePointer(hReadFile ,offsetT,NULL,FILE_CURRENT);
pTBuf += k;
}
if (k < kernel) kernel = k;
#pragma omp parallel for num_threads(kernel)
for (long ik = 0; ik < k; ik++)
{
int kId = omp_get_thread_num();
T* r = KernelR[kId];
float* pcaR = KernelPcaR[kId];
T* pIBuf = pTImg + ik;
float* pJBuf = pFImg + ik;
for (int i = 0; i < Bands; i++)
{
r[i] = *pIBuf;
pIBuf += k;
}
ExcetPca<T>(r,eiv,BLUT,pcaR,Bands,reductBand,meanK[kId]);
for(int i = 0; i < reductBand; i++)
{
*pJBuf = pcaR[i];
pJBuf += k;
}
}
float* pFBuf = pFImg;
for (int i = 0; i < reductBand; i++)
{
WriteFile(hWriteFile,(LPVOID)pFBuf,KF,&writeBytes,NULL);
SetFilePointer(hWriteFile ,offsetF,NULL,FILE_CURRENT);
pFBuf += k;
}
}
FREE2(KernelR,kernel);
FREE2(KernelPcaR,kernel);
free(pTImg);
#pragma omp parallel for
for (int i = 0; i < reductBand; i++)
{
double sum = 0;
for (int kid = 0; kid < kernel; kid++) sum += meanK[kid][i];
mean [i] = sum / HW;
}
FREE2(meanK,kernel);
//去均值
SetFilePointer(hWriteFile,0,NULL,FILE_BEGIN);
k = proSize / sizeof(float);
KF = k * sizeof(float);
pFImg = (float*)realloc(pFImg,proSize);
HW2 = HW / k;
ulong k1 = HW - k * HW2;
ulong K1F = k1 * sizeof(float);
for (int i = 0; i < Bands; i++)
{
for (ulong x = 0; x < HW2; x++)
{
ReadFile(hWriteFile,(LPVOID)pFImg,KF,&readBytes,NULL);
#pragma omp parallel for num_threads(kernel)
for (long ik = 0; ik < k; ik++)
{
float* pFBuf = pFImg + ik;
*pFBuf = *pFBuf - mean[i];
}
SetFilePointer(hWriteFile ,-KF,NULL,FILE_CURRENT);
WriteFile(hWriteFile,(LPVOID)pFImg,KF,&writeBytes,NULL);
}
if(k1 != 0)
{
ReadFile(hWriteFile,(LPVOID)pFImg,K1F,&readBytes,NULL);
#pragma omp parallel for num_threads(kernel)
for (long ik = 0; ik < k1; ik++)
{
float* pFBuf = pFImg + ik;
*pFBuf = *pFBuf - mean[i];
}
SetFilePointer(hWriteFile ,-K1F,NULL,FILE_CURRENT);
WriteFile(hWriteFile,(LPVOID)pFImg,K1F,&writeBytes,NULL);
}
}
free(pFImg);
free(mean);
}