AI计算机视觉笔记十三:危险区域识别系统

简介: 本文介绍了如何在 IPC 监控视频中实现区域入侵检测,通过 YOLOv5 和 ByteTrack 实现人物检测与多目标跟踪。系统能在检测到人员进入预设的危险区域时发出警报,保障安全。主要步骤包括:1)使用 YOLOv5 识别人物;2)使用 ByteTrack 进行多目标跟踪;3)利用射线法判断物体是否进入禁区内。项目基于 Python 开发,使用海思、君正、RK 等摄像头模组,代码已在 RV1126 上验证,计划移植至 RK3568 平台。项目结构清晰,包含模型训练、跟踪算法及图形化界面展示等功能。

一、介绍

在IPC监控视频中,很多IPC现在支持区域检测,当在区域内检测到有人闯入时,发送报警并联动报警系统,以保障生命和财产安全具有重大意义。它能够在第一时间检测到人员进入危险区域的行为,并发出及时警告,从而防止潜在事故的发生。

简单说是,在地图上标记出禁区(多边形),用计算机视觉技术监控进入禁区的物体。

现在很多摄像头模组,都自带了移动侦测功能,比如海思,君正,RK等。

以前有在RV1126上实现过类似的,现在想在RK3568上实现。

记录下PC端测试情况。
image.png
检测流程:

1、使用YOLOV5识别人物

2、使用ByteTrack实现多目标跟踪

3、使用射线法判断点是否在区域内

二、环境搭建

环境搭建参考AI项目二十二:行人属性识别-CSDN博客

项目结构
image.png

ByteTrack是git下载的源码

fonts存放了字体文件

weights存放yolov5s.pt模型

yolov5是git下载的源码

main.py主程序

mask_face.py是人脸遮挡代码

track.py是多目标根据和闯入识别代码

三、代码解析

代码功能不多,直接附上源码

main.py

import cv2
import torch
import numpy as np
from PIL import Image, ImageDraw, ImageFont
print("0")
from mask_face import mask_face
print("2")
from track import PersonTrack

print("1")
def cv2_add_chinese_text(img, text, position, text_color=(0, 255, 0), tex_size=30):
    img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    draw = ImageDraw.Draw(img)
    font_style = ImageFont.truetype(
        "./fonts/MSYH.ttc", tex_size, encoding="utf-8")
    draw.text(position, text, text_color, font=font_style)
    return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)
print("2")
class BreakInDetection:
    def __init__(self):
        self.yolov5_model = torch.hub.load('yolov5'
                                           , 'custom'
                                           , path='./weights/yolov5s.pt'
                                           , source='local')
        self.yolov5_model.conf = 0.7
        self.tracker = PersonTrack()

    @staticmethod
    def yolo_pd_to_numpy(yolo_pd):
        box_list = yolo_pd.to_numpy()
        detections = []
        for box in box_list:
            l, t = int(box[0]), int(box[1])
            r, b = int(box[2]), int(box[3])

            conf = box[4]

            detections.append([l, t, r, b, conf])
        return np.array(detections, dtype=float)

    def plot_detection(self, person_track_dict, penalty_zone_point_list, frame, frame_idx):
        print(frame_idx)
        break_in_num = 0
        for track_id, detection in person_track_dict.items():
            l, t, r, b = detection.ltrb
            track_id = detection.track_id
            print(track_id, detection.is_break_in)

            if detection.is_break_in:
                box_color = (0, 0, 255)
                id_color = (0, 0, 255)
                break_in_num += 1
            else:
                box_color = (0, 255, 0)
                id_color = (255, 0, 0)
            frame[t:b, l:r] = mask_face(frame[t:b, l:r])

            # 人体框
            cv2.rectangle(frame, (l, t), (r, b), box_color, 1)
            cv2.putText(frame, f'id-{track_id}', (l + 2, t - 3), cv2.FONT_HERSHEY_PLAIN, 3, id_color, 2)


        # 绘制禁区
        pts = np.array(penalty_zone_point_list, np.int32)
        pts = pts.reshape((-1, 1, 2))
        cv2.polylines(frame, [pts], True, (0, 0, 255), 2)
        cover = np.zeros((frame.shape[0], frame.shape[1], 3), np.uint8)
        cover = cv2.fillPoly(cover, [pts], (0, 0, 255))
        frame = cv2.addWeighted(frame, 0.9, cover, 0.3, 0)
        frame = cv2_add_chinese_text(frame, f'禁区', (600, 450), (255, 0, 0), 30)

        # 统计区
        info_frame_h, info_frame_w = 200, 400
        info_frame = np.zeros((info_frame_h, info_frame_w, 3), np.uint8)
        if_l, if_t = 100, 100
        if_r, if_b = if_l + info_frame_w, if_t + info_frame_h
        frame_part = frame[if_t:if_b, if_l:if_r]
        mixed_frame = cv2.addWeighted(frame_part, 0.6, info_frame, 0.7, 0)
        frame[if_t:if_b, if_l:if_r] = mixed_frame

        frame = cv2_add_chinese_text(frame, f'统计', (if_l + 150, if_t + 10), (255, 0, 0), 40)
        frame = cv2_add_chinese_text(frame, f'当前闯入禁区 {break_in_num} 人', (if_l + 60, if_t + 80), (255, 0, 0), 35)
        return frame

    def detect(self):
        cap = cv2.VideoCapture('./video.mp4')
        video_w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
        video_h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
        fps = round(cap.get(cv2.CAP_PROP_FPS))
        print(fps)
        video_writer = cv2.VideoWriter('./video_result.mp4', cv2.VideoWriter_fourcc(*'H264'), fps, (video_w, video_h))


        frame_idx = 0
        while cap.isOpened():
            frame_idx += 1
            success, frame = cap.read()
            if not success:
                print("Ignoring empty camera frame.")
                break

            results = self.yolov5_model(frame[:, :, ::-1])
            pd = results.pandas().xyxy[0]
            person_pd = pd[pd['name'] == 'person']
            person_det_boxes = self.yolo_pd_to_numpy(person_pd)
            if len(person_det_boxes) > 0:
                person_track_dict, penalty_zone_point_list = self.tracker.update_track(person_det_boxes, frame)
                frame = self.plot_detection(person_track_dict, penalty_zone_point_list, frame, frame_idx)

            cv2.imshow('Break in Detection', frame)
            video_writer.write(frame)

            if cv2.waitKey(1) & 0xFF == ord("q"):
                break

        cap.release()
        cv2.destroyAllWindows()

