☰
FairScan纸张尺寸识别揭秘:让扫描PDF还原A4/Letter的自动吸附算法
2026/10/23 1:58:28 网站建设 项目流程

【免费下载链接】FairScan

An Android app to scan your documents — simple and respectful

项目地址:https://gitcode.com/gh_mirrors/fa/FairScan
点击查看免费下载

FairScan 是一款开源、隐私友好的 Android 文档扫描应用,所有处理都在本机完成。很多扫描应用的通病是:拍完照生成的 PDF 页面大小总是和真实纸张"差一口气"。本文带你拆解 FairScan 的纸张尺寸识别与自动吸附算法——它如何从一张歪斜的照片里估算出纸张的真实毫米尺寸,再把 212×300mm 这样的近似值一键"吸附"到 A4、Letter 等标准纸型,让扫描 PDF 一比一还原真实纸张。

扫描件为什么总"对不上" A4?

📷 用普通相机拍一张纸,照片里的"纸"是透视变形过的:近宽远窄、梯形、带阴影。如果直接把裁剪结果塞进 PDF,页面尺寸只能按像素拍脑袋,打印出来必然偏大或偏小。

FairScan 的解决思路分三步:先算出纸的真实尺寸(毫米),再吸附到标准纸型,最后把毫米写进 PDF。

三步管线:从一张歪斜照片到毫米级纸型

第 1 步:用透视几何估算"真实尺寸"

核心逻辑在 Perspective.kt 的estimateRealDimensions()函数里,它做了几件事:

  1. 求两组对边的消失点:纸张四条边在照片里是梯形,把上下边、左右边分别延长,交点就是消失点(vanishing point)。
  2. 恢复平面几何:结合相机焦距(若设备提供相机参数CameraIntrinsics,否则用消失点反推焦距f² = -(v1x·v2x + v1y·v2y)),把四个角点"反投影"回三维空间,量出四条边的真实长度。
  3. 输出两种结果:
    • 设备能提供主体距离(subjectDistance)→ 得到Physical(单位:毫米)
    • 拿不到距离 → 只得到Ratio(只有宽高比有意义)

如果纸张几乎正对镜头、透视太弱(消失点飘到无穷远),代码会退回"上下边取平均"的保守估计,保证结果稳定。

第 2 步:自动吸附snapToStandardFormat

量出来的是近似值(相机测距、透视估算都有误差),所以 FairScan 把它"吸附"到最接近的标准纸型,见 Perspective.kt:

标准纸型宽 × 高(mm)宽高比
A3297 × 420≈1.414
A4210 × 297≈1.414
A5148 × 210≈1.419
Letter215.9 × 279.4≈1.294
Legal215.9 × 355.6≈1.647

判定条件(两个默认容差):

  • ratioTolerance = 0.04:宽高比误差 < 4%
  • dimensionTolerance = 0.20:宽、高各自误差 < 20%

两个条件同时满足才算命中;命中横版纸张时还会自动交换宽高,保持方向正确。以上纸型定义在 Perspective.kt 的PaperFormats对象中。

第 3 步:把毫米写进 PDF 页面

导出时,AndroidPdfWriter.kt 按 PDF 规范(72 点/英寸,1 英寸 = 25.4mm)把毫米尺寸换算成 PDF 页面点数:

val pointsPerMm = 72f / 25.4f // ≈ 2.835 点/mm val widthPoints = widthMm.toFloat() * pointsPerMm

同时constrainToMaxFormat()会把页面限制在 A4 范围内,防止异常尺寸撑爆版面。若某页拿不到物理尺寸,则退化为"按 A4 高度等比缩放"的兜底策略。

4% 容差是怎么定出来的?

🎯 关键洞察:标准纸型之间要么"宽高比差很多",要么"尺寸差很多",所以 4% + 20% 的双门槛足以避免误判:

  • A4 vs Letter:宽高比 1.414 vs 1.294,相差约 12%,远超 4% 容差 → 一眼分辨
  • A4 vs A5:宽高比几乎相同(1.414 vs 1.419),但尺寸差了约 30% → 靠 20% 的绝对尺寸容差拦截
  • 远非标准纸:如 150×400mm 的怪尺寸,两项都超差 → 原样保留,不强行吸附

这套"比例 + 绝对尺寸"双校验,正是 EstimatedDimensionsTest.kt 中单元测试覆盖的场景:

输入(mm)吸附结果
212 × 300✅ A4 (210×297)
218 × 281✅ Letter (215.9×279.4)
300 × 212✅ 横版 A4 (297×210)
150 × 400🚫 保持不变

常见疑问:什么时候会吸附失败?

  1. 设备缺少相机参数或测距数据→ 只能得到Ratio(宽高比),snapToStandardFormat()直接跳过,PDF 用兜底缩放。
  2. 纸几乎正对镜头→ 消失点不可靠,退回"边长平均"估计,同样只得到比例。
  3. 纸张太倾斜(中心射线与纸面法线夹角余弦 < 0.1)→ 测距结果被判定不可信,降级为比例。
  4. 非标准纸张(手写便签、A4 剪裁件等)→ 保持估算原值,不吸附。

换句话说:FairScan 宁可不吸附,也不"猜错纸型",这与它"简单且尊重用户"的产品定位一致。

源码地图 🗺️

  • 纸型定义与吸附算法:imageprocessing/src/main/java/org/fairscan/imageprocessing/Perspective.kt
  • 尺寸估算调用处(裁剪管线):imageprocessing/src/main/java/org/fairscan/imageprocessing/DocumentDetection.kt
  • 导出前尺寸计算:app/src/main/java/org/fairscan/app/domain/ExportPreparation.kt
  • PDF 页面尺寸写入:app/src/main/java/org/fairscan/app/platform/AndroidPdfWriter.kt
  • 吸附单元测试:imageprocessing/src/test/java/org/fairscan/imageprocessing/EstimatedDimensionsTest.kt
  • 更新日志("Better PDF page sizes with automatic detection of standard paper formats"):metadata/en-US/changelogs/


📌一句话总结:FairScan 用"透视几何量真实毫米 + 4% 比例容差吸附标准纸型 + 毫米直写 PDF"这条管线,让扫描件无需任何手动调整,就能获得 A4/Letter 的精确页面尺寸——而且整个过程 100% 在你的手机上完成。

【免费下载链接】FairScan

An Android app to scan your documents — simple and respectful

项目地址:https://gitcode.com/gh_mirrors/fa/FairScan
点击查看免费下载
上一篇:FunASR核心组件解密:构建端到端语音识别系统的底层技术架构
下一篇:如何高效整合开源课程教学资源:最佳实践与工具推荐清单

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询