
Accessible Book Reader 成品
对于盲人和重度视障者来说,普通纸质书本身没有语音输出,依赖屏幕的阅读设备也未必容易操作。作者 lhm0 因此制作了一台 Accessible Book Reader:把打开的书倒扣在两块倾斜玻璃上,按下实体按键,设备便拍摄左右两页、识别文字并按顺序朗读。
这是一套开源软件与开放硬件结合的完整设备。Raspberry Pi 5 负责图像处理、OCR 和系统控制;两颗 1600 万像素摄像头分别拍摄左右页;Raspberry Pi Pico 管理两组 NFC 读卡器;实体按键、旋钮和语音提示承担全部交互。使用者不需要触摸屏,也不必在扫描过程中操作手机。
先看懂整套系统如何工作

系统硬件框图
每次按下启动键,两颗摄像头采集打开书本的左右页,两块各含 20 颗 LED 的灯板以较低角度照亮纸面,尽量减少玻璃反光。图像交给 Raspberry Pi 5 处理,RapidOCR 在本机提取文字,Page Ingestor 再整理段落、断词和跨页句子,随后 Google Cloud Text-to-Speech 将文本转换为音频,并通过内置扬声器播放。

从按键到语音输出的处理顺序
作者没有把识别结果简单地逐页保存。扫描内容会按书籍分别管理,并被划分为大约 10 至 20 页的段落组;检测到章节边界时,系统尽量在章节处结束当前分组。Gemini 为完成的分组生成摘要,再由语音合成服务读出。

两类摘要功能:Recent Pages 关注最近阅读内容,Story So Far 汇总目前为止的整本书进度
设备能处理哪些书
当前软件内置德语和美式英语配置。其他语言原则上也可以增加,但必须同时具备相应的 OCR 与语音服务支持,并修改软件配置。
扫描区域面向每页不超过 160 × 240 mm 的书籍。原文还要求文字距离书脊内侧至少约 9 mm;如果平装书装订很紧、内边距过小,靠近书脊的文字可能被页面弯曲遮挡,或者落到稳定成像区域之外。

NFC 标签贴在书籍后封面的内侧。标签 UID 用作系统中的书籍标识
每本书都需要一枚 NFC 标签。系统用标签 UID 建立独立目录,把该书的识别文本、阅读记录和摘要放在一起,因此读者可以在多本书之间切换,之后再继续扫描。项目支持 ISO 14443A 与 ISO 15693;作者更推荐读取距离较长的 ISO 15693 标签。
主要硬件与材料
| 模块 |
项目原文配置 |
| 主控 |
Raspberry Pi 5 4GB 与官方主动散热器 |
| 图像采集 |
2个 Arducam IMX519 1600万像素相机,配140度M12广角镜头 |
| 页面照明 |
2块定制LED板,每块20颗LED,由MOSFET独立控制 |
| 交互 |
3个实体按键、EC11旋转编码器及内置按键、扬声器 |
| 书籍识别 |
Raspberry Pi Pico加2个PN5180读卡器,支持ISO 14443A和ISO 15693标签 |
| 音频 |
MAX98357A I2S功放与无源扬声器 |
| 结构 |
PLA打印外壳、两块4 mm玻璃、M2 M2.5 M3紧固件 |
| 软件 |
RapidOCR本地识别,Google Cloud TTS语音合成,Gemini生成摘要 |
物料表还列出了定制的树莓派扩展板、控制面板、旋钮板、两块长 LED 板、PN5180 适配板和继电器板,以及 10 芯排线、IDC 插头、JST XH 插头、FQP30N06L MOSFET、470 μF 电解电容、CD4093、1N5819、2N7000 和继电器等元件。
12 个制作步骤
第一步:了解阅读流程与书籍要求
首先确认设备的基本流程:放置已贴 NFC 标签的书,按启动键,等待双页拍摄与文字处理,听取左右页内容;需要回顾时,再使用两个摘要按键。等待第一段音频生成期间,设备会周期性播放提示音,让使用者知道请求已经被接受。
制作前先检查常用书籍的页面尺寸、内侧留白和语言。标签应固定在后封面内侧。若希望提高隔着纸张和玻璃识别的稳定性,原文建议选择 ISO 15693;如果还要兼容 ISO 14443A,则需要在后续步骤中更细致地调谐天线。
第二步:打印并组装外壳

