Golang:从 .tif 文件获取坐标

Golang: get coordinate from .tif file

我从站点(例如https://drive.google.com/file/d/1OiFy-vLq9CvVeqNg9VogmxSPOMcpcD1W/view?usp=sharing)下载了地形数据并得到了数据。对格式 *_DCM.tif 特别感兴趣,据我所知,它存储点数据 - 经度、纬度和高度。

使用 gdal 我可以将文件转换为 .XYZ 文件并获取数据,但文件大小变得太大。

XYZ file example

这方面,2个问题:

  1. 是否可以通过某种方式解析 tif 文件并获取此数据?
  2. 是否可以在 .XYZ 中以编程方式转换 .tif 并使用接收到的数据?

我已经查看了哪些库:

https://github.com/chai2010/tiff/tree/master/examples

https://github.com/lukeroth/gdal/blob/master/examples/tiff/tiff.go

https://github.com/airbusgeo/godal/blob/main/doc_test.go

https://pkg.go.dev/github.com/rwcarlsen/goexif/exif

https://pkg.go.dev/github.com/evanoberholster/imagemeta

更新:

我找到了 gdallocationinfo 方法。例如,我已将所有 tiff 文件转换为 VRT 并正在使用它:gdallocationinfo -xml -wgs84 dsm-mosaic.vrt 28.000139 50.999861

gdallocationinfo result

我需要“值”- 海拔高度

但我无法以任何方式在 Golang 上找到实现。我也尝试重写Python中的代码,但没有成功。

有人告诉我从代码调用控制台命令是个坏主意。

如果有人知道如何获取经纬度信息,那我就是gdal :)

标准库的tiff包无法处理使用的编码,它说不支持使用的SampleFormat:tiff: unsupported feature: sample format.

github.com/chai2010/tiff 库可以完成这项工作。下面的示例对图像进行解码,因此我们可以遍历其所有像素。所需格式使用 GPS 坐标,因此我们必须做一些转换工作,我硬编码了偏移量以保持示例简洁,从文件名动态解析它们应该不难。

我不是 100% 确定 float64(x) / float64(bounds.Max.X)) 部分,因为值似乎与您发送的屏幕截图不匹配。可能是应该根据网格大小使用其他一些缩放值,但我认为你可以自己解决这个问题。

package main

import (
    "bufio"
    "image/color"
    "os"
    "strconv"

    "github.com/chai2010/tiff"
)

func main() {
    input, err := os.Open("N050E028_DSM.tif")
    if err != nil {
        panic(err)
    }

    // TODO: parse the offsets from the file name
    latOffset := float64(50)
    lngOffset := float64(28)

    output, err := os.Create("N050E028_DSM.xyz")
    if err != nil {
        panic(err)
    }
    outputWriter := bufio.NewWriter(output)

    img, err := tiff.Decode(bufio.NewReader(input))
    if err != nil {
        panic(err)
    }

    bounds := img.Bounds()
    for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
        for x := bounds.Min.X; x < bounds.Max.X; x++ {
            // Normalize X and Y to a 0 to 1 space based on the size of the image.
            // Add the offsets to get coordinates.
            lng := lngOffset + (float64(x) / float64(bounds.Max.X))
            lat := latOffset + (float64(y) / float64(bounds.Max.Y))

            height := img.At(x, y).(color.Gray16)

            outputWriter.WriteString(strconv.FormatFloat(lng, 'f', 16, 64))
            outputWriter.WriteString(" ")
            outputWriter.WriteString(strconv.FormatFloat(lat, 'f', 16, 64))
            outputWriter.WriteString(" ")
            outputWriter.WriteString(strconv.Itoa(int(height.Y)))
            outputWriter.WriteString("\n")
        }
    }
}