您的位置:首页 > 其它

遥感影像分类(监督分类,最小距离法)

2016-02-24 17:24 162 查看
在遥感影像中,比较简单的一种分类方法就是监督分类中的最小距离法,简单的说,这种方法就是:通过比较影像中各个像素点与样本的中心点之间的距离,然后与样本点进行比较,比较后判断其属于哪一类。

由上面介绍可以知道,遥感影像最小距离法监督分类,应该分为两步:

1、获取样本点的值。

2、进行影像分类。

就这两个步骤进行介绍:

1、获取样本点:

在ENVI中,一般选取样本点使用的是ROI工具;在ERDAS中,一般选取样本点使用的是AOI工具。由于商业原因,ENVI的ROI文件是无法直接用记事本(或Notepad)等文本编辑工具打开的(我只试着用记事本打开.ROI文件,没有尝试过ERDAS的AOI文件,所以不清楚ERDAS是怎样的)。

那么,怎么获取到可以打开的样本区呢,我下面就介绍下如何用ENVI的ROI工具拿到可以直接用记事本打开的样本区:

1)打开ENVI软件,先打开要分类的影像,为了让影像中一些地物能够突出显示出来,可以选择不同的波段,我是用5,4,3显示的,5,4,3看起来容易些。



2)打开影像之后,在上图显示窗口上面又有一串菜单,找Tools(工具)下面的Region
of Interest(即ROI,就是前面三个单词的首字母),然后找到它下面的ROI tool...(后面三个省略号很突兀哦,可还是不太明白是干嘛的,不过不影响操作,所以先忽略掉),这里怎么找ROI,我就不详细叙述了,可以搜索如何用ENVI选取ROI,我直接把选取好的样本点(ENVI教程里的数据)导入。



3)下面就将ROI文件导出,在上图中显示的ROI工具界面中,选择File,再选择Outputs ROIs to ASCII,然后保存出来,就是txt为后缀的可以用编辑器打开的文件。打开之后就是排列非常整齐的描述和数字。



4)下面就是读取txt文件了,与普通的读取txt文件的方法类似,我们可以通过ROI rgb value后面的花括号里的数字创建颜色表,从而用来最后区分分类结果。读取的时候搞清楚每行的关系就可以了,类别的描述是每四行就是一种类别的描述,而样本点的属性有ID,X,Y作为空间属性,B1,B2,B3...Bn表示的是特征属性。值得注意的是,样本点的记录数字前面没有分号,可以作为区别的一个标识。

至此,样本点就读取完毕了。

因为监督分类中的最小距离分类,是需要知道各类的样本点中心,所以需要将第1步中的各个类别的样本点的特征值求平均,每个波段可以认为是一个特征。

2、进行影像分类:

在获取样本点的时候,使用的还是GDAL中的RasterIO函数。在第1步读取ROI文件的时候,就统计出类别数目,然后计算各个像素点到样本中心点的距离,判断各个像素点到哪个类别的距离最小,即将该像素点分为哪个类别。那么就需要用一个标签记录各个像素点的类别,分类完毕后,按照颜色表写入到影像文件。

//-------------------------------------开始对影像进行最小距离的分类------------------------------------------------

float *pafScanBlock = (float *)CPLMalloc((nImgSizeX)*(nImgSizeY)*sizeof(float));//定义一段用来记录图像的内存值
float *pafBlockDistancePre = (float *)CPLMalloc((nImgSizeX)*(nImgSizeY)*sizeof(float));//定义一段用来记录与某一个类别的距离
float *pafBlockDistanceNow = (float *)CPLMalloc((nImgSizeX)*(nImgSizeY)*sizeof(float));//记录与上面距离进行比较的距离

float *pafScanblockRed = (float *)CPLMalloc((nImgSizeX)*(nImgSizeY)*sizeof(float)); //定义红色波段的值
float *pafScanblockGreen = (float *)CPLMalloc((nImgSizeX)*(nImgSizeY)*sizeof(float)); //定义绿色波段的值
float *pafScanblockBlue = (float *)CPLMalloc((nImgSizeX)*(nImgSizeY)*sizeof(float)); //定义蓝色波段的值

