GDAL 栅格数据矢量化(附有完整代码)

        在使用 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;
}

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值