如何将GTiff格式的遥感图像转换为OpenCV可以读取的格式

时间:2020-12-09 06:35:13

因为做任务时发现opencv只是支持部分Tiff文件格式,对于GeoTiff这样带有投影和坐标信息的遥感栅格影像总是读不出来,输出时这些信息也会消失。搜网上的解决方法大多都是基于早期的IplImage与CvMat数据结构来表示图像,新版本的opencv中只需Mat类就能解决。本人是菜鸟,对OpenCV接触不多,所以就利用GDAL函数库作中介对图像进行读写,并赋给Mat矩阵。这是比较简单的方法将GeoTiff遥感图像转化为Mat格式,即只是希望能够其他遇到这个问题的人能够有所参考和改进,顺便告诉下我,本人感激不尽。参考网址:http://blog.csdn.net/liminlu0314/article/details/7433936

这段代码使用了GDAL(1.10.1)与OpenCV(2.4.8)两个函数库,只是针对单个波段的影像而言:

#include "gdal_priv.h"
#include

//单个波段影像而言
Mat ConvertImage2CV(const char *pszRasterFile)
{
//为了支持中文路径,请添加下面这句代码
CPLSetConfigOption("GDAL_FILENAME_IS_UTF8","NO");
//注册栅格驱动
GDALAllRegister();
GDALDataset *poRaDS=(GDALDataset*)GDALOpen(pszRasterFile,GA_ReadOnly);//以只读方式打开遥感图像
if (poRaDS==NULL)
printf("文件: %s打开失败.\n",pszRasterFile);


GDALRasterBand *poband=poRaDS->GetRasterBand(1);
int nBandCount=poRaDS->GetRasterCount();
int ImageLength=poRaDS->GetRasterXSize();
int ImageWidth=poRaDS->GetRasterYSize();

DT_16U *pRaData=new DT_16U[ImageLength];
if (nBandCount!=1)
printf("掩膜文件存在多个波段,检查输入是否有误\n");

Mat MaskIM(ImageWidth,ImageLength,CV_16UC1,Scalar(0));

//遍历所有像素,并赋值
for (int i=0;i {
poband->RasterIO(GF_Read,0,i,ImageLength,1,pRaData,ImageLength,1,GDT_UInt16, 0, 0);
for (int j=0;j {
MaskIM.at (i,j)=pRaData[j];
}
}
//别忘记释放
RELEASE(pRaData);
GDALClose((GDALDatasetH)poRaDS);
return MaskIM;
}


//单个波段影像而言
int SaveMat2Image(Mat &MaskIM,GDALDataset *poReferIM,const char *pszRasterFile,const char* pszFormat )
{
int XSize=MaskIM->cols;//获得输出对象大小
int YSize=MaskIM->rows;

//为了支持中文路径,请添加下面这句代码
CPLSetConfigOption("GDAL_FILENAME_IS_UTF8","NO");
//注册栅格驱动
GDALAllRegister();
GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);
if( poDriver == NULL )
{
printf("不能创建制定类型的文件,请检查该文件类型GDAL是否支持创建!");
return RE_FILENOTSUPPORT;
}

//假设输入图像也是16U的数据 ,1个波段
GDALDataset *poRasterDS = poDriver->Create(pszRasterFile, XSize, YSize, 1, GDT_UInt16, NULL);
double dGeoTrans[6] = {0};
//设置仿射变换参数
poReferIM->GetGeoTransform(dGeoTrans);
poRasterDS->SetGeoTransform(dGeoTrans);
//设置图像投影信息
poRasterDS->SetProjection(poReferIM->GetProjectionRef());

GDALRasterBand *poband=poRasterDS->GetRasterBand(1);
DT_16U *pRaData=new DT_16U[XSize];
for (int i=0;i rows;i++)
{
for (int j=0;j cols;j++)
{
pRaData[j]=MaskIM->at (i,j);
}
poband->RasterIO(GF_Write,0,i,XSize,1,pRaData,XSize,1,GDT_UInt16, 0, 0);
}
printf("Mat存储为影像成功\n");
RELEASE(pRaData);
GDALClose((GDALDatasetH)poRasterDS);
return RE_SUCCESS;
}



int main(int argc,char **argv)
{
GDALDataset *poImageDS=ReadImageFile();
const char *pszRaReadFile="D:\\Documents\\ExerciseData\\Mask.tif";
Mat MaskIM=ConvertImage2CV(pszRaReadFile);


//poImageDS影像提供投影和坐标信息,Format为输出格式
const char *pszSaveRaFile="D:\\Documents\\ExerciseData\\MaskMat.tif";
const char* pszFormat="GTiff";
int z=SaveMat2Image(MaskIM,poImageDS,pszSaveRaFile,pszFormat);
if (z==RE_SUCCESS)
printf("输出文件成功\n");
else
{
printf("输出文件失败\n");
return 0;
}

GDALClose((GDALDatasetH)poImageDS);
return 1;
}

经过编译运行后是成功的。