去除背景的gdal矢量化

由于gdal的矢量化在大图上效率太低,这里采用掩膜去除背景后矢量化操作。

复制后直接使用以下Raster2Vector函数即可

//Raster2Vector:栅格转矢量
//注意:
//	   程序中调用了创建掩膜函数!
//输入:
//     pszSrcFile—栅格数据路径
//     pszDstFile—矢量数据保存路径
//     pszFormat—矢量数据格式,默认为shp
//     Background—所需掩膜的背景值,默认为0
//返回:
//     0—转换失败
//     1—转换成功

int CImageProcess::Raster2Vector(const char * pszSrcFile, const char* pszDstFile, const char* pszFormat = "ESRI Shapefile", int Background = 0)
{
	GDALAllRegister();//注册驱动
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");//解决中文乱码问题
	GDALDataset* poSrcDS = (GDALDataset*)GDALOpen(pszSrcFile, GA_ReadOnly);
	if (poSrcDS == NULL)
	{
		return 0;
	}
	// 根据Shapefile驱动创建输出矢量文件  
	GDALDriver *poDriver;
	poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);
	if (poDriver == NULL)
	{
		printf("%s driver not available.\n", pszFormat);
		exit(1);
	}
	//根据文件名创建输出矢量数据集 
	GDALDataset* poDstDS = poDriver->Create(pszDstFile, 0, 0, 0, GDT_Unknown, NULL);
	if (poDstDS == NULL)
	{
		printf("Creation of output file failed.\n");
		exit(1);
	}
	// 定义空间参考,与输入图像相同 
	OGRSpatialReference *poSpatialRef = new OGRSpatialReference(poSrcDS->GetProjectionRef());
	if (poSpatialRef == NULL)
	{
		return 0;
	}
	OGRLayer* poLayer = poDstDS->CreateLayer("DstLayer", poSpatialRef, wkbPolygon, NULL);//创建图层
	if (poDstDS == NULL)
	{
		GDALClose(poSrcDS);
		GDALClose(poDstDS);
		delete poSpatialRef;
		return 0;
	}
	OGRFieldDefn oField("GRIDCODE", OFTInteger);//创建属性表,只有一个字段即“gridcode”,里面保存对应栅格的像元值
	if (poLayer->CreateField(&oField) != OGRERR_NONE)
	{
		printf("Creating Name field failed.\n");
		exit(1);
	}
	GDALRasterBandH hSrcBand = (GDALRasterBandH)poSrcDS->GetRasterBand(1); //获取图像的第一个波段
	GDALDataset* MaskData = CreateMask(poSrcDS, Background);
	GDALRasterBandH MaskBand = (GDALRasterBandH)MaskData->GetRasterBand(1);
	GDALPolygonize(hSrcBand, MaskBand, (OGRLayerH)poLayer, 0, NULL, NULL, NULL); //调用栅格矢量化 
	GDALClose(poSrcDS); //关闭文件  
	GDALClose(poDstDS);
	GDALClose(MaskData);
	return 1;
}


