GDAL:利用Shape文件对遥感影像进行裁剪

10 篇文章 7 订阅

支持单个或多个多边形要素的shp文件,对于没有仿射信息的影像裁剪不成功。
直接上代码:

//ImageCut.h
#include "gdal_priv.h"
#include <iostream>
#include "ogr_spatialref.h"
#include "ogrsf_frmts.h"
#include "gdalwarper.h"

using namespace std;

class ImageCut{
public:
	ImageCut();
	~ImageCut();
	/*设置影像输入路径*/
	void setSrcImageFilename(const char* pszSrcFile);
	/*设置裁剪后影像输出的路径*/
	void setDstImageFilename(const char* pszDstFile);
	/*设置shape文件的路径*/
	void setShapeFilename(const char*pszShapeName);
	/*设置输出影像的格式*/
	void setImageFormat(const char* pszFormat);
	/*开始影像AOI裁剪*/
	int ImageCutByAOI();
private:
	const char* pszSrcFile;
	const char* pszDstFile;
	const char*	pszShapeName;
	const char* pszFormat;
	/*输入影像的指针*/
	GDALDataset *ptrSrcImage;
	/*投影坐标转行列号*/
	bool Projection2ImageRowCol(double *adfGeoTransform, double dProjX, double dProjY, int &iCol, int &iRow);
	/*行列号转投影坐标*/
	bool ImageRowCol2Projection(double *adfGeoTransform, int iCol, int iRow, double &dProjX, double &dProjY);
	/*根据shape文件和输入的影像输出多边形WKT文件*/
	int outputPolygonWkt(string &pszAOIWKT);
	/*影像裁剪的代码*/
	int ImageCutting(const char* pszAOIWKT);

};

//ImageCut.cpp
#include "ImageCut.h"
ImageCut::ImageCut(){
	GDALAllRegister();
	OGRRegisterAll();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");
	CPLSetConfigOption("SHAPE_ENCODING", "");
	pszDstFile = "";
	pszFormat = "";
	pszShapeName = "";
	pszSrcFile = "";
	ptrSrcImage = NULL;
}
ImageCut::~ImageCut(){
	GDALClose(ptrSrcImage);//关闭源影像
}
void ImageCut::setSrcImageFilename(const char* pszSrcFile){
	this->pszSrcFile = pszSrcFile;
}
void ImageCut::setDstImageFilename(const char* pszDstFile){
	this->pszDstFile = pszDstFile;
}
void ImageCut::setShapeFilename(const char*pszShapeName){
	this->pszShapeName = pszShapeName;
}
void ImageCut::setImageFormat(const char* pszFormat){
	this->pszFormat = pszFormat;
}
int ImageCut::ImageCutByAOI(){
	string pszAOIWKT = "";
	int isoutput = outputPolygonWkt(pszAOIWKT);
	if (isoutput == 0)
	{
		cout << "output polygon wkt false" << endl;
		return 0;
	}
	int iscut = ImageCutting(pszAOIWKT.c_str());
	if (iscut != 1)
	{
		cout << "Image Cut false" << endl;
		return 0;
	}
	return 1;
}

