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和讯为电子多目标检测已实现。

相关文章
|
9天前
|
人工智能 前端开发 小程序
2024年12月30日蜻蜓蜻蜓AI工具系统v1.0.0发布-优雅草科技本产品前端源代码已对外开源可免费商用-优雅草老八
2024年12月30日蜻蜓蜻蜓AI工具系统v1.0.0发布-优雅草科技本产品前端源代码已对外开源可免费商用-优雅草老八
2024年12月30日蜻蜓蜻蜓AI工具系统v1.0.0发布-优雅草科技本产品前端源代码已对外开源可免费商用-优雅草老八
|
5天前
|
机器学习/深度学习 人工智能 自然语言处理
AigcPanel:开源的 AI 虚拟数字人系统,一键安装开箱即用,支持视频合成、声音合成和声音克隆
AigcPanel 是一款开源的 AI 虚拟数字人系统,支持视频合成、声音克隆等功能,适用于影视制作、虚拟主播、教育培训等多种场景。
67 12
AigcPanel:开源的 AI 虚拟数字人系统,一键安装开箱即用,支持视频合成、声音合成和声音克隆
|
6天前
|
存储 人工智能 开发框架
Eliza:TypeScript 版开源 AI Agent 开发框架,快速搭建智能、个性的 Agents 系统
Eliza 是一个开源的多代理模拟框架,支持多平台连接、多模型集成,能够快速构建智能、高效的AI系统。
73 8
Eliza:TypeScript 版开源 AI Agent 开发框架,快速搭建智能、个性的 Agents 系统
|
4天前
|
机器学习/深度学习 人工智能 监控
AI在交通管理系统中的应用
AI在交通管理系统中的应用
36 23
|
13天前
|
人工智能 自然语言处理 并行计算
ASAL:Sakana AI 联合 OpenAI 推出自动探索人工生命的系统,通过计算机模拟生命进化的过程
ASAL 是由 Sakana AI 联合 OpenAI 等机构推出的自动化搜索人工生命系统,基于基础模型实现多种搜索机制,扩展了人工生命研究的边界。
65 1
ASAL:Sakana AI 联合 OpenAI 推出自动探索人工生命的系统,通过计算机模拟生命进化的过程
|
27天前
|
存储 人工智能 vr&ar
转载:【AI系统】CPU 基础
CPU,即中央处理器,是计算机的核心部件,负责执行指令和控制所有组件。本文从CPU的发展史入手,介绍了从ENIAC到现代CPU的演变,重点讲述了冯·诺依曼架构的形成及其对CPU设计的影响。文章还详细解析了CPU的基本构成,包括算术逻辑单元(ALU)、存储单元(MU)和控制单元(CU),以及它们如何协同工作完成指令的取指、解码、执行和写回过程。此外,文章探讨了CPU的局限性及并行处理架构的引入。
转载:【AI系统】CPU 基础
|
23天前
|
人工智能 安全 算法
CAMEL AI 上海黑客松重磅来袭!快来尝试搭建你的第一个多智能体系统吧!
掌握多智能体系统,🐫 CAMEL-AI Workshop & 黑客马拉松即将启航!
CAMEL AI 上海黑客松重磅来袭!快来尝试搭建你的第一个多智能体系统吧!
|
27天前
|
人工智能 缓存 并行计算
转载:【AI系统】CPU 计算本质
本文深入探讨了CPU计算性能,分析了算力敏感度及技术趋势对CPU性能的影响。文章通过具体数据和实例,讲解了CPU算力的计算方法、算力与数据加载之间的平衡,以及如何通过算力敏感度分析优化计算系统性能。同时,文章还考察了服务器、GPU和超级计算机等平台的性能发展,揭示了这些变化如何塑造我们对CPU性能的理解和期待。
转载:【AI系统】CPU 计算本质
|
27天前
|
机器学习/深度学习 存储 人工智能
转载:【AI系统】计算之比特位宽
本文详细介绍了深度学习中模型量化操作及其重要性,重点探讨了比特位宽的概念,包括整数和浮点数的表示方法。文章还分析了不同数据类型(如FP32、FP16、BF16、FP8等)在AI模型中的应用,特别是FP8数据类型在提升计算性能和降低内存占用方面的优势。最后,文章讨论了降低比特位宽对AI芯片性能的影响,强调了在不同应用场景中选择合适数据类型的重要性。
转载:【AI系统】计算之比特位宽
|
27天前
|
机器学习/深度学习 人工智能 算法
转载:【AI系统】关键设计指标
本文介绍了AI芯片的关键设计指标及其与AI计算模式的关系,涵盖计算单位(如OPS、MACs、FLOPs)、关键性能指标(精度、吞吐量、时延、能耗、成本、易用性)及优化策略,通过算术强度和Roofline模型评估AI模型在芯片上的执行性能,旨在帮助理解AI芯片设计的核心考量与性能优化方法。
转载:【AI系统】关键设计指标
下一篇
开通oss服务