<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    Hi!<br>
    <br>
    Some time ago, I asked for an inversion of gdal.Warp based on
    GEOLOCATION arrays (longitude/latitude). Back then, my question was:
    How can I transform an image with projected coordinates back to
    cartesian/image coordinates, given that a geolocation array tells
    GDAL where to put which pixel in the output?<br>
    <br>
    In 11/2021, this was unfortunately not implemented yet. However, is
    seems like in the meantime someting like this has been added:<br>
        - <a class="moz-txt-link-freetext" href="https://github.com/OSGeo/gdal/pull/5520">https://github.com/OSGeo/gdal/pull/5520</a><br>
        - <a class="moz-txt-link-freetext" href="https://github.com/OSGeo/gdal/pull/6069">https://github.com/OSGeo/gdal/pull/6069</a><br>
        -
<a class="moz-txt-link-freetext" href="https://github.com/OSGeo/gdal/blob/c92b22d02c99eae0152f49595947fb3747ddc280/autotest/gcore/geoloc.py#L396">https://github.com/OSGeo/gdal/blob/c92b22d02c99eae0152f49595947fb3747ddc280/autotest/gcore/geoloc.py#L396</a><br>
    <br>
    But I am not quite sure if that is what I want. If so, how would a
    Python implementation based on gdal.Warp look like? Is that
    documented somewhere?<br>
    <br>
    Best,<br>
    Daniel<br>
    <br>
    <br>
    <br>
    <div class="moz-cite-prefix">Am 30.11.2021 um 14:20 schrieb Daniel
      Scheffler:<br>
    </div>
    <blockquote type="cite"
      cite="mid:b1cf6b86-4922-ca9a-bdd4-ec4fff2883d7@gfz-potsdam.de">
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      Ok thanks, too bad that this is not implemented. I think the
      inversion of this transformation would be a nice feature to be
      added in GDAL. It would be very useful to me (especially if it is
      accessible via the Python bindings) and would ease the
      implementation in a processing pipeline for the upcoming EnMAP
      hyperspectral satellite. Should I open a feature request in the
      GDAL issue tracker on GitHub?<br>
      <br>
      <br>
      <div class="moz-cite-prefix">Am 30.11.2021 um 14:02 schrieb Even
        Rouault:<br>
      </div>
      <blockquote type="cite"
        cite="mid:1791a553-3e0e-f5e6-659d-11ac6f708ab3@spatialys.com">
        <meta http-equiv="Content-Type" content="text/html;
          charset=UTF-8">
        <p><br>
        </p>
        <div class="moz-cite-prefix">Le 30/11/2021 à 12:52, Daniel
          Scheffler a écrit :<br>
        </div>
        <blockquote type="cite"
          cite="mid:c2cf3a49-200b-91a6-dd81-1b3059859558@gfz-potsdam.de">
          <meta http-equiv="content-type" content="text/html;
            charset=UTF-8">
          Thanks a lot for taking the time, Even, I got the
          transformation from cartesian to projected coordinates to work
          in memory with the GTiff driver. With MEM, NUMPY or VRT it
          does not work because these formats are either not readable
          from /vsimem/ or don´t have a regular file path which is
          needed to set the <font size="2">X_DATASET and </font><font
            size="2">Y_DATASET keys in the GEOLOCATION metadata</font>.<br>
        </blockquote>
        Ah indeed for X_DATASET/Y_DATASET, you can't use a MEM or NUMPY
        dataset. But a /vsimem/xxx dataset in another format should
        work.<br>
        <blockquote type="cite"
          cite="mid:c2cf3a49-200b-91a6-dd81-1b3059859558@gfz-potsdam.de">
          <div class="moz-forward-container"> <br>
            <font size="2">Regarding the inversion of this
              transformation, i.e., </font><font size="2">from
              projected coordinates to pixel/line:</font><br>
            <blockquote type="cite">The logic of <span class="pl-en">GDALCreateGenImgProjTransformer2()
                around <a class="moz-txt-link-freetext"
