Реализация алгоритма GDAL в C ++ GDALFillNodata () - PullRequest
0 голосов
/ 30 мая 2018

Нужна помощь с кодом C ++ для реализации / вызова алгоритма GDALFillNoData ().У меня уже есть рабочая версия, использующая Python и GDAL, что несколько медленное заполнение высот DEMs (1,5 ГБ).Мне любопытно, если это возможно.Я написал код для приложения командной строки и разместил его здесь.На данный момент пути к файлам жестко заданы.Он строит (CodeBlocks 16.1 / MinGW) и запускается, но затем падает.

Я не программист C ++, хотя мне бы хотелось, но я пытаюсь лучше понять язык.Я в меру порядочный на питоне.Я, вероятно, упускаю что-то базовое здесь, что нормально для C ++.

Там, скорее всего, код, который был закомментирован в ходе тестирования.Поэтому, если что-то не имеет смысла, вот почему.

Вот код:

#include <iostream>
#include "gdal.h"
#include "gdal_priv.h"
#include "cpl_conv.h"
#include "gdal_alg.h"

int main()
{
    GDALAllRegister();
    //CPLPushErrorHandler(CPLQuietErrorHandler);

    // Read/Write Files
    const char *input = "D:/myIn.tif";

    GDALDataset *pSrcDataset;
    //GDALRasterBandH hMaskBand;
    GDALRasterBand  *poBand;
    //CPLErr maskBand;
    int maskFlags;
    int noData;
    double maxSearch = 10.0;
    int maxInt = 1;
    int nBlockXSize, nBlockYSize;
    double adfGeoTransform[6];
    //CPLErr eErr;

    pSrcDataset = (GDALDataset*) GDALOpen(input, GA_Update);
    CPLAssert( pSrcDataset != NULL );

    poBand = pSrcDataset->GetRasterBand( 1 );
    poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
    printf( "Block=%dx%d Type=%s, ColorInterp=%s\n",
           nBlockXSize, nBlockYSize,
           GDALGetDataTypeName(poBand->GetRasterDataType()),
           GDALGetColorInterpretationName(
           poBand->GetColorInterpretation()) );

    noData = pSrcDataset->GetRasterBand(1)->GetNoDataValue();
    printf( "No Data Value = %i\n",noData );

    printf( "Driver: %s/%s\n",
           pSrcDataset->GetDriver()->GetDescription(),
           pSrcDataset->GetDriver()->GetMetadataItem( GDAL_DMD_LONGNAME ) );

    printf( "Size is %dx%dx%d\n",
           pSrcDataset->GetRasterXSize(), pSrcDataset->GetRasterYSize(),
           pSrcDataset->GetRasterCount() );

    if( pSrcDataset->GetProjectionRef()  != NULL )
        printf( "Projection is `%s'\n", pSrcDataset->GetProjectionRef() );

    if( pSrcDataset->GetGeoTransform( adfGeoTransform ) == CE_None )
        printf( "Origin = (%.6f,%.6f)\n", adfGeoTransform[0], 
               adfGeoTransform[3] );
        printf( "Pixel Size = (%.6f,%.6f)\n",adfGeoTransform[1], 
               adfGeoTransform[5] );

    //maskBand = pSrcDataset->GetRasterBand(1)->GetMaskBand();

    //hMaskBand = GDALGetMaskBand( maskBand );
    //hMaskBand = pSrcDataset->GetRasterBand(1)->GetNoDataValue();
    maskFlags = pSrcDataset->GetRasterBand(1)->GetMaskFlags();
    printf ( "Mask Flags = %i\n", maskFlags );

    printf ( "Processing image\n" );

    // Ignore that this is on two lines here
    GDALFillNodata(pSrcDataset, pSrcDataset->GetRasterBand(1)- 
    >GetMaskBand(), maxSearch, 0, maxInt, NULL, NULL, NULL); 
    //CPLAssert( eErr == CE_None);

    GDALClose(pSrcDataset);

    return 0;
}

Некоторые ошибки, которые я получаю при запуске этого кода (см. Ссылки на изображения).Процесс возвращает 255, что, на мой взгляд, является чем-то уникальным для CodeBlocks?

Сбой программы

Процесс возвращает 255

Вот реализация Python.Довольно прямо вперед.None - это то же самое, что NULL?Потому что одна из ошибок, которые я получил при использовании NULL в качестве hMaskBand ( rasterfill.cpp )

#Run the gdal fill
    ET = gdal.Open(infile, GA_Update)
    ETband = ET.GetRasterBand(1)

    result = gdal.FillNodata(targetBand = ETband, maskBand = None, 
    maxSearchDist = 500, smoothingIterations = 1)

    print result # return 0

    ET = None

Пожалуйста, дайте мне знать, если вам нужна дополнительная информация.Знание того, что я мало знаю о C ++, возможно, является моей средой сборки.:)

Спасибо, Хит

1 Ответ

0 голосов
/ 30 мая 2018

В дополнение к комментариям выше, проблема заключается в том, что первый аргумент, предоставленный GDALFillNoData API , представляет собой GDALDataset * вместо GDALRasterBand *.

Но я слишком много боролся с GDAL, чтобы не дать много объяснительного ответа.

Реализация библиотеки GDAL очень ориентирована на C, хотя она действительно написана с использованием функций C ++ (например, классов).Итак, вы обнаружите, что во многих доступных API аргументы не относятся к типам, определенным в библиотеке.Вместо этого они используют typedef, такой как GDALRasterBandH , который действительно является псевдонимом типа void *.

Это имеет неприятный эффект: любой тип аргумента, который вы передаете компилятору, выигрываетне жалуйтесь, следовательно, вы получите много ошибок во время выполнения, если вы сделаете такие (очень распространенные) ошибки.

Почему они это делают?Я думаю, что это был способ использовать PIMPL , чтобы компилятор не работал с несколькими единицами перевода , каждый раз, когда один из этих классов был изменен.

реальная проблема этого подхода заключается в том, что вы теряете все преимущества статической проверки типов , то есть компилятор сообщает вам, когда происходит несоответствие типов.В качестве примечания: это не критика библиотеки GDAL (слава Богу, она у нас есть! И это огромный и очень полезный проект), просто так оно и есть.

Кстати,В настоящее время я работаю над проектом C ++ с открытым исходным кодом, Rasterix , который предназначен для удобного графического интерфейса для инструментов GDAL для наборов растровых данных.Не воспринимайте это как подсказку , как я , так как это приложение все еще нуждается в надлежащем тестировании, но есть много вариантов использования API GDAL, которые могут помочь, если вам нужны примеры того, как их использовать.

...