两块分体式底板。由于整体尺寸较大,作者将底板拆成两个可打印部分
除两块玻璃外,外壳结构均采用 3D 打印。作者使用 Bambu Lab X1C 和 PLA。部分零件几乎占满打印平台,较大且较薄的零件应充分冷却后再取下,以免继续降温时发生翘曲。

带通风孔和安装位的侧面外壳零件。项目同时提供 Fusion 源文件、STL 和 3MF
玻璃厚度为 4 mm,物料表列出的两块尺寸分别为 162 × 244 mm 和 166 × 244 mm。作者收到的玻璃短边比标称值约长 1 mm,因此 front、front2、back 和 back2 提供普通版与 _dev 版。打印前应先实测玻璃。3MF 文件还预设了暂停点,用于在打印过程中嵌入 M2、M2.5 或 M3 螺母。

完成底部与侧板连接后的外壳内部,电子部件尚未安装
外壳使用 M2 和 M3 螺钉连接,完整装配关系可以参考仓库中的 abr.f3z。两端的山墙形结构各由内外两层组成,黑色的 front 和 back 先装入主体,两块玻璃从上方插入;木色 front2 和 back2 最后覆盖玻璃边缘并负责固定。
作者建议在电子部分安装、调试和相机对焦结束前,先不要装 front2 与 back2。这样可以随时抽出玻璃进入内部。此阶段玻璃没有被锁住,移动设备时必须防止其滑落。
第三步:制作控制面板并安装树莓派

控制面板由主按键板、EC11 旋钮小板和扬声器组成
较大的控制板安装三个瞬时按键与 10 针接口,小板安装 EC11 旋转编码器,两板之间用五根导线连接,扬声器也直接接入主板。焊接后要检查元件方向、焊点以及按键和旋钮是否能自由穿过外壳开孔。

安装完成的控制面板。三个按键采用不同尺寸,便于通过触摸区分

Raspberry Pi 5 与扩展板安装在底板上,官方主动散热器负责持续散热
先安装 Raspberry Pi 5 官方主动散热器,再用四根 M2.5 × 20 mm 支柱固定主板。OCR 会带来较高处理负载,外壳上的通风孔需要与散热器形成可交换空气的通道。
下一步会安装扩展板并遮挡相机接口,因此此时就要插入两根 22 针、200 mm、Type B 的 FFC 线。Type B 排线两端的裸露触点位于相反面,操作锁扣时要避免损坏细小塑料结构。
第四步:焊接并安装扩展板

扩展板正面:Raspberry Pi Pico、MAX98357A、IDC 接口、LED 接口和驱动元件集中在一块板上
扩展板连接控制面板、两套 PN5180 和两块 LED 板。板上还有 MAX98357A I2S 音频模块、Raspberry Pi Pico 以及两路高功率 N 沟道 MOSFET。焊接时要核对 Pico、MAX98357A、MOSFET、接口和有极性元件的方向。
检查完成后,将扩展板与 Raspberry Pi 5 的 GPIO 排针仔细对齐并压入,再用 M2.5 螺钉固定。相机排线不能被扩展板夹住。
第五步:布置 NFC 天线与 LED 灯板

0.5 mm 漆包铜线沿玻璃边缘形成单匝天线,图中红色箭头标出走线路径
每块玻璃周围布置一匝由 0.5 mm 漆包铜线制成的天线。铜线从前后端板的小孔穿过,短边贴着端板表面,上部长边跨过两块玻璃之间的夹角,下部长边藏在 LED 三角安装条后方。两端需要留出足够长度,之后连接相应的 PN5180。

两块长 LED 板位于玻璃下缘,以较低角度照亮纸面;图中还能看到摄像头和内部电子板
每块 LED PCB 接一根两芯线,另一端压接 2 针 JST XH 插头,并严格核对极性。左右三角支架用 M2 螺钉固定,安装前确认 NFC 铜线完全进入槽内,不能被支架压住。最后把灯板锁在支架上,并接到扩展板对应的左右 LED 插座。
第六步:改装 PN5180 读卡器

