有没有办法使用 javascript 从 tiff 图像中提取地理标签?

2023-11-30

我正在开展一个项目,需要使用正射马赛克地图。该地图采用 .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
const block = image[0];
const pixels = block.data;

// let's see what tags apply
const fields = block.fields;

console.log(fields);

产量(对于这个特定的 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'
}

我想知道它如何提取信息并将其放置在地图上,以便我可以自己完成。

系好安全带,这将变得更加详细。

标签号都是明确定义的东西,可以在上面列出https://www.awaresystems.be/imaging/tiff/tifftags.html,例如33550 is the 模型像素比例 tag, 34737 is the GeoASCII 参数标签等

其中,34735 可以说是最重要的标签,因为它包含GeoKey字典地图软件使用它来正确放置图像:

第一行,1 1 0 5, reads:

  • “蒂夫版本 1”,
  • “keys revision 1.0”(编码为单独的主要值和次要值),
  • “有5 项在这本词典里”

其中每个条目都按“key、tifftaglocation、count、value(s)”排序,其中tifftaglocation字段可以是 0(“值”是 SHORT)或 1(tiff 标签的正式规范告诉您如何解码该值),其中count字段告诉我们该值由多少个 SHORT 组成。

在这种情况下:

  • 1024 (型号类型) 的值为 2:地理纬度-经度系统。
  • 1025 (光栅类型) 的值为 1:每个像素代表一个区域(例如,它是平均高度图,而不是像素是仅在该点具有确切已知海拔的特定点)
  • 2048 (地理类型) 的值为 4326:这是 WGS84 数据,例如它使用几乎所有地图软件都使用的 Web Mercator 投影
  • 2052 (线性单位) 的值为 9001:数据使用 EPSG 线性单位(即“十进制度”,因此值 38.25 表示数字通常的含义)。
  • 2054 (角度单位) 的值为 9102:数据的角度方面是弧度,因此与之前的值结合我们知道,如果我们看到 38.25,则意味着 38.25 * 1 弧度。

为了进行与地图相关的事情(在没有可以自动为您放置 tiff 的工具的情况下),我们查看标签 33500(它为我们提供地图比例)和 33922(它为我们提供地图翻译):

  ...
  33550 => Float64Array(3) [
    0.0002777777777777778,
    0.0002777777777777778,
    0
  ],
  33922 => Float64Array(6) [
    0,
    0,
    0,
    168,
    -44,
    0
  ],
  ...

这告诉我们像素索引 x=0, y=0(未使用的 z 值 0)映射到现实世界弧度坐标 x=168, y=-44,即 S4E E168(也未使用的 z 值 0) )并且图像中的每个像素代表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:

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);
let [_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 };
}

