做这个小东西的起因很简单:想做一个不用解释、拿起来就能看懂的作品。手机摄像头拍下的画面里,人脸一旦出现,屏幕立刻给人脸盖上一层彩色像素马赛克。它不是什么高深的项目,但把视觉识别和屏幕显示串在了一个很直观的反馈里:镜头在看见脸,系统在保护这段画面。
说白了,这就是把平时看新闻时那种画面脱敏的效果,搬到一块开发板上自己玩。识别到人脸的瞬间,彩色方块像滤镜一样盖住脸;哪怕检测偶尔闪一下,马赛克也不会啪一下消失,而是会多坚持几秒,不会让路过的人看到人脸一闪一闪露出来。

都要准备什么
我用的是行空板K10,这块板子自带ESP32-S3、摄像头和一块2.8寸的彩色LCD屏,麦克风扬声器WiFi蓝牙也都有。关键是它集成了离线人脸检测,不需要联网,摄像头对着自己或屏幕就能当场演示。编程环境我用的是PlatformIO,配合K10的Arduino框架和AIRecognition库,管理依赖比较省心。
程序到底在做什么
整个流程其实就四步:先初始化屏幕、人脸识别模块和摄像头预览;然后把摄像头画面作为底层图像,在上面叠一层透明画布;接着不断读取识别库返回的人脸位置,算出遮挡区域;最后把马赛克画上去。检测到人脸位置变化时重绘,没检测到时保留上一帧,让遮挡看起来是连续的。

三个坑,踩完才顺畅
第一个坑是画布层级。摄像头预览和画布都是屏幕上的图层,如果先建画布再建摄像头图像,后建的图像会盖住画布,结果就是识别框数据都对,马赛克却看不见。解决办法是初始化时先把摄像头预览临时隐藏,等画布建好再恢复显示。
第二个坑是画色块的方式。一开始我在1x1的小矩形上设置大边框来撑起色块,结果屏幕上一排彩色竖条,根本不成方块。后来改用线段来画,让线段的长度和线宽都接近色块尺寸,才得到稳定的方块效果。色块大小由一个常量控制,调大画面更粗糙、绘制更省,调小更细腻、但要画的块也更多。
第三个坑是闪断。识别模块和屏幕刷新并不是逐帧同步的,人脸短暂漏检时识别状态会返回假,如果每轮都清空画布,马赛克就会跟着闪。我的处理是:人脸框变化超过几个像素才重绘,并在最后一次有效检测后保留马赛克五秒。这个办法改善的是显示连续性,不是识别率本身,保留时长也能自己调。
现场想让识别更稳,可以这样做
识别模型改不了,但能通过使用习惯让检测更稳定:让人脸正对摄像头,别大角度侧脸或被手、口罩遮住;光线均匀充足,避免逆光和明暗乱闪;让脸在画面中间、尺寸够大。如果发现绿色检测框经常消失,就先调光线、角度和距离,实在不行再考虑延长保留时间。
最后说一句关于隐私的实话
这里要讲清楚:这个小项目只是把遮挡画在了屏幕预览上,并没有改原始画面,也没有对录制或网络传输的数据做处理。如果真想拿来做可靠的隐私保护,必须把人脸检测和遮挡放到真正保存、传输画面的那一步去执行,不能只靠屏幕上的覆盖层。仅延长显示层的保持时间,保证不了所有画面都已脱敏。
总的说,这个项目真正的收获不在调用人脸识别本身,而是把摄像头图层、画布绘图、异步检测这三个平时容易忽略的点都理了一遍。按自己固件版本重新编译、实机验证一下,就能在本地预览里看到一个还算连续的人脸马赛克效果。


