mis*_*toe 2 javascript tiff maptiler
我正在开展一个项目,需要使用正射马赛克地图。该地图采用 .tiff 格式。我想从该地图中提取地理信息,以便我可以将其正确覆盖在谷歌地图上。我在这个项目中使用平均堆栈。
所以我的最后一个问题是:有没有办法使用 JavaScript 从 tiff 图像中提取地理标签?
编辑:当我使用 Maptiler(https://www.maptiler.com/)时,它会自动将 .tif 文件正确放置在谷歌地图上。我想知道它如何提取信息并将其放置在地图上,以便我可以自己完成。
为了读取 TIFF 标签,您需要一个适当的 TIFF 解析器(如tiff包),以便您可以运行IFD 块的非位图部分:
import tiff from "tiff";
// Load a GeoTIFF file
const file = fs.readFileSync(`ALPSMLC30_S045E168_DSM.tif`);
// We can do this in the browser, too, the `decode` function takes an ArrayBuffer
const image = tiff.decode(file.buffer);
// get the first IFD block's pixels and fields
const { data:pixels, fields, width, height } = image[0];
// let's see what tags apply
console.log(fields);
Run Code Online (Sandbox Code Playgroud)
产量(对于这个特定的 GeoTIFF):
Map(19) {
254 => 0,
256 => 3600,
257 => 3600,
258 => 16,
259 => 1,
262 => 1,
273 => Uint32Array(3600) [
... 3600 more items
],
274 => 1,
277 => 1,
278 => 1,
279 => Uint32Array(3600) [
... 3600 more items
],
282 => 1,
283 => 1,
284 => 1,
339 => 2,
33550 => Float64Array(3) [
0.0002777777777777778,
0.0002777777777777778,
0
],
33922 => Float64Array(6) [
0,
0,
0,
168,
-44,
0
],
34735 => Uint16Array(24) [
1, 1, 0, 5,
1024, 0, 1, 2,
1025, 0, 1, 1,
2048, 0, 1, 4326,
2052, 0, 1, 9001,
2054, 0, 1, 9102
],
34737 => 'WGS-84'
}
Run Code Online (Sandbox Code Playgroud)
我想知道它如何提取信息并将其放置在地图上,以便我可以自己完成。
系好安全带,这将变得更加详细。
标签号都是明确定义的东西,可以在https://www.awaresystems.be/imaging/tiff/tifftags.html上找到,其中所有低编号的都是通用 TIFF 标签(256 和 257 是图像的宽度和高度,274 是“该图像是否旋转”,284 告诉我们像素是否存储为 RGBRGBetc 还是作为单独的 R、G 和 B 数组等),数字较大的是“私有”标签,仅使用在特定的背景下。例如,339告诉我们像素使用二进制补码存储有符号整数,33550是模型像素比例标签,34737是GeoASCII 参数标签等。
其中,34735 可以说是最重要的标签,因为它包含地图软件用来正确放置图像的GeoKey 字典:
第一行 ,1 1 0 5内容如下:
GeoKey 字典中的每个条目都按“键、tifftaglocation、计数、值”排序,字段为tifftaglocation0(所有“值”字段使用 SHORT,无符号 16 位整数数据类型)或 1(tiff 标记的正式规范告诉您如何解码该值),该count字段告诉我们该值由多少个 SHORT 组成。
在这种情况下:
为了进行与地图相关的事情(在没有可以自动为您放置 tiff 的工具的情况下),我们查看标签 33500(它为我们提供地图比例)和 33922(它为我们提供地图翻译):
...
33550 => Float64Array(3) [
0.0002777777777777778, 0.0002777777777777778, 0
],
33922 => Float64Array(6) [
0, 0, 0,
168, -44, 0
],
...
Run Code Online (Sandbox Code Playgroud)
33922 中的值告诉我们,像素索引 x=0、y=0(具有未使用的 z 值 0)映射到现实世界弧度坐标 x=168、y=-44,即 S44 E168(也具有未使用的 z 值) -值 0) 和 33550 告诉我们图像中的像素1 degree of arc * 0.00027[...] = 1/3600 arc degree = 1 arc second = 30.87 meters在 x 和 y 方向上都是间隔开的,这使我们能够确定在地图上放置和对齐此数据的正确平移和缩放。
它还允许我们计算“给定 TIFF 像素的 GPS 坐标”和“给定 GPS 坐标的 TIFF 像素”。基于https://gdal.org/tutorials/geotransforms_tut.html:
Map(19) {
254 => 0,
256 => 3600,
257 => 3600,
258 => 16,
259 => 1,
262 => 1,
273 => Uint32Array(3600) [
... 3600 more items
],
274 => 1,
277 => 1,
278 => 1,
279 => Uint32Array(3600) [
... 3600 more items
],
282 => 1,
283 => 1,
284 => 1,
339 => 2,
33550 => Float64Array(3) [
0.0002777777777777778,
0.0002777777777777778,
0
],
33922 => Float64Array(6) [
0,
0,
0,
168,
-44,
0
],
34735 => Uint16Array(24) [
1, 1, 0, 5,
1024, 0, 1, 2,
1025, 0, 1, 1,
2048, 0, 1, 4326,
2052, 0, 1, 9001,
2054, 0, 1, 9102
],
34737 => 'WGS-84'
}
Run Code Online (Sandbox Code Playgroud)
(变换反转在https://gis.stackexchange.com/a/452575/219296上进行了解释)
使用此代码,我们可以在 GPS 坐标和像素坐标之间进行转换。例如,运行以下代码:
...
33550 => Float64Array(3) [
0.0002777777777777778, 0.0002777777777777778, 0
],
33922 => Float64Array(6) [
0, 0, 0,
168, -44, 0
],
...
Run Code Online (Sandbox Code Playgroud)
针对上述 TIFF 数据生成以下日志:
GPS: (-44.9856891,168.321971), PX: (1159,3548), elevation: 1421m
Run Code Online (Sandbox Code Playgroud)
或者走另一条路:
function transform(matrix, x, y) {
return [
matrix[0] + matrix[1] * x + matrix[2] * y,
matrix[3] + matrix[4] * x + matrix[5] * y,
];
}
let [sx, sy, _sz] = fields.get(33550);
const [
_px, _py, _k,
gx, gy, _gz
] = fields.get(33922);
// Just like SVG or <canvas>, GeoTIFF uses a "flipped" y coordinate.
sy = -sy;
// Our "forward transform" goes from pixels to geographic coordinate,
// and is the (partial) matrix from the link above.
const pixel_to_geo = [
gx, sx, 0,
gy, 0, sy
];
// Our "reverse transform" is literally the inverse matrix operation,
// converting geographic coordinates to pixels.
const geo_to_pixel = [
-gx/sx, 1/sx, 0,
-gy/sy, 0, 1/sy
];
function pixelToGeo(x, y) {
const [lat, long] = transform(pixel_to_geo, x, y);
return { lat, long };
}
function geoToPixel(long, lat) {
const [x, y] = transform(geo_to_pixel, long, lat);
return { x: x|0, y: y|0 };
}
Run Code Online (Sandbox Code Playgroud)
针对上述 TIFF 数据生成以下日志:
PX: (278,1882) maps to GPS: (-44.522777777777776,168.07722222222222)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1374 次 |
| 最近记录: |