PN5180 板载天线的两处切断位置。改装不可逆,必须先核对原图
PN5180 模块自带的印刷天线读取距离不足,因此作者切断板载天线两端的 PCB 走线,刮开指定焊盘附近的阻焊层,露出铜箔并焊接外部天线接口。加热时间不能过长,以免铜皮翘起。

改装后的 PN5180、接口适配板与继电器板组合
两组大天线即使只有一组主动工作,也可能互相耦合。作者增加继电器接口板:一侧读卡器工作时,另一侧天线在电气上断开。继电器板使用继电器、CD4093 与相关元件。若只使用 ISO 15693,可安装 22 pF 调谐电容;若兼容 ISO 14443A,作者建议先装 18 pF,再在 C2 位置增加小电容完成后续调谐。
第七步:安装双摄像头并完成接线

两颗 IMX519 相机固定在底部支架上,以约 45 度角分别面对左右玻璃
镜头调焦环原本由少量胶固定,需要先用锋利刀片谨慎割开胶点,只切胶,不伤到细牙螺纹和附近元件。随后用 M2 螺钉固定支架,每颗相机用四颗螺钉装入支架,并连接预先铺设的 FFC 排线。

作者使用小台钳将 IDC 插头均匀压到 10 芯排线上
控制面板和两套 PN5180 共使用三根 10 芯排线,每根两端各压接一个 IDC 插头。带色标的导线应在两端都对应 1 脚,插头防呆键和应力释放结构方向也要一致。完成六个插头后,最好检查排线连续性,再分别接到扩展板和三个外设组件。
第八步:写入 Pico 固件并安装内部盖板
Pico 固件已经以 UF2 形式放在仓库的 hardware/pn5180_gateway/firmware/pn5180_gateway_pico.uf2。断开 Pico USB,按住 BOOTSEL 再连接电脑,出现 RPI-RP2 磁盘后,把 UF2 文件拖入。复制完成后磁盘自动消失并重启,属于正常现象,不需要额外编程器。

盖板安装前的内部布局:相机、灯板、读卡器、扩展板与排线均已就位
确认所有插头插紧、线缆没有被夹住后,再装两个内部电子盖板。Raspberry Pi 上方盖板会形成独立通风腔,外壳通风槽让主动散热器与外界交换空气。作者要求先完成通电检查,再固定盖板。
第九步:配置 Raspberry Pi 5
原文建议使用 Raspberry Pi OS Lite 64 位。用 Raspberry Pi Imager 写卡时创建用户、启用 SSH 并设置初始网络,首次启动后更新系统,再从仓库克隆项目并创建虚拟环境。
sudo apt update
sudo apt full-upgrade -y
sudo reboot
mkdir -p ~/src
git clone https://github.com/lhm0/accessible_book_reader.git ~/src/abr
cd ~/src/abr
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[ocr-rapidocr,dev,tts-google]"
启动配置还要启用两颗 IMX519 相机、连接 Pico 的 UART 和连接 MAX98357A 的 I2S,并在 /etc/asound.conf 中把 MAX98357A 配成默认 ALSA 设备。仓库中的 config.txt 只是参考,原文明确提醒不要直接覆盖现有 /boot/firmware/config.txt。
当前生产路径使用 Google Cloud Text-to-Speech 与 Vertex AI Gemini,因此需要建立启用计费的 Google Cloud 项目,开启 texttospeech.googleapis.com 和 aiplatform.googleapis.com,并配置 Application Default Credentials。凭据保存在项目目录之外,不能提交到 GitHub。
cd ~/src/abr
sudo deploy/install_language_switch.sh
sudo deploy/install_control_panel_service.sh
# 选择书籍语言
sudo abr-language de
# 或
sudo abr-language en
安装脚本会把控制程序注册为系统服务,使其开机启动并在 SSH 断开后继续运行。初次检查应确认两颗相机、Pico 网关、扬声器、语言配置和 abr-control-panel.service 均正常。
第十步:对焦并校正双摄像头