for (int i = 0; i < nImgSizeX*nImgSizeY; i++){
pafBlockDistanceNow[i] = 0;
pafBlockDistancePre[i] = 999999999.0;
}

int *pafBlockTag = (int *)CPLMalloc((nImgSizeX)*(nImgSizeY)*sizeof(int)); //用来标记像素所属的类别

for (int i = 0; i < ClassNumber; i++){
for (int j = 0; j < BandCount; j++){
//将某个波段的影像读取到内存里
OriginalImg->GetRasterBand(j + 1)->RasterIO(GF_Read, 0, 0, nImgSizeX, nImgSizeY, pafScanBlock, nImgSizeX, nImgSizeY, GDT_Float32, 0, 0);
for (int k = 0; k < nImgSizeX*nImgSizeY; k++){
pafBlockDistanceNow[k] += (pafScanBlock[k] - Average[i][j])*(pafScanBlock[k] - Average[i][j]);
}
}
for (int j_Compare = 0; j_Compare < nImgSizeX*nImgSizeY; j_Compare++){
if (pafBlockDistanceNow[j_Compare] < pafBlockDistancePre[j_Compare])
{
pafBlockTag[j_Compare] = i + 1;
pafBlockDistancePre[j_Compare] = pafBlockDistanceNow[j_Compare];
pafBlockDistanceNow[j_Compare] = 0;
}
}
}
//-----------------------------------------------------------------------------------------------------------------
//----------------------------------输出分类的结果,将分类的结果输出到一个影像上---------------------------------------
float Color[10][3];
Color[0][0] = 0; Color[0][1] = 139; Color[0][2] = 0;
Color[1][0] = 0; Color[1][1] = 238; Color[1][2] = 0;
Color[2][0] = 0; Color[2][1] = 205; Color[2][2] = 0;
Color[3][0] = 205; Color[3][1] = 104; Color[3][2] = 57;
Color[4][0] = 255; Color[4][1] = 255; Color[4][2] = 255;
Color[5][0] = 0; Color[5][1] = 0; Color[5][2] = 200;
Color[6][0] = 150; Color[6][1] = 0; Color[6][2] = 0;
Color[7][0] = 0; Color[7][1] = 150; Color[7][2] = 0;
Color[8][0] = 0; Color[8][1] = 0; Color[8][2] = 150;
Color[9][0] = 200; Color[3][1] = 0; Color[3][2] = 0;

for (int i = 0; i < ClassNumber; i++){
for (int j = 0; j < nImgSizeX*nImgSizeY; j++){
if (pafBlockTag[j] == i + 1){
pafScanblockRed[j] = Color[i][0];
pafScanblockGreen[j] = Color[i][1];
pafScanblockBlue[j] = Color[i][2];
}
}
}

GDALDriver *poDriver = (GDALDriver*)GDALGetDriverByName("GTiff");
GDALDataset *pDstDS = poDriver->Create("Min_DistanceClassify.tif", nImgSizeX, nImgSizeY, 3, GDT_Float32, NULL);

//定义分辨率,方位等空间信息
double adfGeoTransform[6] = { 0 };
OriginalImg->GetGeoTransform(adfGeoTransform);

pDstDS->SetGeoTransform(adfGeoTransform);				//设置输出影像的空间信息
pDstDS->SetProjection(OriginalImg->GetProjectionRef());		//设置输出影像的投影信息

pDstDS->GetRasterBand(1)->RasterIO(GF_Write, 0, 0, nImgSizeX, nImgSizeY, pafScanblockRed, nImgSizeX, nImgSizeY, GDT_Float32, 0, 0);
pDstDS->GetRasterBand(2)->RasterIO(GF_Write, 0, 0, nImgSizeX, nImgSizeY, pafScanblockGreen, nImgSizeX, nImgSizeY, GDT_Float32, 0, 0);
pDstDS->GetRasterBand(3)->RasterIO(GF_Write, 0, 0, nImgSizeX, nImgSizeY, pafScanblockBlue, nImgSizeX, nImgSizeY, GDT_Float32, 0, 0);
至此,遥感影像分类(监督分类,最小距离分类)就介绍完毕,还是比较简单的分类,想要做的更好,还需要大量的看高手怎么做,然后模仿,最后再做出自己的方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息