int ImageCut::outputPolygonWkt(string &pszAOIWKT){
	ptrSrcImage = (GDALDataset*)GDALOpen(pszSrcFile, GA_ReadOnly);
	if (ptrSrcImage == NULL)
	{
		cout << "read image false" << endl;
		return 0;
	}
	double SrcGeoTransform[6] = { 0 };
	ptrSrcImage->GetGeoTransform(SrcGeoTransform);
	//读取shape数据--------------
	OGRDataSource *ptrShape = OGRSFDriverRegistrar::Open(pszShapeName);
	if (ptrShape == NULL)
	{
		cout << "read shape false" << endl;
		return 0;
	}
	int numLayer = ptrShape->GetLayerCount();//获取图层个数
	if (numLayer != 1)
	{
		cout << "the method only support one layer" << endl;
		return 0;
	}
	OGRLayer *ptrLayer = ptrShape->GetLayer(0);//这里只支持一个图层
	if (ptrLayer == NULL)
	{
		cout << "open the layer false" << endl;
		return 0;
	}
	ptrLayer->ResetReading();//将图层重置一下,标号从0开始
	//OGRFeatureDefn *ptrDefn = ptrLayer->GetLayerDefn();//获取当前图层的属性表结构,主要包涵一些字段信息

	OGRFeature *poFeature = NULL;//定义包含几何和属性的要素指针


	//统计一下图层内多边形个数
	int count_ = 0, cout_1(0);
	while ((poFeature = ptrLayer->GetNextFeature()) != NULL){
		count_++;
	}
	poFeature = NULL;
	ptrLayer->ResetReading();
	//-*-----------------------------------------------------------
	//string pszAOIWKT = "";//待输出的多边形wkt文件
	pszAOIWKT.clear();
	if (count_ == 1)
	{
		pszAOIWKT = "POLYGON ((";
	}
	else
	{
		pszAOIWKT = "MULTIPOLYGON (((";
	}
	while ((poFeature = ptrLayer->GetNextFeature()) != NULL)
	{
		OGRGeometry *ptrGeometry = poFeature->GetGeometryRef();//获得要素的几何属性
		if (wkbFlatten(ptrGeometry->getGeometryType()) != wkbPolygon)
		{
			cout << "Only polygon feature cutting images are supported(wkbPolygon)" << endl;
			return 0;
		}
		OGRPolygon *ptrPolygon = (OGRPolygon *)ptrGeometry->clone();//将几何要素指针强制转化为多边形要素指针
		OGRLinearRing *ptrOGRLinearRing = ptrPolygon->getExteriorRing();//获取多边形的外环点的指针
		int numExterRing = ptrOGRLinearRing->getNumPoints();//外环点数
		int numInteriorRing = ptrPolygon->getNumInteriorRings();//内环数(暂时不加入考虑)
		double x, y;//存储临时的xy值
		int row_, col_;//存储临时的行列值
		for (int i = 0; i < numExterRing; i++)
		{
			if (i != 0){
				pszAOIWKT += ",";
			}
			x = ptrOGRLinearRing->getX(i);
			y = ptrOGRLinearRing->getY(i);
			row_, col_;
			Projection2ImageRowCol(SrcGeoTransform, x, y, row_, col_);
			pszAOIWKT += (to_string(row_) + " " + to_string(col_));
		}
		cout_1++;
		if (count_ == 1)
		{
			pszAOIWKT += "))";
		}
		else if (cout_1 == count_)
		{
			pszAOIWKT += ")))";
		}
		else
		{
			pszAOIWKT += ")),((";
		}
		OGRFeature::DestroyFeature(poFeature);
	}

	//GDALClose(ptrSrcImage);//关闭影像,放在了析构函数,避免重复打开影像
	OGRDataSource::DestroyDataSource(ptrShape);
	OGRCleanupAll();
}
int ImageCut::ImageCutting(const char* pszAOIWKT){
	// 打开原始图像并计算图像信息
	//GDALDataset *pSrcDS = (GDALDataset*)GDALOpen(pszSrcFile, GA_ReadOnly);
	GDALDataType eDT = ptrSrcImage->GetRasterBand(1)->GetRasterDataType();

	int iBandCount = ptrSrcImage->GetRasterCount();
	int iSrcWidth = ptrSrcImage->GetRasterXSize();
	int iSrcHeight = ptrSrcImage->GetRasterYSize();

	double pSrcGeoTransform[6] = { 0 };
	double pDstGeoTransform[6] = { 0 };
	ptrSrcImage->GetGeoTransform(pSrcGeoTransform);			//图像的仿射变换信息
	memcpy(pDstGeoTransform, pSrcGeoTransform, sizeof(double) * 6);

	// 将传入的AOI的WKT处理为一个OGRGeometry类型,用于后续处理
	char *pszWKT = (char*)pszAOIWKT;
	OGRGeometry* pAOIGeometry = NULL;
	//cout << *pszWKT << endl;
	if (*pszWKT == 'P')
	{
		pAOIGeometry = OGRGeometryFactory::createGeometry(wkbPolygon);
	}
	else
	{
		pAOIGeometry = OGRGeometryFactory::createGeometry(wkbMultiPolygon);
	}

	pAOIGeometry->importFromWkt(&pszWKT);

	OGREnvelope eRect;
	pAOIGeometry->getEnvelope(&eRect);

	// 设置输出图像的左上角坐标
	GDALApplyGeoTransform(pSrcGeoTransform, eRect.MinX, eRect.MinY, (&pDstGeoTransform[0]), &(pDstGeoTransform[3]));
	// 根据裁切范围确定裁切后的图像宽高
	int iDstWidth = static_cast<int>(eRect.MaxX - eRect.MinX);
	int iDstHeight = static_cast<int>(eRect.MaxY - eRect.MinY);

	// 创建输出图像
	GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);
	GDALDataset *pDstDS = poDriver->Create(pszDstFile, iDstWidth, iDstHeight, iBandCount, eDT, NULL);
	pDstDS->SetGeoTransform(pDstGeoTransform);
	pDstDS->SetProjection(ptrSrcImage->GetProjectionRef());

	// 构造坐标转换关系
	void *hTransformArg = GDALCreateGenImgProjTransformer2((GDALDatasetH)ptrSrcImage, (GDALDatasetH)pDstDS, NULL);
	GDALTransformerFunc pfnTransformer = GDALGenImgProjTransform;

	// 构造GDALWarp的变换选项
	GDALWarpOptions *psWO = GDALCreateWarpOptions();

	psWO->papszWarpOptions = CSLDuplicate(NULL);
	psWO->eWorkingDataType = eDT;
	psWO->eResampleAlg = GRA_NearestNeighbour;

	psWO->hSrcDS = (GDALDatasetH)ptrSrcImage;
	psWO->hDstDS = (GDALDatasetH)pDstDS;

	psWO->pfnTransformer = pfnTransformer;
	psWO->pTransformerArg = hTransformArg;

	psWO->nBandCount = iBandCount;
	psWO->panSrcBands = (int *)CPLMalloc(psWO->nBandCount*sizeof(int));
	psWO->panDstBands = (int *)CPLMalloc(psWO->nBandCount*sizeof(int));
	for (int i = 0; i < iBandCount; i++)
	{
		psWO->panSrcBands[i] = i + 1;
		psWO->panDstBands[i] = i + 1;
	}

	// 设置裁切AOI,AOI中的坐标必须是图像的行列号坐标,否则不能进行裁切
	psWO->hCutline = (void*)pAOIGeometry;
	// 设置上面的hCutline的值和使用下面的CUTLINE配置项的效果一样,两个选择一个即可
	psWO->papszWarpOptions = CSLSetNameValue(psWO->papszWarpOptions, "CUTLINE", pszAOIWKT);

	// 创建GDALWarp执行对象,并使用GDALWarpOptions来进行初始化
	GDALWarpOperation oWO;
	oWO.Initialize(psWO);

	// 执行处理
	oWO.ChunkAndWarpImage(0, 0, iDstWidth, iDstHeight);

	// 释放资源和关闭文件
	GDALDestroyGenImgProjTransformer(psWO->pTransformerArg);
	GDALDestroyWarpOptions(psWO);

	GDALClose((GDALDatasetH)pDstDS);

	return 1;
}
bool ImageCut::Projection2ImageRowCol(double *adfGeoTransform, double dProjX, double dProjY, int &iCol, int &iRow)
{
	try
	{
		double dTemp = adfGeoTransform[1] * adfGeoTransform[5] - adfGeoTransform[2] * adfGeoTransform[4];
		double dCol = 0.0, dRow = 0.0;
		dCol = (adfGeoTransform[5] * (dProjX - adfGeoTransform[0]) -
			adfGeoTransform[2] * (dProjY - adfGeoTransform[3])) / dTemp + 0.5;
		dRow = (adfGeoTransform[1] * (dProjY - adfGeoTransform[3]) -
			adfGeoTransform[4] * (dProjX - adfGeoTransform[0])) / dTemp + 0.5;

		iCol = static_cast<int>(dCol);
		iRow = static_cast<int>(dRow);
		return true;
	}
	catch (...)
	{
		return false;
	}
}

