手机拍灯为什么有一条条黑纹?PWM 240Hz 实测

同一块 240Hz PWM 屏幕,1/2000 快门能拍到 4 条暗带。

把快门拖到 1/60,暗带变成 0 条,频闪指数还是 50.0%。

黑纹不是灯坏了,是相机逐行读出撞上了 PWM 的亮灭周期。

在线案例与源码:gitcode.com/OPCTeam/dem... 成品是一个 index.html,双击就能打开,不连网,不装依赖。

一、先看结果:240Hz 屏幕,快门一换暗带就消失

页面默认 240Hz、50% 占空比、1/2000 快门。

相机取景器里是 4 条横向暗带。

右侧指标卡同时给出频闪指数 50.0%、暗带 4 条。

我把快门从 1/2000 拖到 1/60,暗带归零。

频闪指数没有变,仍然是 50.0%。

这说明光没有变,变的是每一行像素的积分窗口。

手机拍屏幕出现条纹,经常被解释成"快门太快"。

这句话只对了一半。

快门快,单行曝光短,容易撞上亮灭瞬间。

快门慢到正好覆盖整数个周期,条纹也会消失,但频闪并没有消失。

这个页面把两种情况都摆在同一屏,让你自己拖出来。

二、为什么值得看:条纹是卷帘快门和 PWM 撞在一起

搜"手机拍屏幕 条纹",出来最多的是手机广告和"快门调慢一点"的结论。

很少有人把光源波形、手机面板和相机取景器放在同一屏。

更少有人告诉你,暗带条数不等于频闪频率。

240Hz 的光源,在 15ms 读出里只跨 3.6 个周期。

所以画面里是 4 条暗带,不是 240 条。

这个页面就是用来拆开这层关系的。

它不判断某块屏幕伤不伤眼。

它只回答一件事:同样的光,为什么换个快门,相机看到的结果完全不同。

三、模型怎么跑:420 行传感器,逐行算积分

整个页面是一个 1600×1000 的单文件 index.html。

没有 CDN,没有外部字体,没有图片依赖。

绘图全部走 Canvas。

光源用 lightAt(t) 生成矩形波。

给定频率和占空比,任意时刻的亮度只有 0 或 1。

相机的卷帘读出用 sampleRowProfile 模拟。

它把 15ms 读出时间切成 420 行。

每一行从自己的起始时刻开始,积分一个快门窗口。

窗口内亮的时间占比,就是这一行的平均亮度。

暗带用 darkBandSegments 统计。

先取整列亮度的最小值,再加 36% 的峰谷差作为阈值。

低于阈值的连续行算一条暗带。

频闪指数用 flickerIndex 计算。

采样 6 个周期、4096 个点。

高于平均值的面积除以总面积,就是频闪指数。

混叠判断在 aliasInfo 里。

快门时间除以光源周期,如果接近整数倍,就标记为混叠。

页面把这条判断显示在指标区,避免你看图得出反结论。

四、实测:15ms 读出跨 3.6 个周期,所以是 4 条不是 240 条

我把几组常用参数跑了一遍,数据如下。

光源 快门 快门除以周期 暗带 频闪指数
240Hz / 50% 1/2000 0.120 T 4 条 50.0%
240Hz / 50% 1/250 0.960 T 4 条 50.0%
240Hz / 50% 1/125 1.920 T 4 条 50.0%
240Hz / 50% 1/60 4.000 T 0 条 50.0%
480Hz / 50% 1/2000 0.240 T 7 条 50.0%
480Hz / 50% 1/250 1.920 T 8 条 50.0%
1440Hz / 50% 1/2000 0.720 T 22 条 50.0%
DC 恒流 任意 无周期 0 条 0.0%

240Hz 的周期是 4.167ms。

15ms 读出除以 4.167ms,等于 3.6。

所以画面里出现 4 条暗带,边缘那条只覆盖了半个周期。

480Hz 的周期是 2.083ms。

15ms 跨 7.2 个周期,暗带落在 7 到 8 条之间。

换快门相位,边缘那条会多切出一段。

1440Hz 的周期是 0.694ms。

15ms 跨 21.6 个周期,暗带变成 22 条。

这就是为什么高频 PWM 的条纹更密。