(变换反转已在上解释过https://gis.stackexchange.com/a/452575/219296)

使用此代码,我们可以在 GPS 坐标和像素坐标之间进行相互转换:

const lat = 168.321971;
const long = -44.9856891;
const { x, y } = geoToPixel(long, lat);
const elevation  = pixels[x + y * block.width];
console.log(`GPS: ${lat},${long}, PX: ${x},${y}, elevation: ${elevation}m`);

根据上述 TIFF 数据,生成以下信息:

GPS: -44.9856891,168.321971, PX: 1159,3548, elevation: 1421m

或者走另一条路:

const [ x, y ] = [
  (Math.random() * block.width)|0,
  (Math.random() * block.height)|0
];
const { lat, long } = pixelToGeo(x, y);
console.log(`PX: ${x},${y} maps to GPS: ${lat},${long}`);

根据上述 TIFF 数据,生成以下信息:

PX: 278,1882 maps to GPS: -44.522777777777776,168.07722222222222
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

有没有办法使用 javascript 从 tiff 图像中提取地理标签? 的相关文章

随机推荐

  • 如何修复 Python ValueError:bad marshal data?

    在 Ubuntu 中运行 flexget Python 脚本 出现错误 flexget series forget Orange is the new black s03e01 Traceback most recent call last
  • 如何在 Nuxt 中使用私有 API 密钥(在客户端)?

    问题解决了 如果您遇到同样的问题 请查看已接受的答案 这是使用 serverMiddleware 实现它的一种方法 我正在使用需要私钥的 API 我已将密钥存储在 env 文件中 并在 nuxt 配置文件中调用它 如下所示 privateR
  • 如何使用 R 中的最大似然模型将非线性函数拟合到 ggplot2 中的数据?

    数据集 x test y test 是指数拟合 我正在尝试适应自定义非线性函数 并附上代码 常规点图很好 但我无法使拟合线发挥作用 有什么建议么 x test lt runif 50 2 8 y test lt 0 5 x test df
  • 如何处理 socket.io 客户端聊天应用程序中的页面重新加载

    我正在实现一个聊天应用程序 我不在服务器中 包含 javascript 文件的页面可以是文件系统上嵌入了 javascript socket io 的任何 html 页面 现在的问题是 根据定义 页面重新加载总是会触发新的请求 从而产生新的
  • 如何从辅助方法设置变量以包含在 SASS SCSS 样式表中?

    我有一个辅助方法 可以检索需要进入 SASS scss 样式表的字符串 如果我在视图中调用该方法 它工作正常 但似乎 sass 需要一个变量 似乎如果我尝试在控制器中设置一个 var 并认为这最初是正确的方法 我无法在任何地方看到该 var
  • Perl:匹配时空 $1 正则表达式值?

    读者们 我有以下正则表达式问题 code usr bin perl w use 5 010 use warnings my filename input txt open my FILE lt filename or die while m
  • 剂量响应 - 使用 R 进行全局曲线拟合

    我有以下剂量反应数据 希望绘制剂量反应模型和全局拟合曲线 xdata 药物浓度 ydata 0 5 不同药物浓度下的响应值 我毫无问题地绘制了标准曲线 标准曲线数据拟合 df lt data frame xdata c 1000 00 30
  • 从 C# 代码调用 delphi DLL 方法

    我正在尝试从 C ASP NET 代码调用 Delphi 函数 该函数的声明如下所示 function SomeFunction const someString SomeOtherString string OleVariant 从我的
  • 我如何洗牌并向玩家一次一张发牌?

    这就是我到目前为止所得到的 发现自己陷入困境 Private Sub Dealbtn Click sender As Object e As EventArgs Handles Dealbtn Click Dim Suits As Stri
  • 如果数组包含 2 或 3,则返回 True

    我遇到了这个 CodingBat 问题 给定一个长度为 2 的 int 数组 如果它包含 2 或 3 则返回 True 我尝试了两种不同的方法来解决这个问题 谁能解释我做错了什么 This one says index is out of
  • ValueError:地下矩形外表面积

    我正在制作一款相机跟随玩家的平台游戏 我试图通过在整个地图上拥有一个大的表面并且只传输放大的部分来实现这一点 但是我只能获得 30 fps 最小化 和 8 fps 全屏 所以我尝试优化它是在位块传输之前裁剪它 但我得到ValueError
  • 是否有用于电话状态的 NSNotification

    当设备打开 关闭手机时 我们是否可以观察到 NSNotification The NotificationCenter不会发出任何有关此的通知 但请看一下CTCallCenteriOS 4 中引入的类 它有一个callEventHandle
  • R 按键分组获取多列的最大值

    我想做这样的事情 如何使R中的A列唯一并保留B列中具有最大值的行 除了我的data table有一个键列和多个值列 所以说我有以下内容 a b c 1 1 1 1 2 1 2 1 3 1 2 2 4 2 1 1 5 2 2 5 6 2 3
  • Perl - 在关联数组单词和单词上下文中查找并保存

    我有一个像这样的数组 这只是一个小概述 但它有 2000 行及更多这样的行 list affaire chose question cause chose mati re 我想要这样的输出 te affaire gt chose quest
  • 当对象大于视口时,CSS 居中

    我试图让 jquery 轮播位于屏幕中央 即使剪切区域比视口更宽 这基本上总是给元素一个负的左边距 我该如何指定呢 剪切区域的宽度是固定的 但视口区域当然是可变的 这是我能找到的最佳解决方案 在固定宽度内容周围使用环绕元素 然后在内容本身上
  • Android:BroadcastReceiver 重新启动被杀死/崩溃的应用程序

    我有一个应用程序 我希望能够在发生错误或崩溃 应用程序关闭时重新启动它 我熟悉如何注册BroadcastReceivers 使用闹钟等 我是否可以拦截应用程序关闭时发出的任何信号 或者当任何应用程序关闭时操作系统会发送出去 我是否可以拦截应
  • 如果需要,允许使用 Cleartext 流量 Android Studio

    我有 2 部手机 api 28 17 所以当请求 HTTP 时 它与 api 17 一起使用 但不是在 api 28 中 朋友说 我必须使用 android usesCleartextTraffic true 在清单中 但是当构建它在手机中
  • 将 template.js.erb 重写为 template.js.slim

    下面的 js erb 模板重写为 slim 后会是什么样子 new reservation hide after Slim 提供了一种多行方法 var html j render new reservation new reservatio
  • 从输入文件路径logstash中提取字段?

    我想从各个目录读取日志文件 例如 Server1 Server2 Server1子目录为cron auth 这些子目录中是log file分别 所以我正在考虑读取这样的文件 input file path to folders server
  • 有没有办法使用 javascript 从 tiff 图像中提取地理标签?

    我正在开展一个项目 需要使用正射马赛克地图 该地图采用 tiff 格式 我想从该地图中提取地理信息 以便我可以将其正确覆盖在谷歌地图上 我在这个项目中使用平均堆栈 所以我的最后一个问题是 有没有办法使用 javascript 从 tiff