【问题标题】:Golang: get coordinate from .tif fileGolang:从 .tif 文件中获取坐标
【发布时间】:2021-12-23 17:29:09
【问题描述】:

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

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

XYZ file example

在这方面,2个问题:

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

我已经查看了哪些库:

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 :)

【问题讨论】:

    标签: go tiff


    【解决方案1】:

    标准库的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")
            }
        }
    }
    

    【讨论】:

    • 感谢您的提示。不幸的是,我无法通过这种方式获取信息
    • 您可以在某处上传一个示例文件以便我们查看您正在处理的内容吗?因为我们无法从提供的链接下载它。还有一些关于这种 .XYZ 格式的信息,它与维基百科文章中描述的相同吗?或其他格式(似乎很可能,因为您谈论的是地理数据而不是化学)
    • 我找到了一个可行的例子,希望对您有所帮助
    • 你拯救了我的神经系统。谢谢
    猜你喜欢
    • 2013-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多