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

时间:2022-07-26 19:29:35

因为做任务时发现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;iRasterIO(GF_Read,0,i,ImageLength,1,pRaData,ImageLength,1,GDT_UInt16, 0, 0);
		for (int j=0;j(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;irows;i++)
	{
		for (int j=0;jcols;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;
}

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