使用YoloV5和Mediapipe实现——上课玩手机检测(附完整源码)

 

目录

效果展示

应用场景举例

1. 课堂或考试监控(看到这个学生党还会爱我吗)

2. 驾驶安全监控(防止开车玩手机)

3. 企业办公管理(防止工作时间玩手机)

4. 监狱、戒毒所、特殊场所安保

5. 家长监管(防止孩子沉迷手机)

6. 公共场所提醒(图书馆、博物馆等)

7. 体育馆或健身房监督

实现模块

YOLO(You Only Look Once)

MediaPipe Hands

两者之间的合作使用

实现思路

1. 模块初始化

2. 视频流读取

3. 手机检测

4. 手部检测

5. 距离计算与判断

6. 显示与退出

完整源码

总结


效果展示

玩手机检测


应用场景举例

1. 课堂或考试监控(看到这个学生党还会爱我吗

应用场景:

  • 在学校的 考试或课堂 过程中,自动检测学生是否在使用手机,防止考试作弊或上课玩手机。

  • 教师可以使用该系统来提醒学生保持专注,提高课堂纪律。

优势:
非侵入式检测,无需学生主动上交手机。
实时监控,可以及时发现违规行为。
低成本部署,普通摄像头+计算机即可运行。


2. 驾驶安全监控(防止开车玩手机)

应用场景:

  • 安装在 驾驶室 内部,用来检测司机是否在驾驶过程中使用手机。

  • 适用于 出租车、货车、公交车 及私家车,提高行车安全。

优势:
预防分心驾驶,减少因玩手机导致的事故。
可以集成到ADAS(高级驾驶辅助系统),增强智能安全功能。
提供语音或视觉警告,提醒司机停止使用手机。


3. 企业办公管理(防止工作时间玩手机)

应用场景:

  • 在企业办公区域监测 员工是否频繁使用手机,提高工作效率。

  • 可用于 工厂流水线、客服中心、银行等,防止员工因使用手机影响工作。

优势:
自动检测,不影响正常工作
可生成日志,统计员工的手机使用情况
适用于不同工作环境,如流水线、办公室等。


4. 监狱、戒毒所、特殊场所安保

应用场景:

  • 监狱、戒毒所、机密单位 监测是否有人私自使用手机,防止信息泄露或违规通信。

  • 可安装在 监控摄像头系统 中,自动检测并报警。

优势:
防止非法通信,提升安保等级
24小时自动监控,无需人工干预
可结合人脸识别,锁定违规人员


5. 家长监管(防止孩子沉迷手机)

应用场景:

  • 家长可以在家中 设置摄像头,检测孩子是否长时间使用手机。

  • 适用于 儿童学习、睡前管理、写作业时的监督

优势:
自动提醒,减少孩子玩手机时间
保护视力,防止长时间使用手机影响健康
可设置提醒时间,比如晚上9点后检测到手机就提醒休息


6. 公共场所提醒(图书馆、博物馆等)

应用场景:

  • 图书馆、博物馆、会议室、电影院等 需要安静的环境下,提醒人们不要使用手机。

  • 检测到使用手机后,系统可以 弹出提示播放音频提醒

优势:
提升公共场所秩序,减少干扰。
可以结合AI语音助手,自动发出提醒
适用于不同场所,无需额外硬件成本


7. 体育馆或健身房监督

应用场景:

  • 健身房、体育馆 监督运动者是否在运动时过度使用手机。

  • 适用于 健身房、瑜伽馆、篮球馆等,提高训练专注度。

优势:
帮助用户减少手机依赖,提升训练效果
适用于健身教练管理学员训练状态
可以结合数据分析,提供用户的运动专注度统计


实现模块

YOLO(You Only Look Once)

  • 主要作用:
    YOLO是一种目标检测算法,它用于在图像中快速识别和定位特定类别的对象(例如手机)。在这段代码中,YOLO负责检测视频帧中的手机,并返回手机的边界框(即目标在图像中的位置和大小)。

  • 实现原理:

    • 单次前向传播: YOLO将整个图像一次性输入神经网络,网络会将图像划分成网格,并对每个网格预测多个边界框及其对应的类别概率。

    • 实时检测: 由于只需要单次前向传播,因此速度非常快,适合实时应用。

    • 输出信息: 模型输出包括边界框坐标、置信度得分以及预测类别,进而通过后处理筛选出满足条件的检测结果。


MediaPipe Hands

  • 主要作用:
    MediaPipe Hands是Google推出的手部关键点检测模块,专注于检测手部并提取关键点信息(例如手指、手掌的特定位置)。在这段代码中,MediaPipe主要用于检测手部,并提取食指指尖(关键点编号8)的坐标。

  • 实现原理:

    • 检测和追踪: MediaPipe使用经过训练的神经网络模型先检测手部,再对检测到的手部进行关键点定位。

    • 高精度关键点提取: 模型能够输出手部各个关节点的精确坐标,使得后续能够计算手部各部分之间的相对位置和运动。

    • 优化和实时性: 该模块经过高度优化,可以在移动设备和PC上实时运行,适用于视频流处理。


两者之间的合作使用

  • 独立处理,同步运行:
    同一帧图像中,YOLO和MediaPipe分别对不同目标进行检测——YOLO检测手机,MediaPipe检测手部。两者互不干扰,各自独立完成自己的任务。

  • 二者的信息整合:

    • 目标定位: YOLO输出手机在图像中的边界框及中心点,而MediaPipe输出手部关键点(例如食指指尖)的位置。

    • 行为判断: 后续代码将YOLO得到的手机中心点与MediaPipe检测到的手部关键点进行距离计算(欧氏距离),通过预设的距离阈值来判断用户是否在使用手机。

    • 反馈结果: 根据距离的比较,程序在视频画面上显示不同的提示信息,实时反映用户是否可能在使用手机。


实现思路

        YOLO物体检测和MediaPipe手部关键点检测,判断用户是否在使用手机。下面是详细的实现思路:

1. 模块初始化

  • YOLO模型

    • 加载预训练的YOLO模型(此处使用的是YOLOv5su变体),用于在视频帧中检测手机。模型输出包含检测框的坐标、置信度以及类别信息(通过手机的中心点坐标来匹配)

  • MediaPipe Hands

    • 初始化MediaPipe的手部检测模块,配置检测模式、最大手数、检测和追踪的置信度。

    • MediaPipe会返回每只手的多个关键点坐标(例如食指指尖对应关键点编号8)。

2. 视频流读取

  • 使用OpenCV打开默认摄像头,并循环读取每一帧图像。

3. 手机检测

  • 图像预处理

    • 将BGR图像转换为RGB(BGR代表蓝色、绿色和红色,而RGB代表红色、绿色和蓝色。这两种颜色空间的主要区别在于颜色通道的顺序。),因为MediaPipe要求输入RGB图像。

  • YOLO检测

    • 使用YOLO模型对当前帧进行检测,遍历检测结果,筛选出类别为手机的目标。

    • YOLO 训练的数据集通常是 COCO,它包含 80 种常见物体的类别,每个类别都有一个 唯一的索引号

      在 COCO 数据集中:

      "cell phone"(手机)类别的索引是 67

      人(person)        → 类别索引 0

      自行车(bicycle) → 类别索引 1

      汽车(car)           → 类别索引 2

      书本(book)        → 类别索引 73

    • 对每个检测到的手机,提取边界框坐标并在图像上绘制矩形框和标签。

4. 手部检测

  • 使用MediaPipe对RGB图像进行手部检测。

  • 遍历检测到的手部,提取每只手中食指指尖(关键点8)的坐标。

  • 在图像上绘制手部关键点和连接线,并在食指指尖处绘制一个圆点和文字标识。

5. 距离计算与判断

  • 手机中心点计算

    • 对于每个手机检测框,计算其中心点坐标。

  • 欧氏距离计算

    • 对于每个手部食指指尖坐标,计算其与手机中心点之间的欧氏距离。

    • 在图像上显示每对点之间的距离数值,并根据距离绘制不同颜色的连线:

      • 如果距离小于预设的阈值(50像素),认为用户可能正在使用手机,用红色标记;否则用蓝色标记。

  • 状态判断

    • 根据所有手与手机的距离判断,如果至少有一对距离小于阈值(我们这里的阈值为50个像素,可以根据不同的情况实施修改),则显示“Using Phone!!!Stop!!!”,否则显示“Not Using Phone”。

6. 显示与退出

  • 将处理后的图像帧显示在窗口中。

  • 通过监听键盘事件(ESC键)来实现退出循环和释放资源。


完整源码

import cv2
import mediapipe as mp
import numpy as np
from ultralytics import YOLO

# 初始化YOLO模型(预训练YOLOv5s模型)
model = YOLO("./yolov5spt/yolov5su.pt")  # 确保当前目录有该模型文件或使用绝对路径

# 初始化MediaPipe Hands
mp_hands = mp.solutions.hands
hands_detector = mp_hands.Hands(
    static_image_mode=False,
    max_num_hands=2,
    min_detection_confidence=0.5,
    min_tracking_confidence=0.5
)
mp_drawing = mp.solutions.drawing_utils

# 距离阈值(单位:像素),需要根据实际情况调整
DISTANCE_THRESHOLD = 50

# 打开摄像头,这里的0就是默认的第一个摄像头
cap = cv2.VideoCapture(0)

while True:
    ret, frame = cap.read()
    if not ret:
        break

    # 将图像转换为RGB供MediaPipe使用
    frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

    # YOLO检测手机,注意模型可能会检测出多个类别
    # 得到 detections 结果为列表,包含检测框、置信度及类别信息
    results = model(frame)
    phone_boxes = []
    for result in results:
        # 解析检测结果(model返回的数据结构可能会变化,请参考ultralytics文档)
        # 此处假设每个result.boxes对象内有xyxy, conf, cls属性
        for box in result.boxes:
            cls = int(box.cls[0])
            # COCO数据集中,手机(cell phone)的类别大约为 67
            # 这里根据具体模型类别索引进行调整
            if cls == 67:
                # 获取边界框坐标并转换为整型
                x1, y1, x2, y2 = map(int, box.xyxy[0])
                phone_boxes.append((x1, y1, x2, y2))
                # 在图像上绘制手机检测框
                cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
                cv2.putText(frame, "Phone", (x1, y1 - 10),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2)

    # 使用MediaPipe检测手部
    results_hands = hands_detector.process(frame_rgb)
    hand_points = []  # 存放检测到的手部关键点(以食指指尖为例)
    if results_hands.multi_hand_landmarks:
        for hand_landmarks in results_hands.multi_hand_landmarks:
            # 获取食指指尖 landmark,编号8(MediaPipe Hands的关键点编号)
            h, w, _ = frame.shape
            landmark = hand_landmarks.landmark[8]
            cx, cy = int(landmark.x * w), int(landmark.y * h)
            hand_points.append((cx, cy))
            # 在图像上绘制手部关键点和连线
            mp_drawing.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)
            cv2.circle(frame, (cx, cy), 5, (0, 0, 255), -1)
            cv2.putText(frame, "Index Tip", (cx, cy - 10),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)

    # 检查每个手机框与手部关键点之间的距离
    using_phone = False
    for (x1, y1, x2, y2) in phone_boxes:
        # 计算手机检测框中心点
        phone_cx = (x1 + x2) // 2
        phone_cy = (y1 + y2) // 2
        cv2.circle(frame, (phone_cx, phone_cy), 5, (255, 0, 0), -1)
        for (hx, hy) in hand_points:
            # 计算欧氏距离
            dist = np.sqrt((phone_cx - hx)**2 + (phone_cy - hy)**2)
            # 在图像上显示距离值
            cv2.putText(frame, f"{int(dist)}", ((phone_cx+hx)//2, (phone_cy+hy)//2),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 0), 2)
            if dist < DISTANCE_THRESHOLD:
                using_phone = True
                # 用红色标记距离过近的情况
                cv2.line(frame, (phone_cx, phone_cy), (hx, hy), (0, 0, 255), 2)
            else:
                cv2.line(frame, (phone_cx, phone_cy), (hx, hy), (255, 0, 0), 1)

    # 显示结果
    if using_phone:
        cv2.putText(frame, "Using Phone!!!Stop!!!", (50, 50),
                    cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
    else:
        cv2.putText(frame, "Not Using Phone", (50, 50),
                    cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)

    cv2.imshow("Phone and Hand Detection", frame)
    # 按ESC退出
    if cv2.waitKey(1) & 0xFF == 27:
        break

cap.release()
cv2.destroyAllWindows()

总结

        通过YOLO模型实时检测手机位置,再通过MediaPipe检测手部关键点,利用计算出的距离判断用户是否在使用手机,并将结果实时显示在视频画面上。这种方法融合了目标检测和关键点检测技术,适用于监控、驾驶安全提醒等场景。

 

 

 

 

### 关于51Nod平台上编号为1020的问题详情与解答 #### 问题描述 在51Nod平台上的第1020号问题是关于计算两个大整数相加的结果[^1]。给定两个正整数AB,长度不超过10^6位,要求编写程序来求解这两个数的。 #### 输入格式说明 输入数据由多组测试案例组成;每组测试案例占两行,分别表示要相加的大整数AB。对于每一组测试案例,应当单独输出一行结果,即A+B的值。 #### 解决方案概述 解决此问题的关键在于处理超大数据类型的运算,在大多数编程语言中内置的数据类型无法直接支持如此大规模数值的操作。因此,可以采用字符串的方式来存储这些大整数,并实现逐位相加逻辑,同时考虑进位情况。 下面是一个Python版本的具体实现方法: ```python def add_large_numbers(a: str, b: str) -> str: # Reverse strings to make addition easier from least significant digit a = a[::-1] b = b[::-1] carry = 0 result = [] max_length = max(len(a), len(b)) for i in range(max_length): digit_a = int(a[i]) if i < len(a) else 0 digit_b = int(b[i]) if i < len(b) else 0 total = digit_a + digit_b + carry carry = total // 10 current_digit = total % 10 result.append(str(current_digit)) if carry != 0: result.append(str(carry)) return &#39;&#39;.join(reversed(result)) if __name__ == "__main__": while True: try: num1 = input().strip() num2 = input().strip() print(add_large_numbers(num1, num2)) except EOFError: break ``` 该代码片段定义了一个函数`add_large_numbers`用于接收两个作为参数传入的大整数(形式上为字符串),并返回它们之同样作为一个字符串。通过反转输入字符串使得最低有效位位于索引位置0处从而简化了按位累加的过程。最后再将得到的结果列表反向拼接成最终答案输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WenJGo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值