在使用 GDAL 栅格转矢量时,一般默认输入的栅格数据带有地理信息,如果输入的图片不带有地理信息,则会出现矢量化结果与原图上下反转;
注意:
1、如果代码中涉及到获取投影坐标,则需要设置环境变量,如下所示;
//获取地理坐标时应当注意的问题
CPLSetConfigOption("GDAL_DATA", "E:/gdal232/data"); //设置环境变量,防止在设置、获取投影坐标时出错
2、如果输入的栅格数据带有地理信息,则无需自定义坐标系;
3、如果输入的栅格数据不带地理信息,则需要自定义坐标系,否则会出现量化结果与原图上下反转;
4、自定义坐标系代码:
//自定义坐标系
//如果输入的栅格数据没有地理信息的话,需要自定义坐标系,否则矢量化结果与原数据程垂直镜像对称
OGRSpatialReference spatialReference;
spatialReference.importFromEPSG(4326); //wgs84地理坐标系
char* pszWKT = nullptr;
spatialReference.exportToWkt(&pszWKT);
poSrcDS->SetProjection(pszWKT);
CPLFree(pszWKT);
pszWKT = nullptr;
//坐标信息
double padfTransform[6] = {
114.0, //左上角点坐标X
0.000001, //X方向的分辨率
0, //旋转系数,如果为0,就是标准的正北向图像
34.0, //左上角点坐标Y
0, //旋转系数,如果为0,就是标准的正北向图像
-0.000001, //Y方向的分辨率
};
5、栅格转矢量完整代码:
#include <iostream>
#include "gdal_priv.h"
#include "ogrsf_frmts.h" //for ogr
#include "gdal_alg.h" //for GDALPolygonize
using namespace std;
//栅格转矢量
int Raster2Vector(const char* pszSrcFile, const char* pszDstFile, const char* pszFormat);
int main()
{
const char* pszSrcFile = ".\\image_save\\roadThin.png"; //输入栅格数据路径
const char* pszDstFile = ".\\image_save\\Vector.shp"; //输出矢量数据路径
//栅格数据矢量化
Raster2Vector(pszSrcFile, pszDstFile, "ESRI Shapefile");
return 0;
}
//栅格转矢量
int Raster2Vector(const char* pszSrcFile, const char* pszDstFile, const char* pszFormat)
{
GDALAllRegister(); //使用 GDAL 时第一步,注册驱动
//获取地理坐标时应当注意的问题
CPLSetConfigOption("GDAL_DATA", "E:/gdal232/data"); //设置环境变量,防止在设置、获取投影坐标时出错
CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO"); //解决中文乱码问题
//读取栅格数据
GDALDataset* poSrcDS = (GDALDataset*)GDALOpen(pszSrcFile, GA_ReadOnly);
if (poSrcDS == NULL)
{
cout << "输入图像数据为空!" << endl;
return 0;
}
//自定义坐标系
//如果输入的栅格数据没有地理信息的话,需要自定义坐标系,否则矢量化结果与原数据程垂直镜像对称
OGRSpatialReference spatialReference;
spatialReference.importFromEPSG(4326); //wgs84地理坐标系
char* pszWKT = nullptr;
spatialReference.exportToWkt(&pszWKT);
poSrcDS->SetProjection(pszWKT);
CPLFree(pszWKT);
pszWKT = nullptr;
//坐标信息
double padfTransform[6] = {
114.0, //左上角点坐标X
0.000001, //X方向的分辨率
0, //旋转系数,如果为0,就是标准的正北向图像
34.0, //左上角点坐标Y
0, //旋转系数,如果为0,就是标准的正北向图像
-0.000001, //Y方向的分辨率
};
poSrcDS->SetGeoTransform(padfTransform);
//根据 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)
{
cout << "创建矢量文件失败!" << endl;
exit(1);
}
//定义空间参考,与输入图像相同
OGRSpatialReference* poSpatialRef = new OGRSpatialReference(poSrcDS->GetProjectionRef());
if (poSpatialRef == NULL)
{
return 0;
}
//创建图层
OGRLayer* poLayer = poDstDS->CreateLayer("DstLayer", NULL, wkbPolygon, NULL);
if (poDstDS == NULL)
{
GDALClose(poSrcDS);
GDALClose(poDstDS);
// delete poSpatialRef;
return 0;
}
//创建属性表,只有一个字段即“value”,里面保存对应栅格的像元值
OGRFieldDefn oField("value", OFTInteger);
if (poLayer->CreateField(&oField) != OGRERR_NONE)
{
printf("Creating Name field failed.\n");
exit(1);
}
//获取图像的第一个波段
GDALRasterBandH hSrcBand = (GDALRasterBandH)poSrcDS->GetRasterBand(1);
//调用栅格矢量化
GDALPolygonize(hSrcBand, NULL, (OGRLayerH)poLayer, 0, NULL, NULL, NULL);
GDALClose(poSrcDS); //关闭文件
GDALClose(poDstDS);
return 1;
}