别人凑过来,屏幕自己藏起来
本地人脸识别 · 非主人入镜自动模糊全屏 · 数据不出本机
PrivacyScreenGuard · Camera Privacy Guard
| 设备选择与快捷启动 | 遮罩外观与健康提醒 | 更新与隐私数据 |
|---|---|---|
![]() |
![]() |
![]() |
PrivacyScreenGuard 是一款 Windows 桌面「摄像头隐私屏」(WPF,.NET 8)。它用摄像头在本地识别坐在屏幕前的是不是你:一旦有陌生人入镜,立刻把整块屏幕模糊遮住;主人回到镜头前,遮罩自动解除。
全程本地推理,不上传、不录制、不保存任何画面。
| 🔒 本地优先 | 🖥️ 多屏覆盖 | ⚡ 自动响应 | 💾 加密存储 |
|---|---|---|---|
| 人脸检测与比对全部在本机 CPU 完成,画面不离开内存 | 全部显示器 / 仅主屏 / 指定屏三种守护范围 | 非主人入镜约 500ms 触发遮罩,主人回归 800ms 解除 | 主人特征经 DPAPI 加密,换用户、换机器均无法解密 |
适用场景:开放工位、共享办公、图书馆、宿舍。临时离开座位不想锁屏时,或在公共场合需要屏幕内容自动隐身时。
- 本地人脸守护:YuNet 人脸检测 + SFace 特征识别,与主人的加密特征模板余弦比对,全程本地推理,不依赖任何云端服务。
- 多屏遮罩:支持"全部显示器 / 仅主显示器 / 指定显示器"三种守护范围,遮罩同时覆盖所选屏幕。
- 点击穿透:遮罩窗口不接收鼠标、不抢焦点,鼠标操作可穿透到下层窗口;不出现在任务栏与 Alt+Tab。
- 全局热键:默认
Ctrl+Alt+P一键暂停/恢复守护(可在设置中更换,被占用时提示)。 - 系统托盘:常驻托盘图标(绿=守护中 / 黄=已暂停 / 红=摄像头异常),右键菜单 + 关键事件气泡提醒。
- 加密存储:主人特征模板使用 DPAPI(当前 Windows 用户)加密落盘,换用户/换机器均无法解密;提供一键清除生物特征。
- 健康提醒(可选):基于现有人脸检测提供久坐、用眼距离、低头坐姿、喝水、放松五类温和提醒,默认全部关闭;健康分析仅使用人脸几何数据(不保存任何图像),全部本机处理,距离与坐姿为粗略估算仅供参考,非医疗建议。
- 明亮 / 深色主题:基于 WPF-UI(Fluent Design)实现 Windows 11 观感,主窗口右上角一键切换明亮与深色主题,选择随设置持久保存,重启后保持。
- 单实例运行:重复启动会提示"已在运行"并退出。
- 开机自启:可选,注册表方式,设置文件为准双向同步。
- 全本地处理:人脸检测、特征提取、比对全部在本机 CPU 完成。
- 唯一的联网行为:仅在首次运行、模型文件缺失且用户点击确认后下载模型(约 37 MB,来自 OpenCV Zoo 官方仓库)。模型就绪后,正常运行期间不发起任何网络请求;可在设置完成后用防火墙/netstat 自行验证。
- 不上传:不向任何服务器发送数据(包括人脸特征、画面、使用统计)。
- 不录制、不保存原始画面:摄像头帧仅在内存中处理,处理完立即释放,绝不写盘、不缓存超过一帧、无临时文件。
- 仅保存加密特征:落盘的只有 DPAPI 加密后的 128 维特征向量(
%LOCALAPPDATA%\PrivacyScreenGuard\owner.bin),不含任何图像。 - 一键清除:主窗口提供"清除主人人脸数据",删除加密模板后需重新注册才能继续守护。
- Windows 10 / 11(x64)
- .NET 8 SDK(构建与运行源码时需要;单文件发布版无需安装运行时)
- 可用的摄像头(内置或 USB)
方式一:下载发布版(推荐) —— 到 Releases 下载单文件 exe,双击即用,无需安装 .NET 运行时。首次启动会提示下载模型(约 37 MB)。
方式二:从源码构建 —— 见下方「构建与运行」。
应用启动时必须能找到以下两个模型(缺失则提示并退出):
| 模型 | 文件名 | 用途 | 许可证 |
|---|---|---|---|
| YuNet 人脸检测 | face_detection_yunet_2023mar.onnx(约 0.22 MB) |
输出人脸框 + 5 关键点(左眼、右眼、鼻尖、左嘴角、右嘴角) | Apache-2.0(可商用) |
| SFace 人脸识别 | face_recognition_sface_2021dec.onnx(约 36.9 MB) |
从对齐后的 112×112 人脸提取 128 维特征 | Apache-2.0(可商用) |
下载地址(OpenCV Zoo 官方 GitHub 仓库):
- https://github.com/opencv/opencv_zoo/raw/main/models/face_detection_yunet/face_detection_yunet_2023mar.onnx
- https://github.com/opencv/opencv_zoo/raw/main/models/face_recognition_sface/face_recognition_sface_2021dec.onnx
放置路径:
- 程序内自动下载(推荐):首次启动时若模型缺失,程序会询问并自动下载到 exe 同目录的
models/;该位置不可写时(如安装在Program Files)自动改用%LOCALAPPDATA%\PrivacyScreenGuard\models\ - 手动放置:开发期放仓库根
models/;发布后放 exe 同目录的models/文件夹
程序按以下顺序查找模型目录(见 ModelLocator):① exe 同目录 models → ② 当前工作目录 models → ③ exe 目录上溯三级的 models(兼容开发期 bin/Debug 结构)→ ④ %LOCALAPPDATA%\PrivacyScreenGuard\models。
下载源按顺序尝试:GitHub 官方 → 国内镜像(
ghfast.top、gh-proxy.com),任一成功即停;下载先写入.tmp临时文件,校验大小后原子改名,避免残缺文件被当作模型使用。下载失败时窗口内可点"重试"(会重新遍历下载源)。
# 构建整个解决方案
dotnet build PrivacyScreenGuard.sln
# 运行(需已按上节准备好 models/ 目录)
dotnet run --project src/PrivacyScreenGuard调试说明:
- 使用 Visual Studio 或 VS Code 打开
PrivacyScreenGuard.sln即可调试(VS Code 需 C# Dev Kit 或 C# 扩展)。 - 推荐断点:
GuardEngine.OnFrameCaptured/GuardEngine.ProcessFrame(帧处理主链路)、GuardStateMachine.Process(状态机判定)。 - 首次运行(无主人模板)会自动弹出注册向导;取消向导则应用退出。
- 单元测试:
dotnet test(状态机、健康提醒、多人在场策略、姿态过滤、模板存储共 54 个用例)。
注意:
TemplateStoreTests直接读写真实的%LOCALAPPDATA%\PrivacyScreenGuard\owner.bin,每个用例开头会Delete()清场。若本机已注册主人人脸,请先备份该文件再执行dotnet test,否则模板会被清除。
单文件自包含发布(无需目标机器安装 .NET 运行时):
dotnet publish src/PrivacyScreenGuard/PrivacyScreenGuard.csproj -c Release -r win-x64 --self-contained -p:PublishSingleFile=true -o publish发布完成后,需要把仓库根的 models 目录复制到 publish 目录旁边(与 PrivacyScreenGuard.exe 同级),否则启动时会提示模型缺失:
Copy-Item -Recurse models publish\modelsMSIX 说明:如需商店分发或打包安装器,可再用 Visual Studio 的"Windows 应用程序打包项目"向导把发布产物打包为 MSIX;本仓库直接提供单文件 exe 即可满足常规使用。
首次启动(未检测到主人模板)会打开注册向导,分三步采集(支持自动采集,约每 0.9 秒一张;采集时按当前步骤的姿态过滤,采错姿态不会入库):
- 正脸(必填 3~5 张):正对镜头,保持自然表情
- 左转头(推荐 1~2 张,可跳过):头向左转约 30° 并保持
- 右转头(推荐 1~2 张,可跳过):头向右转约 30° 并保持
每个姿态组内逐维平均并 L2 归一化,形成多姿态加密模板(正脸 + 左侧 + 右侧)。比对时取与全部模板的最大相似度,并带姿态自适应阈值——侧脸姿态下匹配阈值自动下调 0.08(0.55→0.47),补偿侧脸特征天然偏低的问题。主人扭头看侧屏时,侧脸会与对应方向的侧脸模板匹配上,从根上解决"侧脸被误判为陌生人"。
侧脸采集角度约 30° 即可(头转到一个方向、另一侧脸颊明显可见);过大的角度(如 90° 完全侧面)五官不可见,检测会失效,无需采集。
侧脸样本缺失时仍可完成注册(弹窗确认),但大幅扭头时可能误判。采集画面仅在本地处理,不保存任何图像;落盘的只有 DPAPI 加密后的模板特征。
| 设置项 | 默认值 | 范围/取值 | 说明 |
|---|---|---|---|
| 识别阈值 | 0.55 | 0.3–0.9 | 与主人特征的余弦相似度判定线,越大越严格(漏认主人多、误放陌生人少) |
| 触发延迟 | 500 ms | 300–800 ms | 检测到非主人人脸持续多久后触发遮罩(防瞬时误触发) |
| 恢复延迟 | 800 ms | 500–1000 ms | 主人回归后持续多久解除遮罩(防闪烁) |
| 采集帧率 | 8 FPS | 5–10 FPS | 摄像头采集与推理频率,越低越省电 |
| 无人策略 | 保持正常 | 保持正常 / 触发锁定 | 画面中无人脸时是否视为风险("触发锁定"适用于离开工位自动锁屏场景) |
| 多人在场 | 主人在场即放行 | 放行 / 有陌生人即遮罩 | 主人与他人同框时的策略:放行适合给别人演示;"有陌生人即遮罩"下即使主人在场,出现未匹配主人的人脸也遮罩 |
| 全局热键 | Ctrl+Alt+P | 可自定义 | 暂停/恢复守护;被其他程序占用时注册失败并提示更换 |
| 开机自启 | 关闭 | 开/关 | 写注册表 Run 键,与设置文件双向同步 |
| 摄像头 | 索引 0 | 下拉选择 | 枚举本机摄像头(名称经 WMI 对齐) |
| 守护范围 | 全部显示器 | 全部 / 仅主屏 / 指定 | 多屏遮罩覆盖范围 |
| 识别侧脸样本 | 关闭 | 开/关 | 开启后侧脸/贴边脸也参与比对(配合左/右转头模板能认出侧脸主人、拦截侧身陌生人);关闭时侧脸不判定 |
| 模糊强度 | 50 | 0–100 | 遮罩激活时截屏并高斯模糊的强度(sigma 随值放大),值越大越模糊;0 = 纯黑遮罩。下次遮罩显示时生效 |
| 久坐提醒 | 关闭 | 开/关 + 阈值滑块 | 连续在场达到阈值分钟数后提醒起来活动;阈值范围 15–120 分钟,默认 45 分钟,中途离场超过 5 分钟累计清零 |
| 用眼距离提醒 | 关闭 | 开/关 + 阈值/时长滑块 | 人脸框宽超过画面宽的比例达到阈值(范围 0.25–0.5,默认 0.35)且持续(范围 5–60 秒,默认 10 秒)后提醒"稍往后靠",保护眼睛 |
| 低头坐姿提醒 | 关闭 | 开/关 + 阈值/时长滑块 | 低头比例超过阈值(范围 0.5–0.8,默认 0.62)且持续(范围 10–120 秒,默认 30 秒)后提醒挺直腰背 |
| 喝水提醒 | 关闭 | 开/关 + 间隔滑块 | 每隔设定分钟数提醒喝水;范围 15–180 分钟,默认 60 分钟 |
| 放松提醒 | 关闭 | 开/关 + 间隔滑块 | 每隔设定分钟数提醒远眺放松眼睛;范围 10–120 分钟,默认 30 分钟 |
| 提醒冷却 | 10 分钟 | 1–60 分钟 | 同类提醒的最小间隔分钟数,冷却期内同类型不重复触发;五类提醒均经托盘气泡呈现(同时显示在主窗口消息栏),修改无需重启即时生效 |
| 清除生物特征 | — | 按钮 | 删除加密模板(需确认),之后须重新注册 |
设置持久化于 %LOCALAPPDATA%\PrivacyScreenGuard\settings.json,非法数值在读写时自动夹取到合法范围。
托盘图标右键菜单:显示主窗口 / 暂停守护·恢复守护(文案随状态切换)/ 退出;双击图标等同"显示主窗口"。触发遮罩、摄像头异常(无摄像头/被占用/断开/光线过暗/模型缺失)等关键事件会弹气泡提醒,图标圆点颜色实时反映守护状态。
以下依赖均来自 src/PrivacyScreenGuard/PrivacyScreenGuard.csproj:
| 包 | 版本 | 用途 |
|---|---|---|
| OpenCvSharp4 | 4.13.0.20260627 | OpenCV 的 .NET 封装:摄像头采集(VideoCapture)、DNN 推理(CvDnn)、图像处理(对齐变换等) |
| OpenCvSharp4.runtime.win | 4.13.0.20260627 | OpenCV 在 Windows 上的原生动态库(随单文件发布一并打包) |
| OpenCvSharp4.WpfExtensions | 4.13.0.20260627 | Mat 与 WPF BitmapSource 互转(首次注册向导的摄像头预览) |
| WPF-UI | 4.3.0 | Fluent Design 控件样式与明暗主题服务(Windows 11 观感) |
| System.Management | 10.0.12 | 通过 WMI 查询摄像头设备名称 |
| System.Security.Cryptography.ProtectedData | 10.0.12 | DPAPI 加密主人特征模板 |
| System.Text.Json | 10.0.12 | 读写设置文件 settings.json |
说明:本项目使用的 OpenCvSharp 4.13 版本没有
FaceRecognizerSF包装类,因此 SFace 识别通过CvDnn直接加载 ONNX 推理,5 点对齐使用Cv2.EstimateAffinePartial2D自行实现(与 OpenCV 官方 SFace 实现数值等价)。
- 识别流水线:YuNet 检测(输出人脸框 + 5 关键点)→ 以 ArcFace 标准 5 点为参考,
Cv2.EstimateAffinePartial2D(RANSAC 相似变换)把人脸对齐裁剪到 112×112 → SFace(CvDnn 直接加载 ONNX,预处理与 OpenCV 官方一致)提取 128 维特征 → 与主人多姿态模板(正脸 + 左/右转头,组内平均归一化)逐一比对取最大相似度;侧脸姿态下阈值自适应下调 0.08。 - 状态机(防闪烁):每帧产生观测结论(无人 / 主人在场 / 有人但非主人);"有人但非主人"(以及无人策略为锁定时的"无人")为风险帧——连续风险达到触发延迟才显示遮罩;遮罩激活后需连续安全达到恢复延迟才解除,避免单帧抖动造成遮罩闪烁。触发/恢复延迟与无人策略变更时状态机整体重建,重建/暂停时补发 Hide 保证遮罩不卡死。
- 多人判定:对帧内每张人脸分别比对,默认任意一张匹配主人即视为安全帧(主人在场放行,方便给别人演示);「多人在场」设为"有陌生人即遮罩"后,帧内存在未匹配主人的人脸即触发,即使主人也在场。
- 遮罩窗口:每个目标显示器一个 WPF 无边框半透明窗口(约 88% 不透明深黑 + 提示文字),设置扩展样式
WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE实现点击穿透、不进 Alt+Tab、不抢焦点,并钩WM_MOUSEACTIVATE返回MA_NOACTIVATE双保险;用SetWindowPos以物理像素精确定位(规避 PerMonitorV2 下 WPF DIP 换算偏差),清单声明PerMonitorV2,跨不同缩放率的多屏可正确全覆盖;窗口句柄复用,重复显隐不重建,切换 ≤200ms。 - 摄像头健壮性:DSHOW 后端、640×480;打开失败每 2 秒自动重试(累计 5 次提示"可能被占用"),连续 3 次读帧失败判定断开并自动重连;帧平均亮度低于暗光阈值(默认 18)以 5 秒节流提示;拔掉摄像头应用不崩溃。
- 线程模型:帧处理在摄像头后台采集线程上同步执行(天然限流);引擎事件均在后台线程触发,UI/托盘操作一律经 Dispatcher 封送;普通状态文本 500ms 节流、推理异常 10 秒节流。
目标值(现代 4 核 CPU、CPU 推理):
| 指标 | 目标 |
|---|---|
| CPU 占用 | ≤ 15%(默认 8 FPS) |
| 内存 | ≤ 300 MB |
| 遮罩显隐切换 | ≤ 200 ms |
实测建议:任务管理器观察进程 CPU/内存,让引擎以默认设置连续运行 30 分钟,确认无内存持续增长;用秒表/录屏逐帧核对遮罩出现与消失的响应时间;如 CPU 偏高,可将采集帧率下调(5–10 FPS 可调),帧率越低占用越低。
- 系统级界面无法覆盖:遮罩是普通桌面窗口,无法覆盖 UAC 提升对话框、安全桌面、锁屏、Ctrl+Alt+Del 界面,也无法覆盖受 DRM 保护的内容(如部分流媒体播放器窗口)。
- 不能防物理手段:无法阻止他人用手机拍照、物理截屏或录屏软件录下屏幕内容;防截屏需系统级 API(
SetWindowDisplayAffinity仅对窗口内容生效),MVP 未实现。 - 只做"非主人人脸检测":不判断视线方向(是否"正在看屏幕"),陌生人正脸入镜即触发。
- 侧脸/贴边脸不参与判定(扭头看侧屏不误触发):只有"正脸 + 位于画面中部"的人脸才参与主人比对;明显侧脸(如主人扭头看侧屏)与贴边脸(路过/部分入镜)视为不可靠观测,既不算主人也不算陌生人——不触发遮罩但也不起保护作用。边界:陌生人刻意侧身+只露侧脸靠近屏幕时不会被遮罩拦截;主人短时间完全转出画面(画面里没人)按"无人策略"处理。建议在注册向导中完成左/右转头采集:有侧脸模板后,严格模式/多人严格策略下主人侧脸也能正确匹配,不再依赖姿态过滤放行。
- 主人与陌生人同时在场按主人处理:帧内任意一张正脸匹配主人即不触发遮罩,陌生人可能与主人一同观看屏幕,后续版本可加强。
- "真模糊"已实现(含边界说明):遮罩激活瞬间会在后台对屏幕做一次 GDI 截屏 → OpenCV 高斯模糊(强度可在设置中调节,0 = 纯黑遮罩)→ 以模糊画面覆盖全屏,并叠加约 35% 压暗层保证不可读。模糊快照仅存在于内存、遮罩隐藏即释放、不落盘、不上传。边界:锁屏 / 安全桌面 / DRM 保护内容下截屏会失败或得到黑块,此时自动回退为半透明纯黑遮罩;模糊图截取的是触发瞬间的画面,遮罩期间屏幕内容变化不会实时刷新(本来就不可读)。
- 模型许可证:本项目默认的 YuNet 与 SFace 模型均为 Apache-2.0,可商用。若追求更高精度换用 ArcFace(InsightFace)官方权重,其许可证为"研究/非商业用途",商用需自行评估授权;ArcFace 仅作为可选高精度路线说明,本项目不随包分发。
欢迎提交 Issue 与 Pull Request。开发环境搭建、测试执行、发布打包、目录结构说明等,见 CONTRIBUTING.md。
- 发现 Bug 或有功能建议:请用 Issue 模板 提交,附上系统版本、摄像头型号与复现步骤。
- 报告安全漏洞:请勿公开提 Issue,按 SECURITY.md 的方式私下联系。
- 提交代码:请先阅读 CONTRIBUTING.md 中的代码风格与提交规范。
本项目基于 MIT License 开源,Copyright (c) 2026 meiwe。
第三方依赖与资源的许可证:
| 名称 | 许可证 | 说明 |
|---|---|---|
| OpenCvSharp4 / .runtime.win / .WpfExtensions | Apache-2.0 | OpenCV 的 .NET 封装 |
| WPF-UI | MIT | Fluent Design 控件样式 |
| YuNet / SFace 模型(OpenCV Zoo) | Apache-2.0 | 可商用,不随仓库分发,由程序按需下载 |
项目图标(assets/icon.svg) |
MIT | 本项目原创 |
若你二次分发本项目的发布产物(单文件 exe),需一并遵守上述依赖的许可证条款(Apache-2.0 需保留版权与许可声明,MIT 需保留版权声明)。