不是频率越高越容易拍出来,是同样读出时间里周期更多。

我点了"跑 5 组对照"。

页面计时 0.60ms,五组结果是 4、7、22、4、0 条。

自检面板是 8/8 PASS,用时 0.40ms。

其中一条自检专门测占空比。

10% 占空比的频闪指数是 0.9001。

90% 占空比的频闪指数是 0.1003。

这组数字有点反直觉。

占空比越低,灯越暗,频闪指数反而越高。

因为频闪指数看的是波形不对称程度,不是亮度。

10% 占空比时,只有 10% 的时间是亮的,平均值被拉得很低,亮的部分离平均值很远。

五、验证与踩坑:1/60 快门把 4 条暗带抹成 0

这是我最想让你看的一张图。

光源仍然是 240Hz、50% 占空比。

快门从 1/2000 拖到 1/60。

1/60 是 16.667ms,正好等于 4 个 PWM 周期。

每一行都完整覆盖 4 个亮灭循环,平均亮度都是 50%。

于是暗带变成 0 条。

指标区的频闪指数还是 50.0%。

页面弹出黄色警告:"读数可能被混叠欺骗"。

下面一行写得很具体:"快门 1/60 ≈ 4 × 周期 4.167 ms"。

如果你只看相机取景器,会得出"这盏灯没有频闪"的结论。

这和 50.0% 的频闪指数正好相反。

我把这个状态当作失败路径截图保留下来。

复现方法很简单。

保持 240Hz 和 50% 占空比,只把快门拉到最左边的 1/60。

看暗带是否归零,警告是否出现。

自检里还有一条 1/120 快门整数倍混叠。

它算出的比值是 2.0000,判定倍数是 2。

但 UI 的快门档位里没有 1/120。

最接近的是 1/125,比值 1.920 T。

1/125 不会触发混叠,暗带仍然是 4 条。

所以想看到可见的混叠,用 1/60 最直接。

这也是页面自检和 UI 档位之间的一处边界。

自检测的是公式,不是每一个 UI 档位都能复现。

六、它不是真实相机测试

这个页面没有接相机,也没有拍真实屏幕。

所有亮度曲线都来自矩形波模型。

真实 PWM 有上升沿、下降沿和过冲。

真实相机有噪声、去马赛克、自动曝光和抗频闪算法。

有些手机会自动把快门调到 1/100 或 1/120 来避开频闪。

有些屏幕用 DC 调光,有些用高频 PWM,还有些混着两种方案。

页面里的 15ms 读出、420 行传感器,都是可调的教学参数。

真实手机的读出时间、行数和曝光策略各不相同。

所以它适合用来理解机制。

别拿它给某块屏幕下"伤眼"或"护眼"的结论。

七、准备环境:码道 Web 与本地复现

浏览器打开码道 Web 版:devcloud.cn-north-4.huaweicloud.com/chat?source...

码道有三种使用方式:WebUI(浏览器对话)、TUI(终端命令行)和桌面 IDE(IDE 插件)。本文用 WebUI 版演示。

下载 index.html 后,可以直接双击打开。

也可以在当前目录起一个静态服务:python -m http.server 8000,再打开 http://localhost:8000/index.html。

按这个顺序点,能复现本文的数字:

  1. 保持 240Hz、50% 占空比、1/2000 快门,看暗带 4 条。
  2. 点"跑 5 组对照",看结果 4、7、22、4、0 条。
  3. 把快门拉到 1/60,看暗带归零和混叠警告。
  4. 切到 1440Hz,保持 1/2000,看暗带变成 22 条。
  5. 切到 DC,看暗带和频闪指数同时归零。

自检面板 8/8 PASS。

失败路径提示原文:读数可能被混叠欺骗。

480Hz 也值得单独看一眼。

同样 15ms 读出,它跨 7.2 个周期。

把快门放到 1/250,暗带是 8 条。

八、直接下载试玩

这个 Demo 已经完整开源,源代码、本文档和全部截图都在公开仓库:

进入 codearts-pwm-flicker-lab 文件夹,把 index.html 下载到本地,用浏览器打开即可运行。

九、使用码道体会

需求里我把验收条件写死了。