bool ImageCut::ImageRowCol2Projection(double *adfGeoTransform, int iCol, int iRow, double &dProjX, double &dProjY)
{
	//adfGeoTransform[6]  数组adfGeoTransform保存的是仿射变换中的一些参数,分别含义见下
	//adfGeoTransform[0]  左上角x坐标 
	//adfGeoTransform[1]  东西方向分辨率
	//adfGeoTransform[2]  旋转角度, 0表示图像 "北方朝上"
	//adfGeoTransform[3]  左上角y坐标 
	//adfGeoTransform[4]  旋转角度, 0表示图像 "北方朝上"
	//adfGeoTransform[5]  南北方向分辨率

	try
	{
		dProjX = adfGeoTransform[0] + adfGeoTransform[1] * iCol + adfGeoTransform[2] * iRow;
		dProjY = adfGeoTransform[3] + adfGeoTransform[4] * iCol + adfGeoTransform[5] * iRow;
		return true;
	}
	catch (...)
	{
		return false;
	}
}
#include "ImageCut.h"

int main(){
	const char *ptrShapeFilename = "D:/shp/shp2.shp";
	const char *ptrImageFilename = "D:/software/practice/GF2_PMS2_E100.6_N26.5_20190104_L1A0003735651_AC - 副本.tiff";
	//const char *ptrImageFilename = "F:/测试数据/GF1/GF1_PMS2_E113.2_N23.5_20180113_L1A0002927191-MSS2.tiff";
	const char *ptrDstImageFilename = "D:/OUTPUT5.tiff";
	const char *pszFormat = "GTiff";
	ImageCut ptrImageCut;
	ptrImageCut.setSrcImageFilename(ptrImageFilename);
	ptrImageCut.setDstImageFilename(ptrDstImageFilename);
	ptrImageCut.setImageFormat(pszFormat);
	ptrImageCut.setShapeFilename(ptrShapeFilename);
	cout << "开始AOI裁剪" << endl;
	ptrImageCut.ImageCutByAOI();
	cout << "计算结束" << endl;
	system("pause");
	return 1;
}

