光谱角监督分类算法实现
该函数实现了基于光谱角距离的监督分类算法。函数的输入参数包括图像的行数、列数、波段数、样本数量、每个样本的平均光谱值和图像数据指针。其中,每个样本的平均光谱值是一个二维数组,第一维表示样本数量,第二维表示波段数。图像数据指针是一个指向指针数组的指针,每个指针指向一个波段的图像数据。
函数首先创建了三个动态数组,分别用于存储每个像素的灰度值、到样本区的距离和分类结果。然后,计算参考光谱的几何平均向量,即对每个波段的平均值求平方根。接着,对每个像素进行处理,先将灰度值和距离数组清零,然后计算该像素到每个样本区的光谱角距离,并根据设定的阈值进行分类。如果该像素距离某个样本区的距离小于阈值,则计算该像素与参考光谱的夹角,如果夹角小于该像素到样本区的距离,则将该像素分类为该样本区,否则继续检查其他样本区。如果该像素距离所有样本区的距离都大于阈值,则将其分类为距离最近的样本区。最后,将分类结果写入数组并将其写入输出文件中。
函数的核心是光谱角距离的计算,该距离是通过计算两个向量的夹角来衡量它们的相似度。具体地,将两个向量归一化后,计算它们的点积,再通过反余弦函数计算它们的夹角。该距离越小,表示两个向量越相似。函数中还使用了参考光谱的概念,即将所有样本区的平均光谱值求平均后得到的向量,用于判断未知像素是否与样本区相似。
void CSupervised::SpectralAngle(int Rows, int Cols, int Bands, int number, float AverageValue[][200], LPSTR *pPointer)
{
float *Gray = new float[number];
float *Distance = new float[number];
unsigned char *array = new unsigned char[Rows*Cols];
float min;
CFile g;
CString filename;
filename = 'spectral_angle_class'; //文件储存位置
if (!g.Open(filename, CFile::modeCreate | CFile::modeWrite))
{
AfxMessageBox("输出文件打开失败!", MB_ICONHAND);
return;
}
//计算参考光谱的几何平均向量
float *reference = new float[Bands];
for (int i = 0; i < Bands; i++)
{
float sum = 0;
for (int j = 0; j < number; j++)
{
sum += AverageValue[j][i];
}
reference[i] = pow(sum / number, 1.0 / Bands);
}
//对每个像素进行处理
for (int data = 0; data < Rows*Cols; data++)
{
//数组清零便于计算
for (int k = 0; k < number; k++)
{
Gray[k] = 0;
Distance[k] = 0;
}
//计算结果进行分类 (计算各个点到样本区的距离)
min = 100000;
for (int i = 0; i < number; i++)
{
/////////////////////////光谱角距离////////////////////////
float numerator = 0, denominator1 = 0, denominator2 = 0;
for (int j = 0; j < Bands; j++)
{
numerator += (*pPointer[j] * AverageValue[i][j]);
denominator1 += pow(*pPointer[j], 2);
denominator2 += pow(AverageValue[i][j], 2);
}
Distance[i] = acos(numerator / (sqrt(denominator1)*sqrt(denominator2)));
///////////////////////////////////////////////////////////
//根据阈值进行分类
float threshold = 0.1; //设定阈值
if (Distance[i] <= threshold)
{
//计算未知像元与参考光谱的夹角
float numerator_ref = 0, denominator1_ref = 0, denominator2_ref = 0;
for (int j = 0; j < Bands; j++)
{
numerator_ref += (*pPointer[j] * reference[j]);
denominator1_ref += pow(*pPointer[j], 2);
denominator2_ref += pow(reference[j], 2);
}
float ref_angle = acos(numerator_ref / (sqrt(denominator1_ref)*sqrt(denominator2_ref)));
if (ref_angle < Distance[i])
{
array[data] = i + 1; //分类
break;
}
}
if (Distance[i] <= min)
min = Distance[i];
}
//比较距离,进行分类
for (int n = 0; n < number; n++)
{
if (min == Distance[n])
{
array[data] = n + 1;
}
}
//循环一次,指针移动一位
for (int ban = 0; ban < Bands; ban++)
{
pPointer[ban]++;
}
}
//进行图像的写入
g.Write(array, Rows*Cols);
delete[] Gray;
delete[] Distance;
delete[] array;
delete[] reference;
g.Close();
AfxMessageBox("光谱角分类数据处理完毕!");
}
原文地址: https://www.cveoy.top/t/topic/jpHh 著作权归作者所有。请勿转载和采集!