由于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;
}