Golang:从.tif文件中获取坐标

huangapple go评论85阅读模式
英文:

Golang: get coordinate from .tif file

问题

我从该网站(例如https://drive.google.com/file/d/1OiFy-vLq9CvVeqNg9VogmxSPOMcpcD1W/view?usp=sharing)下载了地形数据,并获取了数据。我特别关注格式为*_DCM.tif的文件,据我了解,它存储了点的数据-经度、纬度和海拔。

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

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

gdallocationinfo结果

我需要的是“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.

XYZ file example

In this regard, 2 questions:

  1. Is it possible to parse the tif file somehow and get this data?
  2. 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

gdallocationinfo result

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 Golang:从.tif文件中获取坐标

答案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 (
	&quot;bufio&quot;
	&quot;image/color&quot;
	&quot;os&quot;
	&quot;strconv&quot;

	&quot;github.com/chai2010/tiff&quot;
)

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

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

	output, err := os.Create(&quot;N050E028_DSM.xyz&quot;)
	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 &lt; bounds.Max.Y; y++ {
		for x := bounds.Min.X; x &lt; 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, &#39;f&#39;, 16, 64))
			outputWriter.WriteString(&quot; &quot;)
			outputWriter.WriteString(strconv.FormatFloat(lat, &#39;f&#39;, 16, 64))
			outputWriter.WriteString(&quot; &quot;)
			outputWriter.WriteString(strconv.Itoa(int(height.Y)))
			outputWriter.WriteString(&quot;\n&quot;)
		}
	}
}

huangapple
  • 本文由 发表于 2021年12月24日 01:29:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/70465519.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定