kluter/SiliconAperture

GitHub: kluter/SiliconAperture

一款纯前端照片测距工具,利用针孔相机模型从单张照片中推算物体的真实物理尺寸。

Stars: 1 | Forks: 0

SiliconAperture logo SiliconAperture

**从单张照片中测量物体的真实尺寸。** `SiliconAperture` 将针孔相机模型应用于照片:在物体上标记两个点,提供到物体的距离以及相机的传感器尺寸,该工具即可返回物体的物理尺寸。无需上传。无需服务器。一切均在您的浏览器中本地运行。 **[在线体验 → kluter.github.io/SiliconAperture](https://kluter.github.io/SiliconAperture/)** < TODO: add demo screenshot → ![SiliconAperture](https://raw.githubusercontent.com/kluter/SiliconAperture/main/assets/demo_screen.png) > ## 背景 2012年,在搭载固定翼平台和定时单反相机的无人机任务中,图像校准只能采用复杂的方式:**内方位元素**(焦距、主点、畸变)和**外方位元素**(空间中的位置和姿态)。在此之前,您无法将任何像素投影回地面并恢复现实世界的距离。需要手动布设地面控制点,这是老派的遥感技术。 `SiliconAperture` 将这一原理精炼为最简单且实用的形式:一张照片,一个已知距离,一次测量。 ## 工作原理 针孔相机模型通过相似三角形将图像像素与现实世界的距离联系起来: ``` size = √( (D · tan(Δx / W · sw / f))² + (D · tan(Δy / H · sh / f))² ) ``` | 符号 | 含义 | |--------|---------| | `D` | 从相机到物体的距离 | | `Δx, Δy` | 物体在各坐标轴上的像素跨度 | | `W, H` | 图像的宽度/高度(以像素为单位) | | `sw, sh` | 传感器的宽度/高度(以 mm 为单位) | | `f` | 焦距(以 mm 为单位) | 每个坐标轴使用其对应的传感器尺寸独立求解,然后使用勾股定理将两个现实世界的分量合并。这意味着您在照片上绘制的线可以是任意角度——水平、垂直或对角线——且结果始终是真实的欧几里得长度,而不是其在某一个坐标轴上的投影。 要获得准确的结果,需要物体**垂直于相机轴线**。如果表面相对于镜头倾斜(靠近或远离),传感器所看到的表观范围将不再与真实的物理尺寸成线性映射关系,测量结果将会出现偏差。 ## 使用方法 1. **拖放照片**到左侧面板(或点击浏览)。 2. 从下拉菜单中**选择您的相机**。如果图像包含 EXIF 元数据,相机型号、传感器尺寸和焦距将自动填入。否则,请从列表中选择,或手动输入传感器尺寸和焦距。 3. 通过在照片上点击两个点来**标记物体的范围**。像素跨度会自动计算。该连线可以是任意角度。 4. **输入**到物体的**距离**(以米为单位),或在卫星地图上点击两个点来进行测量。 只要这四个输入值均有效,结果就会立即显示。 ### 键盘快捷键 | 按键 | 操作 | |-----|--------| | `R` | 重置标记 | | `N` | 加载新图像 | | `Esc` | 关闭帮助 | ## 准确度 该公式假设使用的是标准的针孔相机。真实的镜头会引入畸变,但对于中等焦距(等效焦距约 24 mm 以上)且光学矫正良好的镜头,误差很小。实际中较大的误差来源包括: - **物体未垂直于相机轴线。** 倾斜于镜头(靠近或远离)的表面,其表观范围会被压缩或扩大。该工具无法检测或纠正这种情况。 - **传感器尺寸。** 数据库的数据来源于制造商规格、DXOMark 和 imaging-resource.com。标记为“近似”的值可能与实际生产型号有所差异。对于精密测量工作,请对照相机的官方服务文档进行验证。 - **EXIF 焦距。** 这是拍摄时的物理焦距。变焦镜头会报告其实际位置。裁剪或像素合并的图像可能针对调整大小后的像素网格保留全画幅传感器的焦距——请验证图像尺寸是否与传感器的原生分辨率匹配。 - **距离不确定性。** 结果随 `D` 呈线性缩放。5% 的距离误差会导致 5% 的尺寸误差。 ## 本地运行 这是一个无需构建步骤的静态站点。您可以使用任何工具来托管该文件夹: ``` npx serve . # 或 python3 -m http.server ``` ## 安全与隐私 您的照片永远不会离开您的浏览器。它会被绘制到 canvas 中并在内存中读取其 EXIF 数据:没有上传,也没有服务器。所有 EXIF 文本均通过 `textContent` 写入,因此带有恶意构造元数据的文件无法向页面注入任何内容。 仅有的外部请求是来自公共切片服务器的地图切片(Esri、OpenStreetMap、Carto)以及两个从 CDN 加载的库。 ``` // Every network request SiliconAperture makes: // GET unpkg.com/leaflet@1.9.4/... (map library, once) // GET cdn.jsdelivr.net/npm/exifr/... (EXIF parser, once) // GET .../tile/{z}/{x}/{y} (map tiles) // No image data, no coordinates, nothing else. ``` **关于地图切片的说明:** 切片请求会对您正在查看的区域进行编码。切片服务器可以推断出您正在测量的位置。如果这很重要,请使用 VPN。 ### 依赖项 | 库 | 用途 | 加载来源 | |---------|---------|-------------| | [Leaflet](https://leafletjs.com/) | 地图渲染 | CDN (unpkg) | | [exifr](https://github.com/MikeKovarik/exifr) | EXIF 元数据解析 | CDN (jsDelivr) | 要完全离线运行,请下载这两个库到本地,并替换 `index.html` 中的 CDN 链接。 该工具是在 AI 协助下构建的。代码为纯净、未压缩的 JavaScript —— 可直接在 `js/script.js` 中阅读源码。 ## 相关项目 **[TracePoint](https://github.com/kluter/TracePoint)** - 通过相交视线对照片进行地理定位。 **[ShadowFinder Web](https://github.com/kluter/ShadowFinder-Web)** - 通过阴影长度对照片进行地理定位。
标签:前端工具, 图像测量, 摄影测量, 数据可视化, 本地计算, 自定义脚本, 计算机视觉