参考李明录大哥的代码:
https://blog.csdn.net/liminlu0314/article/details/6136512?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522158717665319195239802256%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=158717665319195239802256&biz_id=0&utm_source=distribute.pc_search_result.none-task-blog-2blogfirst_rank_v2~rank_v25-1
在这里插入图片描述

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
### 回答1: 我可以提供一些建议,但最终的解决方案取决于您的目标和数据集。首先,您可以尝试使用卷积神经网络(CNN)来检测遥感影像的变化。CNN可以处理复杂的图像,并从中提取重要的信息,从而准确地检测变化。其次,您可以使用Keras建立CNN模型,并利用其优化器和损失函数来训练模型。最后,您可以使用Keras中的工具来评估模型的性能,以确保它可以正确地识别遥感影像的变化。 ### 回答2: 卷积神经网络(Convolutional Neural Network, CNN)是一种常用于图像处理的神经网络模型。Python中的Keras库提供了方便实现CNN的工具。 在对遥感影像进行变化检测时,可以使用CNN提取遥感影像中的特征。首先,需要将遥感影像数据预处理为适合输入到CNN中的格式。通常可以将遥感影像切分为小块,并将每个小块作为CNN的输入。 然后,可以使用Keras提供的卷积层、池化层、全连接层等构建CNN模型。卷积层可以通过设置卷积核大小和通道数来提取影像的特征,池化层可以减少特征图的维度,全连接层可以将提取到的特征映射到具体的变化类别。 在构建好CNN模型后,可以使用Keras提供的编译和训练函数对模型进行训练。通过反向传播算法,CNN可以自动学习遥感影像中的变化特征。 训练完成后,可以使用CNN对新的遥感影像进行变化检测。输入新影像块到CNN中预测其对应的变化类别。 最后,可以根据CNN的预测结果将变化区域标记出来,或者进行更进一步的分析和处理。 总之,Python中的Keras库提供了方便实现卷积神经网络的工具,可以用于遥感影像的变化检测。 ### 回答3: Python keras代码可以使用卷积神经网络进行遥感影像的变化检测。遥感影像变化检测是利用遥感技术获取的不同时期的遥感影像数据,通过对比两幅影像的差异来分析地表的变化情况,对于城市规划、农业管理和环境监测等方面具有重要意义。 首先,需要准备两幅不同时期的遥感影像数据作为训练数据集。可以使用Python的库来读取和处理遥感影像数据,例如GDAL库。 接下来,使用Keras库构建卷积神经网络模型。可以使用卷积层、池化层和全连接层搭建神经网络架构。卷积层可以提取图像的特征,池化层可以减小特征图的尺寸并保留重要的特征,全连接层用于分类。 在训练模型之前,需要对遥感影像数据进行预处理。可以进行影像配准,使得两幅影像的像素对应位置一致。还可以对影像进行归一化或标准化处理,以便于模型学习。 然后,将数据集划分为训练集和测试集。训练集用于训练模型,测试集用于评估模型的性能。 在训练过程中,可以使用反向传播算法进行模型优化。通过多次迭代训练模型,使得模型逐渐收敛并学习到输入数据的特征。 最后,使用训练好的模型对新的遥感影像进行变化检测。将新影像输入到模型中,通过模型的输出判断地表是否有变化。 总之,使用Python keras代码,可以基于卷积神经网络对遥感影像进行变化检测。这种方法能够提取影像的特征,并通过训练模型来判断地表是否发生了变化,具有较高的准确性和实用性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值