保留一块玻璃和测试页面,同时从另一侧伸手调节镜头
作者提供 camera_test_server.py,在局域网浏览器中显示实时画面。对焦一侧时,只装对应玻璃和一张细小高对比度文字页面,拆下另一块玻璃以便转动镜头。测试前暂时停止正常服务,并手动打开相应 LED 灯路。

相机测试服务器的浏览器画面,可边转动镜头边观察文字清晰度
相机 0 默认使用 8000 端口,相机 1 使用 8001 端口。镜头每次只转动很小角度,待画面稳定后再判断,完成后用少量胶固定。两颗相机都对好焦后不要再改变镜头、相机角度或高度,否则下一步生成的校准数据会失效。

仓库提供 160 × 240 mm 的 ChArUco 标定板,应以 100% 比例打印
140 度广角镜头会产生明显桶形畸变。由于相机位置固定,每颗相机只需用一张平面 ChArUco 图完成标定,随后把映射文件用于每次扫描。打印 calibration/out/charuco_160x240_a4.svg 时要关闭适应页面选项,并核对整板为 160 × 240 mm、单格为 20 × 20 mm。

相机直接拍摄的标定板,直线受到广角畸变影响
两侧分别保存全分辨率标定照片,再运行 calibrate_planar_charuco.py,生成 cam0_planar.npz、cam1_planar.npz 以及 detected 和 rectified 预览图。两个 NPZ 文件只适用于对应相机与当前机械位置;任何相机、焦距、角度或高度变化都需要重新标定。
第十一步:调谐天线并完成整机测试
停止正常服务并拆下 NFC 盖板。初始状态在 C1 装 18 pF、C2 留空,用 ISO 14443A 标签贴近玻璃中心,通过 Pico 网关 STATUS 命令检查识别,再以约 1 cm 步进把标签垂直移远,记录仍能可靠检测的最大距离。
断电后在 C2 增加约 2 pF,再重复测距,逐步找到最佳总电容。作者调谐后,ISO 14443A 可靠距离约为 8 cm;ISO 15693 视标签和方向不同,可能超过 15 至 20 cm。两套读卡器必须分别调整,任何电容更换都要在设备断电并拔掉电源时进行。
校准和调谐完成后,清洁玻璃内外侧并清除内部灰尘,最后装上 front2 与 back2 锁住玻璃。启动系统服务,放入已贴标签的书并按启动键。
测试时要确认左右页顺序正确、朗读内容与页面一致、旋钮能调节音量、再次按启动键能停止播放,并在积累足够页面后测试两个摘要按键。若异常,可查看 systemctl status 与 journalctl 日志。
第十二步:日常使用与现阶段效果

控制面板功能:大号启动键、两个摘要键和音量旋钮
- 读一组双页:放好打开的书并按启动键,处理完成后开始朗读;再次按启动键停止。
- 识别书籍:NFC 标签贴在后封面内侧,系统用标签 UID 关联该书的页面和摘要。
- 调节音量:在音频播放时旋转 EC11。
- Story So Far:按摘要键 1,按时间顺序汇总目前已扫描的全书内容。
- Recent Pages:按摘要键 2,总结最近完成的分组与之后尚未归档的页面。
- 删除一本书的数据:同时按启动键和两个摘要键,听取语音说明,再按 EC11 内置按键确认;按任一功能键可以取消。
删除操作会移除该书保存的页面、阅读记录和摘要,适合需要从头重新扫描并重建摘要时使用。
作者表示,当前样机已经实现无需屏幕的触觉操作、自动书籍识别、双页 OCR 与语音播放,正常条件下文字识别错误相对较少。项目仍在持续开发,重点包括长期测试以及摘要层的稳定和优化。
目前从按下启动键到开始播放大约需要 25 秒,期间的心跳提示音用于反馈处理仍在进行。主要限制来自 Raspberry Pi 5 的图像预处理与 OCR 性能。作者比较后继续采用成本较低的 Google 标准语音,因为其效果优于测试过的离线方案,而更自然的云端语音成本明显更高。