用Python写了个“AI监工”盯着自己写代码,因过于硬核被围观!(附源码+原理)
·
用Python写了个“AI监工”盯着自己写代码,因过于硬核被围观!(附源码+原理)
摘要:作为一个自制力为负数的程序员,我终于对自己下手了。为了戒掉“写两行代码刷十分钟抖音”的毛病,我用 Python + OpenCV + YOLO + MediaPipe 撸了一个桌面端的AI视觉防摸鱼系统。它能识别我有没有在玩手机、有没有离开座位,甚至支持隔空手势控制。本文分享硬核开发过程、踩坑经验及核心源码。
😡 起因:我被算法“算计”了
不知道大家有没有同感:本来只想打开手机回个微信,结果手指不由自主地点开了短视频,一刷就是半小时。
作为一名开发者,我深知这就是多巴胺的“奖赏预测误差”机制。算法在攻破我的人性弱点。既然打不过算法,那就用魔法打败魔法!
我决定开发一款**“AI 视觉监工” (FocusGuard)**:
- 监控:摄像头实时盯着我,敢拿起手机?直接报警!
- 交互:不想碰鼠标?比个✌️就能暂停休息。
- 复盘:自动记录走神瞬间,生成“羞耻墙”截图。
这是最终做出来的样子(纯Python开发,已打包EXE):

🛠️ 技术栈选型
为了在我的渣机上也能流畅运行,我没有用笨重的 PyTorch 原生推理,而是走了轻量化路线:
- GUI 框架:
CustomTkinter(比原声 Tkinter 美观 10 倍,支持高分屏) - 视觉捕捉:
OpenCV(CV2) - 物体检测:
YOLO11s转ONNX(CPU 推理也能跑满 30FPS) - 手势识别:
MediaPipe(谷歌的方案,稳准狠) - 打包工具:
PyInstaller+Inno Setup(为了把这堆环境塞进一个 exe 也是拼了)
💻 核心代码实现
1. 怎么判断我在玩手机?(YOLO + ONNX)
这是最核心的功能。我训练了一个 YOLO 模型专门识别 Cell Phone。为了性能,我使用了 OpenCV 的 DNN 模块加载 ONNX 模型,这样就不需要安装几 GB 的 PyTorch 环境了。
def detect_phone_onnx(self, frame):
# 图像预处理:归一化 + 尺寸调整
blob = cv2.dnn.blobFromImage(frame, 1/255.0, (640, 640), swapRB=True, crop=False)
self.net.setInput(blob)
outputs = self.net.forward()
# 解析输出
predictions = np.transpose(outputs[0])
rows = predictions.shape[0]
for i in range(rows):
row = predictions[i]
# 获取最大概率的类别
classes_scores = row[4:]
_, max_score, _, max_class_loc = cv2.minMaxLoc(classes_scores)
# ID 67 是 COCO 数据集里的手机,置信度设为 0.45
if max_score > 0.45 and max_class_loc[1] == 67:
print(">>> 警告:监测到手机!")
return True
return False
- 手势控制 (MediaPipe 的妙用)
为了不打断心流(Flow State),我设计了手势交互:
✌️ (剪刀手):申请休息 8 分钟(去喝水、上厕所)。
✋ (张开手掌):申请“手机豁免权” 10 分钟(必须回消息时用)。
这里利用了 MediaPipe Hands 的关键点坐标逻辑:
import mediapipe as mp
def _check_victory(self, hand_landmarks):
"""
检测剪刀手 (Victory)
逻辑:食指中指伸直,无名指小指弯曲
"""
lm = hand_landmarks.landmark
# 8:食指指尖, 6:食指根部 -> y坐标越小位置越高
# 12:中指指尖, 10:中指根部
index_is_open = lm[8].y < lm[6].y
middle_is_open = lm[12].y < lm[10].y
# 16:无名指, 20:小指 -> 必须是弯曲的
ring_is_closed = lm[16].y > lm[14].y
pinky_is_closed = lm[20].y > lm[18].y
return index_is_open and middle_is_open and ring_is_closed and pinky_is_closed
🚀 遇到的坑与解决方案
- PyInstaller 打包后的“模块丢失”
开发时好好的,打包成 .exe 后直接闪退,报错 ModuleNotFoundError: mediapipe.python.solutions。 这是因为 MediaPipe 动态加载了一些子模块,PyInstaller 分析不到。
解决方案: 在 .spec 文件中,必须使用 collect_all 暴力收集:
from PyInstaller.utils.hooks import collect_all
# 强行把 mediapipe 的所有家当都带上
mp_datas, mp_binaries, mp_hiddenimports = collect_all('mediapipe')
a = Analysis(
...
datas=all_datas + mp_datas,
binaries=all_binaries + mp_binaries,
hiddenimports=all_hiddenimports + mp_hiddenimports,
...
)
- 误报问题
刚开始,我喝水用的黑色马克杯经常被识别成手机。 优化:我加入了逻辑判断,不仅要识别到 Object,还必须结合 光流法 (Optical Flow) —— 只有当画面有动作且检测到手机时才报警。如果画面静止(比如手机放在桌上没动),则不报警,减少对注意力的打扰。
📦 成果发布:FocusGuard v1.0
经过两周的迭代(和无数次被自己的程序报警吓一跳),v1.0.0 版本终于上线了。
它能做什么?
1、全自动监工:你只需要打开它,最小化,然后开始工作。一旦你拿起手机,警报声就会响起。
2、不联网、更安全:所有计算都在本地,公司电脑也能放心用。
3、统计报表:结束工作后,它会生成一张“羞耻报表”,告诉你今天摸了多少次鱼,并附带走神瞬间的截图(保存在本地)。
适合人群:
1、写代码写着写着就开始刷手机的程序员。
2、正在肝论文的大学生/研究生。
3、需要长时间深度工作的自由职业者。
更多推荐
所有评论(0)