href="https://github.com/OSGeo/gdal/blob/master/alg/gdaltransformer.cpp#L1825"
                  moz-do-not-send="true">https://github.com/OSGeo/gdal/blob/master/alg/gdaltransformer.cpp#L1825</a>
                which is for the source dataset should be ported a few
                lines after for the target dataset.  Probably with a new
                transformer option to be able to point to an auxiliary
                dataset, such as a VRT one of your example, to extract
                the geolocation metadata items from it, that would be
                different from the target dataset itself, because,
                except perhaps for the netCDF case, most GDAL datasets
                that expose a GEOLOCATION metadata domain must be
                read-only.</span></blockquote>
            <br>
            I don´t completely get what you mean here. To me, this
            sounds like there might be a way to do the inverted
            transformation using the C-API of GDAL. </div>
        </blockquote>
        No, I meant there's some missing code to do that.<br>
        <blockquote type="cite"
          cite="mid:c2cf3a49-200b-91a6-dd81-1b3059859558@gfz-potsdam.de">
          <div class="moz-forward-container">However, I am a Python
            developer and my C skills are a bit poor. Is there any way
            to use the Python bindings here?<br>
            <br>
            Kind regards,<br>
            Daniel<br>
            <br>
            <br>
                      <br>
            <br>
            <div class="moz-cite-prefix">Am 26.11.2021 um 12:38 schrieb
              Even Rouault:<br>
            </div>
            <blockquote type="cite"
              cite="mid:2c9d72a2-3950-f846-b3e4-ee80500179a1@spatialys.com">
              <meta http-equiv="Content-Type" content="text/html;
                charset=UTF-8">
              Daniel,<br>
              <blockquote type="cite"
                cite="mid:8e78eb30-6a89-104b-d2c4-f9ea8231aced@gfz-potsdam.de">
                <br>
                I am trying to convert image data from cartesian/image
                coordinates to projected coordinates AND vice versa
                using geolocation arrays in GDAL. I have two questions:<br>
                <ol>
                  <li>Since this transformation is part of a processing
                    chain implemented in Python, I try to transform the
                    data directly in-memory, i.e, without any disk
                    access. This saves IO time and avoids permission
                    errors when trying to write temporary data on
                    Windows. How can this be done? I got correct results
                    with the code below, however, only when I
                    temporarily write the data to disk. I tried to write
                    the data to /vsimem/ using the MEM, GTiff and NUMPY
                    drivers. However, gdal.Warp can´t find the data
                    there (FileNotFoundError). I think, also the
                    gdal.Transformer class might be useful and I found
                    an interesting thread on that <a
