【问题标题】:Clip Raster with Polygon with GDAL C++使用 GDAL C++ 用多边形裁剪栅格
【发布时间】:2022-01-11 08:59:53
【问题描述】:

我正在尝试使用 GDAL 多边形来剪辑栅格。目前我收到一个错误,即在初始化 WarpOperation 时存在读取访问冲突。我可以访问我的 Shapefile 并检查功能的数量,所以我认为访问很好。我也可以访问我的栅格数据(GetProjectionRef)。所有文件都在同一个 CRS 中。有没有办法将 GdalWarp 与 Cutline 一起使用?

      const char* inputPath = "input.tif";
      const char* outputPath = "output.tif";
     
      //clipper Polygon
      auto w_read_filenamePoly = "Polygon.shp";
      char* read_filenamePoly = new char[w_read_filenamePoly.length() + 1];
      wcstombs(read_filenamePoly, w_read_filenamePoly.c_str(), w_read_filenamePoly.length() + 1);

      GDALDataset* hSrcDS; 
      GDALDataset* hDstDS;

      GDALAllRegister();
      hSrcDS =(GDALDataset *) GDALOpen(inputPath, GA_Update);
      hDstDS = (GDALDataset*)GDALOpen(outputPath, GA_Update);
     
      const char* proj = hSrcDS->GetProjectionRef();
      const char* proj2 = hDstDS->GetProjectionRef();
      //clipper Layer
      GDALDataset* poDSClipper;
      poDSClipper = (GDALDataset*)GDALOpenEx(read_filenamePoly, GDAL_OF_UPDATE, NULL, NULL, NULL);
      Assert::IsNotNull(poDSClipper);
      delete[]read_filenamePoly;
      OGRLayer* poLayerClipper;
      poLayerClipper = poDSClipper->GetLayerByName("Polygon");
      int numClip = poLayerClipper->GetFeatureCount();

      //setup warp options
      GDALWarpOptions* psWarpOptions = GDALCreateWarpOptions();
      psWarpOptions->hSrcDS = hSrcDS;
      psWarpOptions->hDstDS = hDstDS;
      psWarpOptions->nBandCount = 1;
      psWarpOptions->panSrcBands = (int *) CPLMalloc(sizeof(int) * psWarpOptions->nBandCount);
      psWarpOptions->panSrcBands[0] = 1;
      psWarpOptions->panDstBands = (int*)CPLMalloc(sizeof(int) * psWarpOptions->nBandCount);
      psWarpOptions->panDstBands[0] = 1;
      psWarpOptions->pfnProgress = GDALTermProgress;
      psWarpOptions->hCutline = poLayerClipper;
      
      
      // Establish reprojection transformer.
      psWarpOptions->pTransformerArg = GDALCreateGenImgProjTransformer(hSrcDS,proj, hDstDS, proj2, FALSE, 0.0, 1);
      psWarpOptions->pfnTransformer = GDALGenImgProjTransform;
     
      GDALWarpOperation oOperation;
      oOperation.Initialize(psWarpOptions);
      oOperation.ChunkAndWarpImage(0, 0, GDALGetRasterXSize(hDstDS), GDALGetRasterYSize(hDstDS));
      GDALDestroyGenImgProjTransformer(psWarpOptions->pTransformerArg);
      GDALDestroyWarpOptions(psWarpOptions);
      GDALClose(hDstDS);
      GDALClose(hSrcDS);

