GDAL切割重採樣遙感圖像(航拍影像、衛片)

一個小測試程序開發全過程實錄,完全新手入門級的實例,如果你還在爲處理大影像而發愁,來試試這個稱手的工具吧。

Imagec 開發日記
2013-6-25


需求:


影像數據切割,重採樣
數據切割的要求是簡單的給予矩形的等分切割,並以2的冪次爲分割單元,無需使用AOI裁切,
重採樣需要實現多種採樣模式,用戶可以切換採樣模式(下文中所提供的代碼只是利用了RasterIO的一個特性使用了默認的最近鄰重採樣方法)


基本思路


考慮是否存在使實用的gdal接口,
自行設計,利用GDAL的讀寫接口完成數據輸入輸出工作
初步瞭解,GDAL並不提供現成的切割和重採樣的接口。
/////////////////////////////////////////////////////////////////////
2013-6-26


確定使用自己的方法實現:

裁切


1、讀入數據
2、設置剪切範圍
3、完成裁切,將數據寫入目標文件

2013-6-27


重採樣

1.讀入數據
2.借鑑Warp工具代碼重寫重採樣代碼
將數據寫入目標文件

2013-6-28


重採樣2


1.讀入數據
2.使用RasterIO自帶的重採樣功能
3.數據寫入目標文件

////////////////////////////////////////////////////////////////////////////
2013-6-27


實現算法


裁切:


讀入文件
GDALDataset *poDataset;
GDALAllRegister();

//open a dataset
poDataset =(GDALDataset *)GDALOpen(fn,GA_ReadOnly);

if(poDataset == NULL)
設置相關參數爲實現裁切做準備
char **papsOptions = NULL;
const int iXSize = poSrcDS->GetRasterXSize()/2;
const int iYSize = poSrcDS->GetRasterYSize()/2;
int iSize = GDALGetBandTypeSize(GDT_Byte)/8;
//生成一個用於存放數據的緩存空間
poDstDS = poDriver->Create(fnDst,iXSize,iYSize,3,GDT_Byte,papsOptions);
GByte *abyByte = new GByte[iXSize*iYSize*bandCount];
int bandMap[3] = {1,2,3};

const char *pszSRS_WKT = poSrcDS->GetProjectionRef();
poDstDS->SetProjection(pszSRS_WKT);
poDstDS->SetGeoTransform(adfGeoTransform);

//進行裁切工作,讀取原始的數據,寫入目標文件
poSrcDS->RasterIO(GF_Read,0,0,iXSize,iYSize,abyRater,
iXSize,iYSize,GDT_Byte,bandCount,bandMap,iSize*bandCount,iSize*iXSize*3,iSize);
poDstDS->RasterIO(GF_Write,0,0,iXSize,iYSize,abyRater,
iXSize,iYSize,GDT_Byte,bandCount,bandMap,iSize*bandCount,iSize*iXSize*3,iSize);
////////////////////////////////////////////////////////////////


//數據重採樣實現:


打開數據
GDALDataset *SrcDS =  (GDALDataset *)GDALOpen(fn,GA_ReadOnly);

爲RasterIO設置一些必要參數:

const char *strWkt =pSrcDS->GetProjectionRef();
int bandCount = pSrcDS->GetRasterCount();
int iSize = GDALGetDataTypeSize(GDT_Byte)/8;
int bandMap = {1,2,3};

double adfGeoTransform[6];
pSrcDS->GetGeoTransformation(adfGeoTransform);
double dProj[4] ={0};
ImageRowCol2Projection(adfGeoTransform,0,0,dProj[0],dProj[2]);//具體參考李明錄重採樣博文
ImageRowCol2Projection(adfGeoTransform,pSrcDS->GetRasterXSize(),pSrcDS->GetRasterYSize(),dProj[1],dProj[3]);
double maxX = dProj[0] >dProj[1]?dProj[0]:dProj[1];
double minX = dProj[0]<dProj[1]?dProj[1]:dProj[0];
double maxY = dProj[2]>dProj[3]?dProj[2]:dProj[3];
double minY = dProj[2]<dProj[3]?dProj[2]:dProj[3];

double fResX = 2;
double fResY = 2;
adfGeoTransform[0] = maxX;
adfGeoTransform[3] = maxY;
adfGeoTransform[1] = adfGeoTransform[1]/fResX;
adfGeoTransform[4] = adfGeoTransform[5]/fResY;

//得到輸出圖像長寬
int iNewWidth = static_cast<int>((maxX-minX)/ABS(adfGeoTransform[1]) + 0.5);
int iNewHeight = static_cast<int>((maxY-minY)/ABS(adfGeoTransform[5]) + 0.5);
GByte *abyraster2= new GByte[iNewWidth*iNewHeight*bandCount];
創建輸出文件:
GDALDataset *pDstDS2 = poDriver->Create("good.img",
iNewWidth,iNewHeight,3,GDT_Byte,NULL);

設置輸出數據的投影:
pDstDS2->SetGeoTransform(adfGeoTransform);
pDstDS2->SetProjection(strWkt);
使用RasterIO實現數據讀寫:(重採樣全在這讀寫之間,參考第一篇文獻的 第四種方式 一節)
pSrcDS->RasterIO(GF_Read,0,0,pSrcDS->GetRasterXSize(),pSrcDS->GetRasterYSize(),abyraster2,
iNewWidth,iNewHeight,GDT_Byte,bandCount,bandMap,iSize*bandCount,
iSize*iNewWidth*3,iSize);
pDstDS->RasterIO(GF_Write,0,0,iNewWidth,iNewHeight,GDT_Byte,bandCount,bandMap,iSize*bandCount,
iSize*iNewWidth*3,iSize);
完成讀寫後關閉打開的數據集,釋放佔用的內存
if(pDstDS != NULL)
{
GDALClose((GDALDatasetH)pDstDS2);
}
GDALClose((GDALDatasetH)pSrcDS);

 

報錯實例


沒有註冊驅動導致數據讀取失敗
GDALAllRegister();
ERROR 4'../image/result.img' not recognized as a supported format.


投影問題
setGeoTransform 無法爲輸出圖像計算一個投影

參考文獻

GDAL源碼剖析(七)之GDAL RasterIO使用說明

如何使用GDAL重採樣圖像

如何使用GDAL進行AOI裁剪

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章