href="https://lists.osgeo.org/pipermail/gdal-dev/2012-January/031502.html"
                      moz-do-not-send="true">here</a> and a related test
                    in the GDAL autotest suite (<a
href="https://github.com/OSGeo/gdal/blob/master/autotest/alg/transformgeoloc.py"
                      moz-do-not-send="true">here</a>). However, I can´t
                    get it to work for my specific case.</li>
                </ol>
              </blockquote>
              <p>There's no reason it won't work with a in-memory
                dataset.</p>
              <p>If you use a MEM dataset, then you need to provide the
                dataset object itself as the input dataset of
                gdal.Warp() (the name of a MEM dataset is completely
                ignored. a MEM dataset can't be opened, just created).</p>
              <p>Similarly with a NUMPY dataset.   With GTiff and
                /vsimem/, they behave as a regular file. If you pass it
                by name as input of gdal.Warp(), you need to make sure
                to close (ds = None typically) the dataset before, so it
                is properly flushed and can be opened. But you can also
                pass it as an object without that constraint.</p>
              <p>You can also create purely in-memory VRT files by
                assigning them an empty name. Then of course you need to
                provide them as objects to gdal.Warp()<br>
              </p>
              <p><br>
              </p>
              <blockquote type="cite"
                cite="mid:8e78eb30-6a89-104b-d2c4-f9ea8231aced@gfz-potsdam.de">
                <ol>
                  <li>My second question is how I can invert the
                    transformation, i.e., how can I transform an image
                    with projected coordinates back to cartesian/image
                    coordinates, given that a geolocation array tells
                    GDAL where to put which pixel in the output?
                    Background is a processing pipeline for satellite
                    data where some processing steps are running in
                    sensor geometry (image data as acquired by the
                    sensor, without any geocoding and projection) and I
                    need to provide corresponding AUX data which
                    originally come with projected coordinates.<br>
                  </li>
                </ol>
              </blockquote>
              The logic of <span class="pl-en">GDALCreateGenImgProjTransformer2()
                around <a class="moz-txt-link-freetext"
href="https://github.com/OSGeo/gdal/blob/master/alg/gdaltransformer.cpp#L1825"
                  moz-do-not-send="true">https://github.com/OSGeo/gdal/blob/master/alg/gdaltransformer.cpp#L1825</a>
                which is for the source dataset should be ported a few
                lines after for the target dataset.  Probably with a new
                transformer option to be able to point to an auxiliary
                dataset, such as a VRT one of your example, to extract
                the geolocation metadata items from it, that would be
                different from the target dataset itself, because,
                except perhaps for the netCDF case, most GDAL datasets
                that expose a GEOLOCATION metadata domain must be
                read-only.<br>
              </span>
              <blockquote type="cite"
                cite="mid:8e78eb30-6a89-104b-d2c4-f9ea8231aced@gfz-potsdam.de">
                <ol>
                  <li> <br>
                  </li>
                </ol>
                <p>Here is the code I already have to convert a sample
                  image from cartesian to projected coordinates:</p>
                <blockquote>
                  <p><font size="2">import os<br>
                      from tempfile import TemporaryDirectory<br>
                      from osgeo import gdal, osr<br>
                      import numpy as np<br>
                      from matplotlib import pyplot as plt<br>
                      <br>
                      <br>
                      # get some test data<br>
                      swath_data = np.random.randint(1, 100, (500, 400))<br>
                      lons, lats = np.meshgrid(np.linspace(3, 5, 500),<br>
                                               np.linspace(40, 42, 400))<br>
                      <br>
                      with TemporaryDirectory() as td:<br>
                          p_lons_tmp = os.path.join(td, 'lons.tif')<br>
                          p_lats_tmp = os.path.join(td, 'lats.tif')<br>
                          p_data_tmp = os.path.join(td, 'data.tif')<br>
                          p_data_vrt = os.path.join(td, 'data.vrt')<br>
                          p_data_mapgeo_vrt = os.path.join(td,
                      'data_mapgeo.vrt')<br>
                      <br>
                          # save numpy arrays to temporary tif files<br>
                          for arr, path in zip((swath_data, lons, lats),
                      (p_data_tmp, p_lons_tmp, p_lats_tmp)):<br>
                              rows, cols = arr.shape<br>
                              drv = gdal.GetDriverByName('GTiff')<br>
                              ds = drv.Create(path, cols, rows, 1,
                      gdal.GDT_Float64)<br>
                              ds.GetRasterBand(1).WriteArray(arr)<br>
                              del ds<br>
                      <br>
                          # add geolocation information to input data<br>
                          wgs84_wkt = osr.GetUserInputAsWKT('WGS84')<br>
                          utm_wkt = osr.GetUserInputAsWKT('EPSG:32632')<br>
                          ds = gdal.Translate(p_data_vrt, p_data_tmp,
                      format='VRT')<br>
                          ds.SetMetadata(<br>
                          <br>
                              dict(<br>
                                  SRS=wgs84_wkt,<br>
                                  X_DATASET=p_lons_tmp,<br>
                                  Y_DATASET=p_lats_tmp,<br>
                                  X_BAND='1',<br>
                                  Y_BAND='1',<br>
                                  PIXEL_OFFSET='0',<br>
                                  LINE_OFFSET='0',<br>
                                  PIXEL_STEP='1',<br>
                                  LINE_STEP='1'<br>
                              ),<br>
                              'GEOLOCATION'<br>
                          )del ds<br>
                      <br>
                          # warp from geolocation arrays and read the
                      result<br>
                          gdal.Warp(p_data_mapgeo_vrt, p_data_vrt,
                      format='VRT', geoloc=True,<br>
                                    srcSRS=wgs84_wkt, dstSRS=utm_wkt)<br>
                          data_mapgeo =
                      gdal.Open(p_data_mapgeo_vrt).ReadAsArray()<br>
                          <br>
                      # visualize input and output data<br>
                      fig, axes = plt.subplots(1, 4)<br>
                      for i, (arr, title) in enumerate(zip((swath_data,
                      lons, lats, data_mapgeo),<br>
                                                        ('swath data',
                      'lons', 'lats', 'projected data'))):<br>
                          axes[i].imshow(arr, cmap='gray')<br>
                          axes[i].set_title(title)<br>
                      plt.tight_layout()<br>
                      plt.show()</font></p>
                  <p><font size="2"><br>
                    </font></p>
                </blockquote>
                <p>Any help would be highly appreciated!</p>
                <p>Best,</p>
                <p>Daniel Scheffler<br>
                </p>
                <br>
                <pre class="moz-signature" cols="72">-- 

M.Sc. Geogr. Daniel Scheffler

Helmholtz Centre Potsdam
GFZ German Research Centre For Geosciences
Department 1 - Geodesy and Remote Sensing
Section 1.4  - Remote Sensing
Telegrafenberg, 14473 Potsdam, Germany

Phone:  +49 (0)331/288-1198
e-mail: <a class="moz-txt-link-abbreviated moz-txt-link-freetext" href="mailto:daniel.scheffler@gfz-potsdam.de" moz-do-not-send="true">daniel.scheffler@gfz-potsdam.de</a></pre>
                <br>
                <fieldset class="mimeAttachmentHeader"></fieldset>
                <pre class="moz-quote-pre" wrap="">_______________________________________________
gdal-dev mailing list
<a class="moz-txt-link-abbreviated moz-txt-link-freetext" href="mailto:gdal-dev@lists.osgeo.org" moz-do-not-send="true">gdal-dev@lists.osgeo.org</a>
<a class="moz-txt-link-freetext" href="https://lists.osgeo.org/mailman/listinfo/gdal-dev" moz-do-not-send="true">https://lists.osgeo.org/mailman/listinfo/gdal-dev</a>
</pre>
              </blockquote>
              <pre class="moz-signature" cols="72">-- 
<a class="moz-txt-link-freetext" href="http://www.spatialys.com" moz-do-not-send="true">http://www.spatialys.com</a>
My software is free, but my time generally not.</pre>
            </blockquote>
            <br>
            <pre class="moz-signature" cols="72">-- 

M.Sc. Geogr. Daniel Scheffler

Helmholtz Centre Potsdam
GFZ German Research Centre For Geosciences
Department 1 - Geodesy and Remote Sensing
Section 1.4  - Remote Sensing
Telegrafenberg, 14473 Potsdam, Germany

Phone:  +49 (0)331/288-1198
e-mail: <a class="moz-txt-link-abbreviated moz-txt-link-freetext" href="mailto:daniel.scheffler@gfz-potsdam.de" moz-do-not-send="true">daniel.scheffler@gfz-potsdam.de</a></pre>
          </div>
          <br>
          <fieldset class="mimeAttachmentHeader"></fieldset>
          <pre class="moz-quote-pre" wrap="">_______________________________________________
gdal-dev mailing list
<a class="moz-txt-link-abbreviated moz-txt-link-freetext" href="mailto:gdal-dev@lists.osgeo.org" moz-do-not-send="true">gdal-dev@lists.osgeo.org</a>
<a class="moz-txt-link-freetext" href="https://lists.osgeo.org/mailman/listinfo/gdal-dev" moz-do-not-send="true">https://lists.osgeo.org/mailman/listinfo/gdal-dev</a>
</pre>
        </blockquote>
        <pre class="moz-signature" cols="72">-- 
<a class="moz-txt-link-freetext" href="http://www.spatialys.com" moz-do-not-send="true">http://www.spatialys.com</a>
My software is free, but my time generally not.</pre>
        <br>
        <fieldset class="mimeAttachmentHeader"></fieldset>
        <pre class="moz-quote-pre" wrap="">_______________________________________________
gdal-dev mailing list
<a class="moz-txt-link-abbreviated moz-txt-link-freetext" href="mailto:gdal-dev@lists.osgeo.org" moz-do-not-send="true">gdal-dev@lists.osgeo.org</a>
<a class="moz-txt-link-freetext" href="https://lists.osgeo.org/mailman/listinfo/gdal-dev" moz-do-not-send="true">https://lists.osgeo.org/mailman/listinfo/gdal-dev</a>
</pre>
      </blockquote>
      <br>
      <pre class="moz-signature" cols="72">-- 

M.Sc. Geogr. Daniel Scheffler

Helmholtz Centre Potsdam
GFZ German Research Centre For Geosciences
Department 1 - Geodesy and Remote Sensing
Section 1.4  - Remote Sensing
Telegrafenberg, 14473 Potsdam, Germany

Phone:  +49 (0)331/288-1198
e-mail: <a class="moz-txt-link-abbreviated moz-txt-link-freetext" href="mailto:daniel.scheffler@gfz-potsdam.de" moz-do-not-send="true">daniel.scheffler@gfz-potsdam.de</a></pre>
      <br>
      <fieldset class="moz-mime-attachment-header"></fieldset>
      <pre class="moz-quote-pre" wrap="">_______________________________________________
gdal-dev mailing list
<a class="moz-txt-link-abbreviated" href="mailto:gdal-dev@lists.osgeo.org">gdal-dev@lists.osgeo.org</a>
<a class="moz-txt-link-freetext" href="https://lists.osgeo.org/mailman/listinfo/gdal-dev">https://lists.osgeo.org/mailman/listinfo/gdal-dev</a>
</pre>
    </blockquote>
    <br>
    <pre class="moz-signature" cols="72">-- 

Dr. Daniel Scheffler

Helmholtz Centre Potsdam
GFZ German Research Centre For Geosciences
Department 1 - Geodesy and Remote Sensing
Section 1.4  - Remote Sensing and Geoinformatics
Telegrafenberg, 14473 Potsdam, Germany

Phone:  +49 (0)331/288-1198
e-mail: <a class="moz-txt-link-abbreviated" href="mailto:daniel.scheffler@gfz-potsdam.de">daniel.scheffler@gfz-potsdam.de</a></pre>
  </body>
</html>