英文:
Golang: get coordinate from .tif file
问题
我从该网站(例如https://drive.google.com/file/d/1OiFy-vLq9CvVeqNg9VogmxSPOMcpcD1W/view?usp=sharing)下载了地形数据,并获取了数据。我特别关注格式为*_DCM.tif的文件,据我了解,它存储了点的数据-经度、纬度和海拔。
使用gdal,我可以将文件转换为.XYZ文件并提取数据,但文件大小会变得太大。
基于此,有两个问题:
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方法。例如,我已将所有tif文件转换为VRT并使用它进行操作:gdallocationinfo -xml -wgs84 dsm-mosaic.vrt 28.000139 50.999861
我需要的是“Value”-海拔
但是我无论如何都找不到Golang的实现。我还尝试将代码改写为Python,但没有成功。
有人告诉我从代码中调用控制台命令是一个坏主意。
如果有人知道如何获取纬度和经度的信息,我将不胜感激:)
英文:
I downloaded the terrain data from the site (example https://drive.google.com/file/d/1OiFy-vLq9CvVeqNg9VogmxSPOMcpcD1W/view?usp=sharing ) and got the data. Specifically interested in the format *_DCM.tif, which, as I understand it, stores data on point - longitude, latitude and altitude.
With gdal I can convert a file to .XYZ file and take the data, but the file size becomes too large.
In this regard, 2 questions:
- Is it possible to parse the tif file somehow and get this data?
- Is it possible to convert programmatically .tif in .XYZ and work with the received data?
Which libraries have I already reviewed:
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
UPDATE:
I found the gdallocationinfo method. For example, I have converted all tiff files to VRT and am working with it: gdallocationinfo -xml -wgs84 dsm-mosaic.vrt 28.000139 50.999861
I need "Value" - altitude
But I couldn't find an implementation on Golang in any way. I also tried to rewrite the code in Python, but without success.
I was told that calling a console command from code is a bad idea.
If anyone knows how to get information on latitude and longitude, then I will be gdal
答案1
得分: 1
标准库的tiff包无法处理使用的编码,它显示使用的SampleFormat不受支持:tiff: unsupported feature: sample format
。
github.com/chai2010/tiff库可以完成这个任务。下面的示例解码图像,以便我们可以遍历所有像素。所需的格式使用GPS坐标,因此我们需要进行一些转换工作,我在示例中硬编码了偏移量,从文件名动态解析它们应该不难。
对于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: 从文件名解析偏移量
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++ {
// 根据图像大小将X和Y归一化到0到1的空间。
// 添加偏移量以获取坐标。
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")
}
}
}
英文:
The tiff package of the standard library can't handle the encoding used, it says that the SampleFormat that was uses is not supported: tiff: unsupported feature: sample format
.
The github.com/chai2010/tiff library does the job. The example below decodes the image so we can loop over all of its pixels. The desired format uses GPS coordinates, so we have to do some conversion work, I hardcoded the offsets to keep the example concise, parsing them dynamically from the file name should not be difficult.
I am not 100% sure about the float64(x) / float64(bounds.Max.X))
part, since the values don't seem to match the screenshot you sent. Could be that some other scaling values should be used depending on the grid size, but I figure you can fix that yourself.
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")
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论