GDALDataset* CLHBApplication::CreateMask(GDALDataset* poSrcDS, int Background)
{
	GDALAllRegister();
	//为了支持中文路径
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");
	//获取影像大小
	int src_width = poSrcDS->GetRasterXSize();
	int src_height = poSrcDS->GetRasterYSize();
	//获取影像波段数
	int InBands = poSrcDS->GetRasterCount();
	//获取影像格式
	GDALDataType eDataType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
	//定义存储影像的空间参考数组
	double adfInGeoTransform[6] = { 0 };
	const char *pszWKT = NULL;
	//获取影像空间参考
	poSrcDS->GetGeoTransform(adfInGeoTransform);
	pszWKT = poSrcDS->GetProjectionRef();
	//创建文件
	GDALDriver *poDriver = (GDALDriver *)GDALGetDriverByName("MEM");
	GDALDataset *poOutputDS = poDriver->Create("", src_width, src_height, InBands, eDataType, NULL);
	//设置拉伸后图像的空间参考以及地理坐标
	poOutputDS->SetGeoTransform(adfInGeoTransform);
	poOutputDS->SetProjection(pszWKT);
	switch (eDataType)
	{
	case GDT_Byte:
	{
		// 申请所有数据所需要的缓存,如果图像太大应该用分块处理
		char *srcData = (char *)malloc(sizeof(char) *src_width * src_height * 1);
		memset(srcData, 0, sizeof(char) * 1 * src_width * src_height);
		//char *srcData = new char[src_width * src_height];
		//读取多光谱影像到缓存
		poSrcDS->GetRasterBand(1)->RasterIO(GF_Read, 0, 0, src_width, src_height, srcData + 0 * src_width * src_height, src_width, src_height, eDataType, 0, 0);
		for (int src_row = 0; src_row < src_height; src_row++)
		{
			char *dstData = (char*)malloc(sizeof(char)*src_width);
			memset(dstData, 0, sizeof(char)*src_width);
			for (int src_col = 0; src_col < src_width; src_col++)
			{
				char src_temVal = *(srcData + src_row * src_width + src_col);
				if (src_temVal == Background)
				{
					*(dstData + src_col) = 0;
				}
				else
				{
					*(dstData + src_col) = 1;
				}
			}
			poOutputDS->GetRasterBand(1)->RasterIO(GF_Write, 0, src_row, src_width, 1, dstData, src_width, 1, eDataType, 0, 0);
			free(dstData);
		}
		free(srcData);
		break;
	}
	case GDT_UInt16:
	{
		// 申请所有数据所需要的缓存,如果图像太大应该用分块处理
		unsigned short *srcData = (unsigned short *)malloc(sizeof(unsigned short) *src_width * src_height * 1);
		memset(srcData, 0, sizeof(unsigned short) * 1 * src_width * src_height);
		//unsigned short *srcData = new unsigned short[src_width * src_height];
		//读取多光谱影像到缓存
		poSrcDS->GetRasterBand(1)->RasterIO(GF_Read, 0, 0, src_width, src_height, srcData + 0 * src_width * src_height, src_width, src_height, eDataType, 0, 0);
		for (int src_row = 0; src_row < src_height; src_row++)
		{
			unsigned short *dstData = (unsigned short*)malloc(sizeof(unsigned short)*src_width);
			memset(dstData, 0, sizeof(unsigned short)*src_width);
			for (int src_col = 0; src_col < src_width; src_col++)
			{
				char src_temVal = *(srcData + src_row * src_width + src_col);
				if (src_temVal == Background)
				{
					*(dstData + src_col) = 0;
				}
				else
				{
					*(dstData + src_col) = 1;
				}
			}
			poOutputDS->GetRasterBand(1)->RasterIO(GF_Write, 0, src_row, src_width, 1, dstData, src_width, 1, eDataType, 0, 0);
			free(dstData);
		}
		free(srcData);
		break;
	}
	case GDT_Int16:
	{
		// 申请所有数据所需要的缓存,如果图像太大应该用分块处理
		short int *srcData = (short int *)malloc(sizeof(short int) *src_width * src_height * 1);
		memset(srcData, 0, sizeof(short int) * 1 * src_width * src_height);
		//short int *srcData = new short int[src_width * src_height];
		//读取多光谱影像到缓存
		poSrcDS->GetRasterBand(1)->RasterIO(GF_Read, 0, 0, src_width, src_height, srcData + 0 * src_width * src_height, src_width, src_height, eDataType, 0, 0);
		for (int src_row = 0; src_row < src_height; src_row++)
		{
			short int *dstData = (short int*)malloc(sizeof(short int)*src_width);
			memset(dstData, 0, sizeof(short int)*src_width);
			for (int src_col = 0; src_col < src_width; src_col++)
			{
				char src_temVal = *(srcData + src_row * src_width + src_col);
				if (src_temVal == Background)
				{
					*(dstData + src_col) = 0;
				}
				else
				{
					*(dstData + src_col) = 1;
				}
			}
			poOutputDS->GetRasterBand(1)->RasterIO(GF_Write, 0, src_row, src_width, 1, dstData, src_width, 1, eDataType, 0, 0);
			free(dstData);
		}
		free(srcData);
		break;
	}
	case GDT_Float32:
	{
		// 申请所有数据所需要的缓存,如果图像太大应该用分块处理
		float *srcData = (float *)malloc(sizeof(float) *src_width * src_height * 1);
		memset(srcData, 0, sizeof(float) * 1 * src_width * src_height);
		//float *srcData = new float[src_width * src_height];
		//读取多光谱影像到缓存
		poSrcDS->GetRasterBand(1)->RasterIO(GF_Read, 0, 0, src_width, src_height, srcData + 0 * src_width * src_height, src_width, src_height, eDataType, 0, 0);
		for (int src_row = 0; src_row < src_height; src_row++)
		{
			float *dstData = (float*)malloc(sizeof(float)*src_width);
			memset(dstData, 0, sizeof(float)*src_width);
			for (int src_col = 0; src_col < src_width; src_col++)
			{
				char src_temVal = *(srcData + src_row * src_width + src_col);
				if (src_temVal == Background)
				{
					*(dstData + src_col) = 0;
				}
				else
				{
					*(dstData + src_col) = 1;
				}
			}
			poOutputDS->GetRasterBand(1)->RasterIO(GF_Write, 0, src_row, src_width, 1, dstData, src_width, 1, eDataType, 0, 0);
			free(dstData);
		}
		free(srcData);
		break;
	}
	case GDT_Float64:
	{
		// 申请所有数据所需要的缓存,如果图像太大应该用分块处理
		double *srcData = (double *)malloc(sizeof(double) *src_width * src_height * 1);
		memset(srcData, 0, sizeof(double) * 1 * src_width * src_height);
		//float *srcData = new float[src_width * src_height];
		//读取多光谱影像到缓存
		poSrcDS->GetRasterBand(1)->RasterIO(GF_Read, 0, 0, src_width, src_height, srcData + 0 * src_width * src_height, src_width, src_height, eDataType, 0, 0);
		for (int src_row = 0; src_row < src_height; src_row++)
		{
			double *dstData = (double*)malloc(sizeof(double)*src_width);
			memset(dstData, 0, sizeof(double)*src_width);
			for (int src_col = 0; src_col < src_width; src_col++)
			{
				char src_temVal = *(srcData + src_row * src_width + src_col);
				if (src_temVal == Background)
				{
					*(dstData + src_col) = 0;
				}
				else
				{
					*(dstData + src_col) = 1;
				}
			}
			poOutputDS->GetRasterBand(1)->RasterIO(GF_Write, 0, src_row, src_width, 1, dstData, src_width, 1, eDataType, 0, 0);
			free(dstData);
		}
		free(srcData);
		break;
	}
	default:
		::MessageBox(NULL, _T("暂不支持该影像的数据类型!"), _T("提示"), MB_OK);
		return 0;
	}

	poDriver = NULL;
	return poOutputDS;
}

你可能感兴趣的:(写过的小程序,遇到过的问题)