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个问题:
- 是否可以通过某种方式解析 tif 文件并获取此数据?
- 是否可以在 .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")
}
}
}
我从站点(例如https://drive.google.com/file/d/1OiFy-vLq9CvVeqNg9VogmxSPOMcpcD1W/view?usp=sharing)下载了地形数据并得到了数据。对格式 *_DCM.tif 特别感兴趣,据我所知,它存储点数据 - 经度、纬度和高度。
使用 gdal 我可以将文件转换为 .XYZ 文件并获取数据,但文件大小变得太大。
XYZ file example
这方面,2个问题:
- 是否可以通过某种方式解析 tif 文件并获取此数据?
- 是否可以在 .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")
}
}
}