C++调用GDAL库读取并输出tif文件,并计算斑块面积输出景观指数:CSD
// readfile.cpp : 定义控制台应用程序的入口点。
//
/*
part of the codes were cite from: http://www.gdal.org/gdal_tutorial.html
and remaining of code were created :by www.cnblogs.com/AmatVictorialCuram/
and please mark the site if you cite the program fo commercial of publication.
*/
#include "stdafx.h"
#include <iostream>
#include "gdal.h"
#include "gdal_priv.h"
/**/
#include <iomanip>
#include <fstream>
using namespace std;
/**/
int minLabel(int a,int b); int maxLabel(int a,int b); double csd(int *Parea,int length); int main()
{
/*
part of the codes were cite from: http://www.gdal.org/gdal_tutorial.html
and remaining of code were created :by www.cnblogs.com/AmatVictorialCuram/
and please mark the site if you cite the program fo commercial of publication.
*/
const char *pszFilename="E:\\tif/fragstats/sample.tif";
GDALDataset *poDataset; GDALAllRegister(); poDataset = (GDALDataset *) GDALOpen( pszFilename, GA_ReadOnly );
if( poDataset == NULL )
{
cout<<"file read error!"<<endl;;
}
double adfGeoTransform[]; printf( "Driver: %s/%s\n",
poDataset->GetDriver()->GetDescription(),
poDataset->GetDriver()->GetMetadataItem( GDAL_DMD_LONGNAME ) ); printf( "Size is %dx%dx%d\n",
poDataset->GetRasterXSize(), poDataset->GetRasterYSize(),
poDataset->GetRasterCount() ); if( poDataset->GetProjectionRef() != NULL )
printf( "Projection is `%s'\n", poDataset->GetProjectionRef() ); if( poDataset->GetGeoTransform( adfGeoTransform ) == CE_None )
{
printf( "Origin = (%.6f,%.6f)\n",
adfGeoTransform[], adfGeoTransform[] ); printf( "Pixel Size = (%.6f,%.6f)\n",
adfGeoTransform[], adfGeoTransform[] );
} GDALRasterBand *poBand;
int nBlockXSize, nBlockYSize;
int bGotMin, bGotMax;
double adfMinMax[]; poBand = poDataset->GetRasterBand( );
poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
printf( "Block=%dx%d Type=%s, ColorInterp=%s\n",
nBlockXSize, nBlockYSize,
GDALGetDataTypeName(poBand->GetRasterDataType()),
GDALGetColorInterpretationName(
poBand->GetColorInterpretation()) ); adfMinMax[] = poBand->GetMinimum( &bGotMin );
adfMinMax[] = poBand->GetMaximum( &bGotMax );
if( ! (bGotMin && bGotMax) )
GDALComputeRasterMinMax((GDALRasterBandH)poBand, TRUE, adfMinMax); printf( "Min=%.3fd, Max=%.3f\n", adfMinMax[], adfMinMax[] ); if( poBand->GetOverviewCount() > )
printf( "Band has %d overviews.\n", poBand->GetOverviewCount() ); if( poBand->GetColorTable() != NULL )
printf( "Band has a color table with %d entries.\n",
poBand->GetColorTable()->GetColorEntryCount() );
/*****
Reading Raster Data
*****/
float *pafScanline;
int nXSize = poBand->GetXSize();
int nYSize=poBand->GetYSize(); //读取图像的nXSize*nYSize数据
pafScanline = (float*) CPLMalloc(sizeof(float)*nXSize*nYSize);//创建指针
poBand->RasterIO(
GF_Read,//第一个参数表示要读入数据还是写入数据
, ,//nXOff, nYOff表示读取或者写入图像数据的起始坐标图像的左上角坐标为(0,0)
nXSize, nYSize,/*nXSize, nYSize表示读取或者写入图像数据的窗口大小,nXSize表示宽度,
nYSize表示高度,均使用像素为单位,该宽度和高度是从第二个和第三个参数处开始计算。
这两个参数和第二第三个参数一起表示就是,读取和写入图像的窗口位置和大小。*/
pafScanline, //指向存储数据的一个指针
nXSize, nYSize,//指定缓冲区的大小
GDT_Float32,
, );
// poBand->RasterIO( GF_Read, 0, 0, nXSize, nYSize, pafScanline, nXSize, nYSize, GDT_Float32, 0, 0 );
cout<<"列数:nXSize="<<nXSize<<endl;
cout<<"行数:nYSize="<<nYSize<<endl;
//system("pause"); //创建nXSize*nYSize的float数组
float **data=new float *[nXSize];//每列有nXSize列,data数组的大小与dataLabel数组的大小相同,类型不同
int **dataLabel=new int *[nXSize];//创建标签数组,有nYSize行,nXSize列
int t=,i=,j=;
for(int i=;i<nYSize;i++)//nYSize行
{
dataLabel[i]=new int [nXSize];
data[i] = new float [nXSize];
} cout<<"输出元数据数组data:"<<endl;
for(int i=;i<nYSize;i++)
{
for(int j=;j<nXSize;j++)
{
data[i][j]=pafScanline[t++];
cout<<setw()<<data[i][j];
}
cout<<endl;
}
cout<<endl;
//system("pause");
cout<<"输出标签数组dataLabel数组:"<<endl;
for(int i=;i<nYSize;i++)
{
cout<<endl;
for(int j=;j<nXSize;j++)
{
dataLabel[i][j]=nYSize*nXSize;
cout<<setw()<<dataLabel[i][j];
}
}
//system("pause");
cout<<endl;
cout<<"联通区域标记算法开始:"<<endl;
dataLabel[][]=;//把左上角的第一个标签赋值为1
int indexcolor=;
for(i=;i<nYSize;i++)
{
for(j=;j<nXSize;j++)
{
if(i==)
{
if(j==)
continue;
if(data[i][j]==data[i][j-])
dataLabel[i][j]=dataLabel[i][j-];
else
{
dataLabel[i][j]=++indexcolor;
}
continue;
}
if(j==)
{
if(data[i][j]==data[i-][j])
{
if(dataLabel[i-][j]<dataLabel[i][j])
dataLabel[i][j]=dataLabel[i-][j];
}
if(data[i][j]==data[i-][j+])
{
if(dataLabel[i-][j+]<dataLabel[i][j])
dataLabel[i][j]=dataLabel[i-][j+];
}
if(dataLabel[i][j]==nYSize*nXSize)
{
dataLabel[i][j]=++indexcolor;
}
continue;
}
//if(edgeCheckL(i,j) && data[i][j]==data[i][j-1])//左边的,
if(j> && data[i][j]==data[i][j-])
{
if(dataLabel[i][j-]<dataLabel[i][j])
dataLabel[i][j]=dataLabel[i][j-]; }
//if(edgeCheckLU(i,j) && data[i][j]==data[i-1][j-1])//左上角的
if((i> && j>)&& data[i][j]==data[i-][j-])
{
if(dataLabel[i-][j-]<dataLabel[i][j])
dataLabel[i][j]=dataLabel[i-][j-];
}
//if(edgeCheckU(i,j) && data[i][j]==data[i-1][j])//上面的
if(i> && data[i][j]==data[i-][j])
{
if(dataLabel[i-][j]<dataLabel[i][j])
dataLabel[i][j]=dataLabel[i-][j];
}
//if(edgeCheckUR(i,j) && data[i][j]==data[i-1][j+1])//右上角的
if((i> && j<nYSize-) && data[i][j]==data[i-][j+])
{
if(dataLabel[i-][j+]<dataLabel[i][j])
dataLabel[i][j]=dataLabel[i-][j+];
}
if(dataLabel[i][j]==nYSize*nXSize)
dataLabel[i][j]=++indexcolor;
}
}
//system("pause");
cout<<endl;
cout<<"输出第一次标记数组"<<endl<<endl;
for(i=;i<nYSize;i++)
{
for(j=;j<nXSize;j++)
{
cout<<setw()<<dataLabel[i][j];
}
cout<<endl;
}
//system("pause");
cout<<"合并首次生成的标签数组。。。。"<<endl<<endl; //合并:像素值相同,但是标签不同,就把标签值大的变为小的。
for(i=;i<nYSize;i++)//行
{
for(j=;j<nXSize;j++)//列
{
if(i==)//第0行,只判左边的!
{
if(j==)//第一个元素
{
j=;//跳过第一个元素,直接从第二个元素:data[0][1]判断
//判断并执行合并:
if(data[i][j-]==data[i][j] && dataLabel[i][j-]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=;m<nYSize;m++)
{
for(int n=;n<nXSize;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i][j-]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i][j-]);
}
}
}
}
}
}
else//非0行
{
if(j==)//第0列,但不是第一行的:只判断上、右上两个方向
{
if(data[i-][j]==data[i][j] && dataLabel[i-][j]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=;m<nYSize;m++)
{
for(int n=;n<nXSize;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i-][j]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i-][j]);
}
}
}
}
if(data[i-][j+]==data[i][j] && dataLabel[i-][j=]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=;m<nYSize;m++)
{
for(int n=;n<nXSize;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i-][j+]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i-][j+]);
}
}
}
}
}
else if(j==nYSize-)//非0行且最后一列的:判断左、左上、上三个方向
{
if(data[i][j-]==data[i][j] && dataLabel[i][j-]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=;m<nYSize;m++)
{
for(int n=;n<nXSize;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i][j-]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i][j-]);
}
}
}
}
if(data[i-][j-]==data[i][j] && dataLabel[i-][j-]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=;m<nYSize;m++)
{
for(int n=;n<nXSize;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i-][-]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i-][j-]);
}
}
}
}
if(data[i-][j]==data[i][j] && dataLabel[i-][j]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=;m<nYSize;m++)
{
for(int n=;n<nXSize;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i-][j]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i-][j]);
}
}
}
} }
else//非0行且(既不是第一列,也不是最后一列的):判断左、左上、上、右上四个方向
{
if(data[i][j-]==data[i][j] && dataLabel[i][j-]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=;m<nYSize;m++)
{
for(int n=;n<nXSize;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i][j-]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i][j-]);
}
}
}
}
if(data[i-][j-]==data[i][j] && dataLabel[i-][j-]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=;m<nYSize;m++)
{
for(int n=;n<nXSize;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i-][-]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i-][j-]);
}
}
}
}
if(data[i-][j]==data[i][j] && dataLabel[i-][j]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=;m<nYSize;m++)
{
for(int n=;n<nXSize;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i-][j]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i-][j]);
}
}
}
}
if(data[i-][j+]==data[i][j] && dataLabel[i-][j+]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=;m<nYSize;m++)
{
for(int n=;n<nXSize;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i-][j+]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i-][j+]);
}
}
}
}
}
} }
}
t=;
//system("pause");
cout<<"输出合并后的标签数组dataLabel:"<<endl;
for(i=;i<nYSize;i++)
{
for(j=;j<nXSize;j++)
{
if(dataLabel[i][j]>t)
{
t++;
}
cout<<setw()<<dataLabel[i][j]; }
cout<<endl;
}
cout<<endl<<"t="<<t<<endl;
cout<<"联通区域标记算法结束end!!!"<<endl;
//system("pause");
int max=;
for(int i=;i<nYSize;i++)
{
for(int j=;j<nXSize;j++)
{
if(dataLabel[i][j]>max)
{
max=dataLabel[i][j];
}
}
}
cout<<"maxLabel="<<max<<endl;
int *Pid=new int [max+];
int *Parea=new int [max+];
for(i=;i<max+;i++)
{
Pid[i]=i;
Parea[i]=;
}
/////////////////////////////
for(int i=;i<nYSize;i++)
{
for(int j=;j<nXSize;j++)
{
Parea[dataLabel[i][j]]++;
}
}
t=max+;
for(i=;i<t;i++)
{ cout<<"dataLabel为"<<i<<"的面积为:"<<Parea[i]<<endl;
} double Xi=,Si=;
int NPatch=;
for(i=;i<t;i++)
{
if(Parea[i]!=)
{
NPatch++;
Xi=Xi+Parea[i];//求出板块总面积
}
/*cout<<"NPatch="<<NPatch<<endl;
cout<<"Xi="<<Xi<<endl;*/
}
cout<<"NPatch="<<NPatch<<endl;
//cout<<"Xi="<<Xi<<endl;
Xi=Xi/NPatch;//面积平均数
cout<<"Initial Value:Xi="<<Xi<<endl;
cout<<"Initial Value:Si="<<Si<<endl;
//计算出所有
for(i=;i<t;i++)
{
if(Parea[i]!=)
{
Si=Si+((Parea[i]-Xi)*(Parea[i]-Xi))/NPatch;
}
}
cout<<"方差="<<Si<<endl;
Si=sqrt(Si);
cout<<"Standard Deviation(标准差)="<<Si<<endl;
cout<<endl; /****输出内容写出到文件当中****/
ofstream ocout;
//ocout.open("result.csv");
//ocout.open("result.txt");
ocout.open("result.csv");
/****将计算出的结果输出到屏幕****/
ocout<<"PatchID"<<","<<"Area"<<","<<"CSD"<<endl;
for(i=;i<t;i++)
{
if(Parea[i]!=)
{ //ocout<<"Patch: Label="<<i<<setw(4)<<" Area="<<Parea[i]<<setw(10)<<"CSD="<<(Parea[i]-Xi)/Si<<endl;
ocout<<i<<",";
ocout<<Parea[i]<<",";
ocout<<(Parea[i]-Xi)/Si<<","<<endl;
}
}
/*******后面的这一部分没有太大的实质性用处,可有可无**********/
const char *pszFormat = "GTiff";
GDALDriver *poDriver;
char **papszMetadata; poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat); if( poDriver == NULL )
exit( ); papszMetadata = poDriver->GetMetadata();
if( CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATE, FALSE ) )
printf( "Driver %s supports Create() method.\n", pszFormat );
if( CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATECOPY, FALSE ) )
printf( "Driver %s supports CreateCopy() method.\n", pszFormat ); /*释放读取文件用的指针*/
CPLFree(pafScanline);
//关闭文件
GDALClose((GDALDatasetH)poDataset);
free(dataLabel);
free(data);
free(Parea);
free(Pid);
//
ocout.close();
}
int minLabel(int a,int b)
{
return (a>b)?b:a;
}
int maxLabel(int a,int b)
{
return (a<b)?b:a;
}
double csd(int *Parea,int length)
{
return ;
}
C++调用GDAL库读取并输出tif文件,并计算斑块面积输出景观指数:CSD的更多相关文章
- GDAL库——读取图像并提取基本信息
GDAL库是一个跨平台的栅格地理数据格式库,包括读取.写入.转换.处理各种栅格数据格式(有些特定的格式对一些操作如写入等不支持).它使用了一个单一的抽象数据模型就支持了大多数的栅格数据.这里有GDAL ...
- [原创]java WEB学习笔记41:简单标签之带属性的自定义标签(输出指定文件,计算并输出两个数的最大值 demo)
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...
- 基于GDAL库,读取.grd文件(以海洋地形数据为例)C++版
技术背景 海洋地形数据主要是通过美国全球地形起伏数据(GMT)获得,数据格式为grd(GSBG)二进制数据,打开软件通过是Surfer软件,surfer软件可进行数据的编辑处理,以及进一步的可视化表达 ...
- 基于GDAL库,读取.nc文件(以海洋表温数据为例)C++版
对于做海洋数据处理的同学,会经常遇到nc格式的文件,nc文件的格式全称是NetCDF,具体的详细解释请查询官网[https://www.unidata.ucar.edu/software/netcdf ...
- 使用C#版本的gdal库打开hdf文件
作者:朱金灿 来源:http://blog.csdn.net/clever101 最近应同事的请求帮忙研究下使用C#版的gdal库读取hdf文件,今天算是有一点成果,特地做一些记录. 首先是编译C#版 ...
- GDAL C#读取shp中文属性值乱码问题
GDAL的C#版本读取shp中,如果属性值中含有中文,读出来有可能是乱码的问题,根据SWIG生成的C#代码调试发现问题所在,在Ogr.cs文件中有这么一个函数,代码如下: internal stati ...
- 浅析GDAL库C#版本支持中文路径问题
GDAL库对于C#的支持问题还是蛮多的,对于中文路径的支持就是其中之一(另一个就是通过OGR库获取图形的坐标信息). 关于C#支持中文路径,看过我之前博客的应该都不陌生,如果使用的是我修改过的GDAL ...
- GDAL库调试(包括跨语言调试)
很多时候都需要调试GDAL库,尤其是像学习GDAL库中的某些算法是如何实现的时候,调试就必不可少了. 首先说明用C++的调试.以VS2008为例进行说明. 编译DEBUG版本的GDAL库,这个可以参考 ...
- 转 mysql查询结果输出到文件
mysql查询结果输出到文件 mysql查询结果导出/输出/写入到文件 方法一:直接执行命令:mysql> select count(1) from table into outfile ...
随机推荐
- scala目录
1. 使用Scala(构建这样一个应用,它会取回一份列表,其中包括用户持有的股票的代码以及股份,并告知他们在当前日期为止的这些投资的总价.这包含了几件事:获取用户输入.读文件.解析数据.写文件.从We ...
- 20条IPTables防火墙规则用法!
导读 管理网络流量是系统管理员必需处理的最棘手工作之一,我们必需规定连接系统的用户满足防火墙的传入和传出要求,以最大限度保证系统免受攻击.很多用户把 Linux 中的 IPTables 当成一个防火墙 ...
- Foundation学习笔记
. 链接:Foundation学习,代码实例总结(pdf版) .
- C# 之 HttpWebRequest类
提供 WebRequest 类的 HTTP 特定的实现. 继承层次结构 System.Object → System.MarshalByRefObject → System.Net.We ...
- 自定义uitableviewcell通过加上滑动手势进行删除对应的行。PS:用代理来实现
#import <UIKit/UIKit.h> @class ZSDCustomCell; //协议 @protocol ZSDCustomCellDelegate <NSObjec ...
- Oracle基础 物理备份 冷备份和热备份(转)
一.冷备份介绍: 冷备份数据库是将数据库关闭之后备份所有的关键性文件包括数据文件.控制文件.联机REDO LOG文件,将其拷贝到另外的位置.此外冷备份也可以包含对参数文件和口令文件的备份,但是这 ...
- ASP.NET入门(1) - 建立和开发ASP.NET 5 项目
原文转载自:http://www.cnblogs.com/zergcom/p/4493358.html 建立项目 首先,目前只有VS 2015支持开发最新的ASP.NET 5 程序,所以我们首先需要下 ...
- Centos7 安装redis3.2.3 过程
1:安装wget: yum install wget2:安装pip: 1:sudo yum -y install epel-release 2:sudo yum -y install py ...
- React Native学习-控制横竖屏第三方组件:react-native-orientation
在项目中,有时候可能会想使不同的页面显示的横竖屏也不一样,比如前一段我做的<广播体操>的项目,在首页面,肯定是想使页面为竖屏显示,但是播放页面要为横屏显示,即使用户的手机可以转屏,我们的播 ...
- 最初步的正则表达式引擎:生成nfa
这个版本修改了前面版本的两个个bug. 第一个:识别到字符集的时候,只是将name_number加1,却并不对reg_pattern_table[name_number]进行初始化. 第二个:识别到假 ...