print("3")
if __name__ == '__main__':
    BreakInDetection().detect()

mask_face.py

import cv2
import mediapipe as mp

face_detection = mp.solutions.face_detection.FaceDetection(model_selection=1, min_detection_confidence=0.3)


def mask_face(frame):
    frame.flags.writeable = False
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    results = face_detection.process(frame)
    frame_h, frame_w = frame.shape[:2]

    frame.flags.writeable = True
    frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)

    if results.detections:
        for detection in results.detections:
            face_box = detection.location_data.relative_bounding_box
            xmin, ymin, face_w, face_h = face_box.xmin, face_box.ymin, face_box.width, face_box.height
            l, t = int(xmin*frame_w), int(ymin*frame_h)
            r, b = l+int(face_w*frame_w), t+int(face_h*frame_h)

            cv2.rectangle(frame, (l, t), (r, b), (203, 192, 255), -1)

    return frame

track.py

from dataclasses import dataclass
import numpy as np
from collections import deque
import cv2
import paddleclas
import sys
sys.path.append('./ByteTrack/')
from yolox.tracker.byte_tracker import BYTETracker, STrack


@dataclass(frozen=True)
class BYTETrackerArgs:
    track_thresh: float = 0.25
    track_buffer: int = 30
    match_thresh: float = 0.8
    aspect_ratio_thresh: float = 3.0
    min_box_area: float = 1.0
    mot20: bool = False