1600×1000、单文件、无外部依赖、8 条断言、5 组对照、混叠警告。

页面把这些都做出来了,而且把自检结果直接渲染在界面上。

我做的事不是替它写循环,而是把"什么算对"写成可执行的数字。

平均亮度要在 0.5000 上下,10% 占空比的频闪指数要接近 0.9,DC 必须是 0 条暗带。

这些条件越具体,验收越省事。

真正需要我自己判断的是失败路径。

自检全绿不代表每个 UI 档位都能触发混叠。

我把快门拖到 1/60,才看到暗带归零和黄色警告。

这也是我建议每个读者亲手点一遍的地方。

十、下一步

还缺三块。

一是真实相机样张对照。

同一块屏幕,用 1/60、1/125、1/2000 各拍一张,和页面预测并排。

二是更真实的光源波形。

加上上升沿、下降沿和幅度调制,看看频闪指数会怎么变。

三是把逐行亮度导出成 CSV。

方便拿真实相机的行亮度曲线做误差对比。

仓库地址在文章开头,拿去改。

附录:复现用需求

下面是我用来生成这个页面的需求,和页面实际实现一致,可以直接复制:

text 复制代码
用单文件 index.html 做一个中文的「PWM 频闪实验室」,纯前端、无任何外部依赖和 CDN,用 Canvas 绘图,深色科技风,桌面 1600x1000 好看。

核心功能:模拟手机屏幕的 PWM 调光和相机卷帘快门。控件包括调光方式(DC 恒流、240Hz、480Hz、1440Hz PWM)、占空比 5% 到 95%、快门 1/60 到 1/4000、卷帘读出 5ms 到 30ms。

模型:PWM 光源输出矩形波;相机 420 行逐行读出,每行从不同相位开始积分一个快门窗口,窗口内亮的时间占比就是该行平均亮度;暗带按整列亮度最小值加 36% 峰谷差做阈值统计;频闪指数按高于平均值的面积除以总面积计算,采样 6 个周期、4096 个点;快门时间除以光源周期接近整数倍时标记为混叠。

界面布局:左侧光源控制;中间上方是手机发光面板;中间右侧是相机取景器;下方左侧是实时指标和自检面板;下方中间是 PWM 波形和逐行曝光曲线;下方右侧是 5 组对照表和暗带柱状图。

还要有:一键「跑 5 组对照」,固定比较 240Hz 50%、480Hz 50%、1440Hz 50%、240Hz 10%、DC 五组;一个 8 条断言的自检面板,例如 50% 占空比平均光量 0.5000、10% 占空比频闪指数 0.9、DC 零频闪、1/120 快门整数倍混叠、1/480 半周期安全、15ms 读出跨 3.6 个周期、逐行亮度在 0 到 1 之间、5 组对照矩阵完整,每条显示 PASS 或 FAIL 和实际值;快门下接近周期整数倍时显示中文混叠警告。

交互要顺滑,数字用等宽字体,所有文案中文。完成后打开预览,让我直接看到运行效果。
相关推荐
wangruofeng5 小时前
AI Models 1.1.0 发布,查大模型价格、对比模型和找 API 地址
前端·aigc·ai编程
wangruofeng5 小时前
给前端开发者的 100 个设计参考网站
前端·设计
星栈8 小时前
视频即代码,Remotion 能做什么、不能做什么
前端·音视频开发
广州华水科技8 小时前
单北斗GNSS位移监测系统的应用与技术解析
前端
用户47949283569158 小时前
从一句话或代码仓到可交互 HTML:开源 Agent 画图技能 Archify v3.2 实测与选型边界
前端·后端·面试
风骏时光牛马11 小时前
生成一个AI多模态标题,仅输出一条标题,无额外文字、问句、备选、配图、文案等任何附加内容,不需要其他的任务服务 只要标题。
前端
wangruofeng11 小时前
从 GIF 到 AVIF:网页图片格式演进与 2026 年选型指南
前端·架构
清晨Coding12 小时前
为什么用 React Developer Tools 查看组件树这么乱?
前端·react.js
鶴哥只手遮天13 小时前
《Electron 45.2.3 内核解剖》第 4 章 补丁体系:380 个补丁改了什么
前端·electron