【问题讨论】:

    标签: c++ raster gdal shapefile warp


    【解决方案1】:

    您的psWarpOptions->hCutline 应该是一个多边形,而不是一个图层。

    切割线也应该在源像素/线坐标中。

    gdalwarp_lib.cpp检查TransformCutlineToSource,您可能可以简单地从那里获取代码。

    当从 C++ 调用这个特殊的 GDAL 操作时,它充满了陷阱 - 这里有很多关于它的未解决问题 - 我正在复制一个完整的工作示例:

    使用多边形蒙版(切割线)扭曲(重新投影)光栅图像:

    #include <gdal/gdal.h>
    #include <gdal/gdal_priv.h>
    #include <gdal/gdalwarper.h>
    #include <gdal/ogrsf_frmts.h>
    
    int main() {
      const char *inputPath = "input.tif";
      const char *outputPath = "output.tif";
    
      // clipper Polygon
      // THIS FILE MUST BE IN PIXEL/LINE COORDINATES or otherwise one should
      // copy the function gdalwarp_lib.cpp:TransformCutlineToSource()
      // from GDAL's sources
      // It is expected that it contains a single polygon feature
      const char *read_filenamePoly = "cutline.json";
    
      GDALDataset *hSrcDS;
      GDALDataset *hDstDS;
    
      GDALAllRegister();
      auto poDriver = GetGDALDriverManager()->GetDriverByName("GTiff");
      hSrcDS = (GDALDataset *)GDALOpen(inputPath, GA_ReadOnly);
    
      hDstDS = (GDALDataset *)poDriver->CreateCopy(
        outputPath, hSrcDS, 0, nullptr, nullptr, nullptr);
      // Without this step the cutline is useless - because the background
      // will be carried over from the original image
      CPLErr e = hDstDS->GetRasterBand(1)->Fill(0);
    
      const char *src_srs = hSrcDS->GetProjectionRef();
      const char *dst_srs = hDstDS->GetProjectionRef();
    
      // clipper Layer
      GDALDataset *poDSClipper;
      poDSClipper = (GDALDataset *)GDALOpenEx(
        read_filenamePoly, GDAL_OF_UPDATE, NULL, NULL, NULL);
      auto poLayerClipper = poDSClipper->GetLayer(0);
      auto geom = poLayerClipper->GetNextFeature()->GetGeometryRef();
    
      // setup warp options
      GDALWarpOptions *psWarpOptions = GDALCreateWarpOptions();
      psWarpOptions->hSrcDS = hSrcDS;
      psWarpOptions->hDstDS = hDstDS;
      psWarpOptions->nBandCount = 1;
      psWarpOptions->panSrcBands =
        (int *)CPLMalloc(sizeof(int) * psWarpOptions->nBandCount);
      psWarpOptions->panSrcBands[0] = 1;
      psWarpOptions->panDstBands =
        (int *)CPLMalloc(sizeof(int) * psWarpOptions->nBandCount);
      psWarpOptions->panDstBands[0] = 1;
      psWarpOptions->pfnProgress = GDALTermProgress;
      psWarpOptions->hCutline = geom;
    
      // Establish reprojection transformer.
      psWarpOptions->pTransformerArg = GDALCreateGenImgProjTransformer(
        hSrcDS, src_srs, hDstDS, dst_srs, TRUE, 1000, 1);
      psWarpOptions->pfnTransformer = GDALGenImgProjTransform;
    
      GDALWarpOperation oOperation;
      oOperation.Initialize(psWarpOptions);
      oOperation.ChunkAndWarpImage(
        0, 0, GDALGetRasterXSize(hDstDS), GDALGetRasterYSize(hDstDS));
      GDALDestroyGenImgProjTransformer(psWarpOptions->pTransformerArg);
      GDALDestroyWarpOptions(psWarpOptions);
      GDALClose(hDstDS);
      GDALClose(hSrcDS);
    }
    

    【讨论】:

    • 感谢您的建议!我目前正在使用 gdal 3.1.4。我会升级它。
    • 我喜欢你的问题,我更新了我的答案 - GDAL 3.4.1 有一个额外的检查忽略了无效的切割线
    • 我看到代码现在运行没有错误谢谢。我添加了以下几行:std::vector&lt;OGRFeature*&gt; vecClipFeature; OGRFeature* feat; while ((feat = poLayerClipper-&gt;GetNextFeature()) != NULL) { vecClipFeature.push_back(feat); } OGRGeometry* geom = vecClipFeature.at(0)-&gt;GetGeometryRef(); OGRPolygon* clipPoly = geom-&gt;toPolygon(); 我的 hCutline 现在是我的 clipyPoly。但是我的 outImage 只包含 0。你知道吗?
    • 如果在命令行中使用gdalwarp 和相同的剪切线会发生什么?
    • 不能在 cmd 中使用它,但是在使用 QGIS 命令提示符时我可以访问它。输入以下代码:gdalwarp -s_srs EPSG:31258 -t_srs EPSG:31258 -of GTiff -cutline Polygon.shp -cl Polygon -crop_to_cutline input.tif C:/Users/AppData/Local/Temp/processing_OKJpJp/2c8da2e6c2af4bb6aedf0076936010a3/OUTPUT.tif 使用上面的行和 Qgis 的结果是正确的
    猜你喜欢
    • 1970-01-01
    • 2018-06-01
    • 2018-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-28
    • 2019-01-06
    相关资源
    最近更新 更多