本项目在 Windows 上使用 Python 实现一个可见光数据通信模拟系统,包含发射端、接收端、本机 TCP 校准流程、默认测试素材、本地网页界面和桌面 GUI。发射端可以配置为薄膜 PPLN 波导激光变频器或者普通调色 RGB LED,接收端使用常规工业相机参数进行模拟,并支持自动寻找发射光斑、背景去除、字符串还原以及文件恢复。
版本说明
v1:保留原有完整可靠通信链路,对应入口为app.py、desktop_app.py、one_click_test.ps1、one_click_test.bat,核心实现位于vlc_sim/。v2:新增的快速文本通信链路,对应入口为app_v2.py、desktop_app_v2.py、one_click_test_v2.ps1、one_click_test_v2.bat,核心实现位于vlc_fast/。v1与v2并行存在,互不替换。需要稳定文件传输、压缩、CRC、Reed-Solomon 与 bundle 时使用v1;需要更快的文本聊天演示时使用v2。
v2 快速模式概览
v2 面向“尽量快、尽量实时”的文本通信场景,和 v1 的设计目标不同:
- 去掉 CRC、Reed-Solomon 和时间码联合调制,只使用 RGB 颜色和亮度承载符号。
- 使用
4种颜色和4档亮度,共16个状态,即每符号4 bit。 - 在通信前根据背景亮度、运动强度和接收帧率自适应选择重复帧数与有效符号率。
- 根据接收帧率自动切换不同档位策略,当前已包含
standard_30fps、balanced_45fps、high_fps_60fps、ultra_90fps四类适配档位。 - 接收端支持自动光斑搜索、自适应背景抑制、自动速率匹配和可选 GPU / ONNX 路径。
- 对真实视频路径,接收端会自动评估多个候选光斑中心并选择得分最高的路径;对模拟器视频则会切到 sidecar 引导的低扰动解码模式。
- 对模拟器自己生成的
mp4,若存在同名mp4.jsonsidecar,会自动使用其中的发射位置和重复帧先验,避免稳像和跟踪引入额外漂移。 v2CLI、Gradio 和桌面 GUI 现在都提供独立的状态面板,直接显示当前链路档位、接收模式、检测中心、重复帧和置信度。
v2 模式切换
v2 现在提供显式 link_mode,可在 CLI、Gradio 和桌面 GUI 中切换:
short_chat:默认模式,适合短文本和更快的演示路径,header_repeats与payload_symbol_repeats最低。long_text:为较长文本增加冗余,自动提高头部重复和 payload 重复次数,并偏向更稳的repeat_frames。real_camera:面向真实摄像头或 sidecar 被移除的视频回归,采用更保守的频率/重复帧策略,并默认启用多候选中心搜索。
这三种模式会直接影响:
- 校准阶段选择的
minimum_repeat_frames - 头部重复次数
header_repeats - 载荷重复次数
payload_symbol_repeats - 状态面板中的
effective_payload_bps
当前默认 v2 演示背景为 test3.mp4,默认投射位置为 x=1000, y=300。
功能概览
- 发射端输入字符串后,先经过压缩和前向纠错,再映射到颜色、亮度和时间频率联合调制的可见光序列。
- 发射端支持文本消息和任意文件输入,文件在发送前会按固定大小分片,并在接收端自动重组恢复。
- 对于较长文件,发射端支持按时长上限自动拆分为多段视频 bundle,并在接收端按清单顺序自动恢复。
- 发射端将可见光序列以逼真的方式渲染到任意固定机位背景视频上,默认背景是当前目录的
test1.mp4。 - 接收端对视频逐帧分析,自动寻找发射位置,并提供稳像、光流跟踪、经典分割和可选 ONNX AI 分割增强模式;默认走轻量路径,最终还原出原始字符串或文件。
- 发射端和接收端在发送前通过 127.0.0.1 上的 TCP 校准流程协商链路参数,选择吞吐量和稳健性之间最优的配置。
- 提供 Gradio 本地网页界面、Tkinter 桌面 GUI 和命令行入口,方便测试与演示。桌面 GUI 现已支持进度条、取消任务和首帧预览。
- 桌面 GUI 还支持直接打开最新输出文件或所在目录,并显示更清晰的阶段日志,方便本机通信联调。
光源模型与常见频率范围
1. 薄膜 PPLN 波导激光变频器
- 模拟可见输出范围:约 430 nm 到 680 nm。
- 工程上常见的外部电驱调制量级可以达到约 1 kHz 到 100 kHz,具体取决于激光器、驱动器和调制链路。
- 本项目中的视频模拟受限于相机帧率,因此真正进入视频解调的有效调制频率被映射为低频离散时间码,保证普通工业相机可以观测到。
2. 普通调色 RGB LED
- 模拟可见输出范围:约 450 nm 到 650 nm。
- 常见单片机 PWM 调光频率通常在约 500 Hz 到 20 kHz,取决于 MCU 定时器、驱动管和亮度要求。
- 本项目同样把高频硬件调制折算成相机可观测的离散时间亮度变化,用于生成和还原视频中的发光轨迹。
算法设计
1. 校准与匹配
发射端和接收端先通过本机 TCP 进行校准。接收端根据相机帧率、噪声和模糊参数,对若干候选链路配置打分,返回最优配置。当前候选集合主要调整如下参数:
- 每个符号占用多少帧。
- 可用的时间码集合。
- 固定的强度等级和 Reed-Solomon 纠错强度。
评分函数优先保证以下条件:
- 时间码最高频率低于接收端 Nyquist 安全边界。
- 不超过发射源常见硬件调制能力。
- 在满足稳健性的前提下优先更高吞吐量。
2. 数据压缩与纠错
文本或文件发送前执行以下处理:
- 使用 UTF-8 编码。
- 使用 zlib 进行无损压缩。
- 追加 CRC32 校验。
- 使用 Reed-Solomon 进行前向纠错。
这样可以在解码端对一定数量的符号误差进行恢复,同时用 CRC 防止错误内容被误判为成功解码。文件负载会额外附带文件名、媒体类型、分片大小、分片总数和 SHA256 校验。
3. 联合调制
一个发光符号由三部分共同承载信息:
- 颜色维度:4 个高区分度颜色索引。
- 亮度维度:2 个强度等级。
- 时间维度:4 个时间码,内部由频率和相位组合形成。
因此一个符号携带 5 bit 信息。时间码使用窗口内的离散正弦变化,接收端通过匹配滤波和整符号模板匹配进行识别,从而在时间域和频率域都携带数据。
4. 发射端场景渲染
为了让视频更接近真实场景投射,本项目没有简单地直接叠加纯色圆点,而是做了以下处理:
- 使用高斯核构建核心光斑和外扩 bloom,但对中心信号强度保留单独下限,避免真实感增强后影响解码稳定性。
- 使用局部灰度、颜色相似性和模糊趋势估计纹理权重,让光斑贴合墙面、地面、建筑表面等近场承载区域。
- 对高处天空、远景山体、低纹理蓝色区域和雾化区域施加抑制,避免出现明显不真实的远处整块投光。
- 支持
classical_surface投射模式和可选depth_surface模式;后者可结合深度 ONNX 模型进一步压制远景区域。 - 使用局部亮度增益和加性发光混合,保留背景细节和表面起伏,并通过羽化边缘消除突兀方块感。
- 最后叠加相机模糊、噪声和色彩增益,模拟工业相机成像差异。
5. 接收端自动目标定位与解算
接收端默认不需要手工指定光斑位置,会自动完成以下步骤:
- 读取视频前段帧序列。
- 下采样后计算时间中值背景。
- 统计各像素相对于背景的时变能量。
- 对模拟器生成的视频,优先读取同名
mp4.jsonsidecar 中的发射位置作为先验;对真实录像则取能量峰值作为发射器位置初值。 - 在该位置周围建立高斯 ROI 和环形背景区域。
- 可选地先执行全局稳像,再在局部窗口内进行经典分割或 ONNX 分割。
- 对光斑位置执行光流跟踪,得到逐帧中心点。
- 用 ROI 均值减去环形背景均值,得到净发光信号。
- 搜索符号起始帧偏移。
- 用匹配时间码、颜色向量和强度等级方式解码头部和载荷。
这个方案不依赖大型 GPU 模型,适合普通 PC 在几分钟内处理 10 秒量级的视频。默认实现偏向 CPU 友好。如果后续需要引入更重的 AI 开源模型,比如基于分割网络的目标掩码提取或者视频目标跟踪,也可以在当前结构上继续扩展。
代码结构
app.py:命令行和本地网页界面入口。desktop_app.py:Tkinter 桌面 GUI。app_v2.py:v2 命令行和本地网页界面入口。desktop_app_v2.py:v2 Tkinter 桌面 GUI。one_click_test.ps1:一键默认参数通信测试脚本。one_click_test.bat:面向双击或 CMD 环境的一键测试入口。one_click_test_v2.ps1:v2 一键快速文本通信测试脚本。one_click_test_v2.bat:v2 双击版一键测试入口。TECHNICAL_DETAILS.md:扩写后的技术说明文档,包含字符A的完整编码与解码示例。vlc_sim/payload.py:文本/文件统一封装、分片元数据和重组恢复。vlc_sim/ai.py:ONNX 模型下载、分割推理与深度估计。vlc_sim/models.py:源、相机和链路配置数据结构。vlc_sim/calibration.py:本机 TCP 校准流程。vlc_sim/codec.py:压缩、纠错、符号映射与时间码。vlc_sim/render.py:场景光斑渲染与相机模拟。vlc_sim/transmitter.py:发射端视频生成。vlc_sim/receiver.py:接收端自动定位与解码。vlc_fast/models.py:v2 设置、链路配置和结果结构。vlc_fast/protocol.py:v2 的 16 状态快速符号协议。vlc_fast/calibration.py:v2 自适应速率拟合与后端选择。vlc_fast/transmitter.py:v2 快速发射视频生成。vlc_fast/receiver.py:v2 自动定位、同步和文本恢复。
安装
当前目录已经按以下依赖实现:
numpyopencv-python-headlessgradioreedsoloonnxruntimepillow
如果需要重新安装,可以在当前虚拟环境中执行:
g:/toys/.venv/Scripts/python.exe -m pip install numpy opencv-python-headless gradio reedsolo onnxruntime pillow
启动网页界面
g:/toys/.venv/Scripts/python.exe app.py ui --port 7860
启动后打开本机 Gradio 页面,界面包含三个标签页:
- 校准:模拟发射端和接收端在 127.0.0.1 上通过 TCP 选出链路参数。
- 发射端:输入字符串或文件,选择背景视频和投射坐标,生成带可见光通信序列的 mp4。
- 接收端:读取 mp4 或 bundle 清单,自动定位光斑并解码字符串或恢复文件。
- AI 模型:下载可选的 ONNX 分割模型,或直接下载默认深度模型。
启动 v2 网页界面
g:/toys/.venv/Scripts/python.exe app_v2.py ui --port 7861
v2 网页界面包含 4 个标签页:
v2 自适应校准:根据背景视频和接收参数估计repeat、有效符号率和当前计算后端。v2 发射端:直接把文本编码成 RGB + 亮度快速链路并渲染视频。v2 接收端:自动寻找光斑并恢复文本消息。v2 AI 模型:下载可选 ONNX 模型,供背景抑制 / 中心微调用。
启动桌面 GUI
g:/toys/.venv/Scripts/python.exe desktop_app.py
桌面 GUI 使用 Tkinter 构建,适合本机演示,不依赖浏览器。
启动 v2 桌面 GUI
g:/toys/.venv/Scripts/python.exe desktop_app_v2.py
v2 桌面 GUI 提供独立的校准、发射和接收工作页,默认围绕 test3.mp4 与 1000,300 的快速文本链路设计。
桌面 GUI 当前支持:
- 发射、接收、校准三个工作页。
- 后台线程执行任务,避免窗口卡死。
- 进度条与状态文本。
- 取消当前任务。
- 自动显示输出视频首帧预览。
- 一键打开最新输出文件或输出目录。
- 分阶段执行日志,便于确认校准、渲染、解码是否正常推进。
- 文件传输时可直接生成 bundle 清单并在接收端载入。
命令行示例
发射端
g:/toys/.venv/Scripts/python.exe app.py transmit --message "hello visible light" --background test1.mp4 --output outputs/transmission.mp4 --source-type rgb_led --x 900 --y 120
文件发射端
g:/toys/.venv/Scripts/python.exe app.py transmit --message "payload file" --input-file tips.txt --background test1.mp4 --output outputs/file_transfer.mp4 --source-type rgb_led --x 900 --y 120 --chunk-size 32
多分卷文件发射端
g:/toys/.venv/Scripts/python.exe app.py transmit-bundle --input-file tips.txt --background test1.mp4 --output-manifest outputs/tips_bundle.json --source-type rgb_led --x 900 --y 120 --chunk-size 32 --max-volume-seconds 10
接收端
g:/toys/.venv/Scripts/python.exe app.py receive --video outputs/transmission.mp4 --source-type rgb_led --output-dir recovered
v2 长文本模式
g:/toys/.venv/Scripts/python.exe app_v2.py transmit --link-mode long_text --message "v2 long text demo" --background test1.mp4 --output outputs/test1_v2_long.mp4 --x 900 --y 120 --parse-fps 24 --frequency 24 --min-frequency 4 --max-frequency 120 --spot-radius 110 --blur 0.32 --noise 0.25 --processing-scale 0.65 --prefer-gpu
g:/toys/.venv/Scripts/python.exe app_v2.py receive --link-mode long_text --video outputs/test1_v2_long.mp4 --parse-fps 24 --frequency 24 --min-frequency 4 --max-frequency 120 --spot-radius 110 --blur 0.32 --noise 0.25 --processing-scale 0.65 --output-dir recovered_v2_test1_long --candidate-search-count 6 --prefer-gpu
v2 真实摄像头风格回归
g:/toys/.venv/Scripts/python.exe tools/run_v2_real_camera_regression.py --preset simulated_real_test3 --background test3.mp4 --message "real camera t3" --x 1000 --y 300 --simulate-real-camera
可用预设保存在 tools/v2_real_camera_presets.json,当前包含:
webcam_30fpsindustrial_60fpssimulated_real_test3
多分卷接收端
g:/toys/.venv/Scripts/python.exe app.py receive-bundle --manifest outputs/tips_bundle.json --source-type rgb_led --output-dir recovered_bundle
如需启用增强解析路径,可以按需增加:
g:/toys/.venv/Scripts/python.exe app.py receive --video outputs/transmission.mp4 --source-type rgb_led --output-dir recovered --segmentation-mode classical --tracker-mode optical_flow
下载 ONNX 分割模型
g:/toys/.venv/Scripts/python.exe app.py download-ai-model --url "https://example.com/segmenter.onnx" --output models/segmenter.onnx
下载默认深度模型
g:/toys/.venv/Scripts/python.exe app.py download-depth-model --output models/depth_anything_v2_small.onnx
v2 命令行示例
v2 自适应校准
g:/toys/.venv/Scripts/python.exe app_v2.py calibrate --background test3.mp4 --parse-fps 30 --frequency 90 --min-frequency 30 --max-frequency 240 --spot-radius 96 --processing-scale 0.5 --prefer-gpu
v2 发射端
g:/toys/.venv/Scripts/python.exe app_v2.py transmit --message "v2 快速光通信测试" --background test3.mp4 --output outputs/transmission_v2_fast.mp4 --x 1000 --y 300 --parse-fps 30 --frequency 90 --min-frequency 30 --max-frequency 240 --spot-radius 96 --blur 0.35 --noise 0.35 --processing-scale 0.5 --prefer-gpu
v2 接收端
g:/toys/.venv/Scripts/python.exe app_v2.py receive --video outputs/transmission_v2_fast.mp4 --parse-fps 30 --frequency 90 --min-frequency 30 --max-frequency 240 --spot-radius 96 --blur 0.35 --noise 0.35 --processing-scale 0.5 --output-dir recovered_v2 --candidate-search-count 6 --prefer-gpu
下载 v2 可选 AI 模型
g:/toys/.venv/Scripts/python.exe app_v2.py download-ai-model --url "https://example.com/segmenter.onnx" --output models/segmenter.onnx
启用真实投射模式
g:/toys/.venv/Scripts/python.exe app.py transmit --message "hello realism" --background test1.mp4 --output outputs/transmission_realistic.mp4 --source-type rgb_led --projection-mode classical_surface --x 900 --y 120
如需进一步利用深度先验抑制远景区域,可以改用:
g:/toys/.venv/Scripts/python.exe app.py transmit --message "hello realism" --background test1.mp4 --output outputs/transmission_depth.mp4 --source-type rgb_led --projection-mode depth_surface --depth-model models/depth_anything_v2_small.onnx --x 900 --y 120
一键默认通信测试
powershell -ExecutionPolicy Bypass -File .one_click_test.ps1
或者在 cmd.exe / 资源管理器里直接运行:
one_click_test.bat
这个脚本会使用默认背景与默认投射位置 900,120,并采用内置的稳定烟测参数组合,以字符串 你好,栗子树 进行一次完整的发射和接收测试,并自动校验恢复结果是否一致。
一键 v2 快速通信测试
powershell -ExecutionPolicy Bypass -File .one_click_test_v2.ps1
或者在 cmd.exe / 资源管理器里直接运行:
one_click_test_v2.bat
这个脚本会固定使用 test3.mp4、投射位置 1000,300、parse-fps=30、目标频率 90 Hz、光斑半径 96 px,并验证字符串 v2 快速光通信测试 是否能被完整恢复。当前默认自适应结果会选择 repeat=2,对应有效符号率 15 Hz,有效载荷速率约 60 bps。
默认测试方法
开发完成后的默认测试素材为当前目录下的 test1.mp4。建议用下面的流程做一次完整联调:
- 运行发射端,将一段短字符串或文件投射到
test1.mp4上。 - 记录生成的视频路径,比如
outputs/transmission.mp4或outputs/file_transfer.mp4。 - 运行接收端,对该视频进行自动检测、稳像和解码。
- 检查终端或者界面中输出的字符串是否与原始输入一致,或者确认恢复目录中的文件校验正确。
如果你希望直接走内置冒烟测试,可以运行 one_click_test.ps1 或 one_click_test.bat。更详细的编码、调制、同步、解调与纠错过程说明见 TECHNICAL_DETAILS.md,其中还包含整体流程图和字符 A 的时序示意图。
性能与限制
- 当前实现面向固定机位视频,已增加轻量级全局稳像和局部光流跟踪,但不等价于专业级稳像工具链。
- 默认接收算法是 CPU 友好的时域和色域联合分析;ONNX 分割属于可选增强路径。
depth_surface模式会在发送端额外执行 ONNX 深度估计,真实感更好,但生成速度会明显慢于经典模式。- 默认接收会以 0.5 倍比例缩放视频做解析,以降低 1080p 长视频的处理开销;这不会影响模拟视频的 sidecar 引导解码。
- 如果视频分辨率较高、发射点太小或者背景运动过强,建议增大光斑半径、降低符号率,或者提高相机帧率参数。
- 更长的消息会生成更长的视频,因为系统会循环背景视频直到完整承载所有符号。
- 对于文件传输,当前建议把单分片大小控制在 16 到 64 bytes 之间,以换取更稳的恢复率。
- 多分卷模式适合较长文件,但整体生成时间与视频长度成正比,建议先用较小测试文件验证参数。