class Detection(object):
    def __init__(self, ltrb, track_id, is_break_in):
        self.track_id = track_id
        self.ltrb = ltrb
        self.is_break_in = is_break_in  # 是否闯入
        self.track_list = deque(maxlen=30)

    def update(self, ltrb, is_break_in):
        self.ltrb = ltrb
        self.is_break_in = is_break_in
        l, t, r, b = ltrb
        self.track_list.append(((l+r)//2, b))


class PersonTrack(object):
    def __init__(self):
        self.byte_tracker = BYTETracker(BYTETrackerArgs())
        self.detection_dict = {}

        # 禁区多边形
        point1 = (400, 440)
        point2 = (460, 579)
        point3 = (920, 600)
        point4 = (960, 450)
        self.penalty_zone_point_list = [point1, point2, point3, point4]

    def is_point_in_polygon(self, vertices, point):
        """
        判断点是否在多边形内
        :param vertices: 多边形顶点坐标列表 [(x1, y1), (x2, y2), ..., (xn, yn)]
        :param point: 需要判断的点坐标 (x, y)
        :return: True or False
        """
        n = len(vertices)
        inside = False

        p1x, p1y = vertices[0]
        for i in range(1, n + 1):
            p2x, p2y = vertices[i % n]
            if point[1] > min(p1y, p2y):
                if point[1] <= max(p1y, p2y):
                    if point[0] <= max(p1x, p2x):
                        if p1y != p2y:
                            xints = (point[1] - p1y) * (p2x - p1x) / (p2y - p1y) + p1x
                        if p1x == p2x or point[0] <= xints:
                            inside = not inside
            p1x, p1y = p2x, p2y

        return inside

    def update_track(self, boxes, frame):
        tracks = self.byte_tracker.update(
            output_results=boxes,
            img_info=frame.shape,
            img_size=frame.shape
        )

        new_detection_dict = {}
        for track in tracks:
            l, t, r, b = track.tlbr.astype(np.int32)
            track_id = track.track_id

            # 判断人是否闯入
            detect_point = ((l + r)//2, b)
            is_break_in = self.is_point_in_polygon(self.penalty_zone_point_list, detect_point)

            if track_id in self.detection_dict:
                detection = self.detection_dict[track_id]
                detection.update((l, t, r, b), is_break_in)
            else:
                detection = Detection((l, t, r, b), track_id, is_break_in)

            new_detection_dict[track_id] = detection

        self.detection_dict = new_detection_dict

        return self.detection_dict, self.penalty_zone_point_list

代码需要注意的是:

一、区域位置
image.png
二、显示参数位置
image.png
这几个参数需要根据视频的大小,去调整位置,不然会报错。

三、检测点是否在区域内

image.png
转成C语言直接部署到RK3568上。

后续将部署到RK3568,参考git和讯为电子多目标检测已实现。

相关文章
|
2月前
|
人工智能 监控 安全
提效40%?揭秘AI驱动的支付方式“一键接入”系统
本项目构建AI驱动的研发提效系统,通过Qwen Coder与MCP工具链协同,实现跨境支付渠道接入的自动化闭环。采用多智能体协作模式,结合结构化Prompt、任务拆解、流程管控与安全约束,显著提升研发效率与交付质量,探索大模型在复杂业务场景下的高采纳率编码实践。
406 26
提效40%?揭秘AI驱动的支付方式“一键接入”系统
|
2月前
|
人工智能 自然语言处理 前端开发
最佳实践2:用通义灵码以自然语言交互实现 AI 高考志愿填报系统
本项目旨在通过自然语言交互,结合通义千问AI模型,构建一个智能高考志愿填报系统。利用Vue3与Python,实现信息采集、AI推荐、专业详情展示及数据存储功能,支持响应式设计与Supabase数据库集成,助力考生精准择校选专业。(239字)
263 12
|
2月前
|
存储 人工智能 搜索推荐
LangGraph 记忆系统实战:反馈循环 + 动态 Prompt 让 AI 持续学习
本文介绍基于LangGraph构建的双层记忆系统,通过短期与长期记忆协同,实现AI代理的持续学习。短期记忆管理会话内上下文,长期记忆跨会话存储用户偏好与决策,结合人机协作反馈循环,动态更新提示词,使代理具备个性化响应与行为进化能力。
411 10
LangGraph 记忆系统实战:反馈循环 + 动态 Prompt 让 AI 持续学习
|
2月前
|
机器学习/深度学习 人工智能 JSON
PHP从0到1实现 AI 智能体系统并且训练知识库资料
本文详解如何用PHP从0到1构建AI智能体,涵盖提示词设计、记忆管理、知识库集成与反馈优化四大核心训练维度,结合实战案例与系统架构,助你打造懂业务、会进化的专属AI助手。
236 6
|
2月前
|
人工智能 JSON 安全
Claude Code插件系统:重塑AI辅助编程的工作流
Anthropic为Claude Code推出插件系统与市场,支持斜杠命令、子代理、MCP服务器等功能模块,实现工作流自动化与团队协作标准化。开发者可封装常用工具或知识为插件,一键共享复用,构建个性化AI编程环境,推动AI助手从工具迈向生态化平台。
427 1
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
拔俗当AI成为你的“心灵哨兵”:多模态心理风险预警系统如何工作?
AI多模态心理预警系统通过融合表情、语调、文字、绘画等多维度数据,结合深度学习与多模态分析,实时评估心理状态。它像“心灵哨兵”,7×24小时动态监测情绪变化,发现抑郁、焦虑等风险及时预警,兼顾隐私保护,助力早期干预,用科技守护心理健康。(238字)
|
2月前
|
存储 人工智能 自然语言处理
拔俗AI产投公司档案管理系统:让数据资产 “活” 起来的智能助手
AI产投档案管理系统通过NLP、知识图谱与加密技术,实现档案智能分类、秒级检索与数据关联分析,破解传统人工管理效率低、数据孤岛难题,助力投资决策提效与数据资产化,推动AI产投数字化转型。
|
2月前
|
人工智能 算法 数据安全/隐私保护
拔俗AI多模态心理风险预警系统:用科技守护心理健康的第一道防线
AI多模态心理风险预警系统通过语音、文本、表情与行为数据,智能识别抑郁、焦虑等心理风险,实现早期干预。融合多源信息,提升准确率,广泛应用于校园、企业,助力心理健康服务从“被动响应”转向“主动预防”,为心灵筑起智能防线。(238字)
|
2月前
|
人工智能 搜索推荐 Cloud Native
拔俗AI助教系统:教师的"超级教学秘书",让每堂课都精准高效
备课到深夜、批改作业如山?阿里云原生AI助教系统,化身“超级教学秘书”,智能备课、实时学情分析、自动批改、精准辅导,为教师减负增效。让课堂从经验驱动转向数据驱动,每位学生都被看见,教育更有温度。
|
2月前
|
机器学习/深度学习 人工智能 监控
拔俗AI智能营运分析助手软件系统:企业决策的"数据军师",让经营从"拍脑袋"变"精准导航"
AI智能营运分析助手打破数据孤岛,实时整合ERP、CRM等系统数据,自动生成报表、智能预警与可视化决策建议,助力企业从“经验驱动”迈向“数据驱动”,提升决策效率,降低运营成本,精准把握市场先机。(238字)

热门文章

最新文章