AI项目二十三:危险区域识别系统

news2024/11/21 0:37:39

若该文为原创文章,转载请注明原文出处。

一、介绍

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

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

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

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

记录下PC端测试情况。

检测流程:

1、使用YOLOV5识别人物

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

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

二、环境搭建

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

项目结构

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

代码需要注意的是:

一、区域位置

二、显示参数位置

这几个参数需要根据视频的大小,去调整位置,不然会报错。

三、检测点是否在区域内

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

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

如有侵权,或需要完整代码,请及时联系博主。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1837918.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

提升人工智能大模型的智能

前言 提升人工智能大模型的智能是一个涉及到多方面挑战和策略的复杂问题。下面是一些关键的策略和挑战&#xff0c;可以帮助我们更好地理解和处理这一问题。 策略 模型架构与深度优化&#xff1a; 深度学习架构优化&#xff1a;设计更深、更复杂的神经网络结构&#xff0c;如…

python GUI开发: tkinter菜单创建,记事本和画图软件综合项目的实战演练

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

【Nginx系列】反向代理在现代网络架构中的重要性

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

电动汽车厂商Rivian将全新设计元素融入由虚幻引擎驱动的车机界面

Rivian Automotive&#xff08;简称&#xff1a;“Rivian”&#xff09;&#xff0c;是美国一家电动汽车厂商&#xff0c;该品牌创办于2009年&#xff0c;总部位于加州埃尔文&#xff0c;专注于生产电动皮卡车Rivian R1T和电动SUV Rivian R1S。 Rivian的车主们正追寻这样一条道…

做动画?Animatediff 和 ComfyUI 更配哦!

如果从工作流和内存利用率的角度来说&#xff0c;Animatediff 和 ComfyUI 可能更配一些&#xff0c;毕竟制作动画是一个很吃内存的操作。 首先&#xff0c;我们需要在管理器中下载 Animatediff 插件&#xff0c;当然也可以直接导入听雨的工作流&#xff0c;然后在管理器的安装…

Chromium 开发指南2024 Mac篇-开始编译Chromium(五)

1.引言 在之前的指南中&#xff0c;我们已经详细介绍了在 macOS 上编译和开发 Chromium 的准备工作。您学会了如何安装和配置 Xcode&#xff0c;如何下载和配置 depot_tools&#xff0c;以及如何获取 Chromium 的源代码。通过这些步骤&#xff0c;您的开发环境已经搭建完毕&am…

压力应变桥信号变送光电隔离放大模块PCB焊接式 差分信号输入0-10mV/0-20mV/0-±10mV/0-±20mV转0-5V/0-10V/4-20mA

概述&#xff1a; IPO压力应变桥信号处理系列隔离放大器是一种将差分输入信号隔离放大、转换成按比例输出的直流信号混合集成厚模电路。产品广泛应用在电力、远程监控、仪器仪表、医疗设备、工业自控等行业。该模块内部嵌入了一个高效微功率的电源&#xff0c;向输入端和输出端…

STM32CubeMX 安装教程

目录 总体讲解 1.0 java下载 1.1 CubeMx下载 2.0 java安装 2.1 CubMx安装 总体讲解 本次文章讲解CubMx的下载及安装&#xff0c;由于CubMx的运行环境需要java&#xff0c;所以我们需要先下载java的环境。 1.0 java下载 站内java8版本下载&#xff1a; https://download…

数字人源码部署该如何选对数字人源头工厂?

数字人作为AI产业的中流砥柱&#xff0c;其应用场景之广泛。从数字人口播、到直播到数字人克隆、到声音克隆、再至AI复活、数字人名片、数字人员工、数字人客服、3D息影舱智能交互、要知道这一切仅仅只是用了两年的时间&#xff0c;可见我国的AI技术取得突破性发展. 如果把时间…

Matlab绘制三维图像(论文插图)

Matlab绘制三维图像 hfigure; % 创建 surf surf(PHDeformed_1Unwrap); shading interp;lightangle(45,75); % 创建 zlabel zlabel(Z(phase/rad),FontWeight,bold,FontName,Times New Roman); % 创建 ylabel ylabel(Y(pixel),FontWeight,bold,FontName,Times New Roman); % 创建…

细说MCU输出互补型PWM波形的实现方法

目录 一、硬件及工程 二、建立工程 1、TIM1引脚 2、建立工程 &#xff08;1&#xff09;配置GPIO &#xff08;2&#xff09;选择时钟源和Debug模式 &#xff08;3&#xff09;配置定时器 &#xff08;4&#xff09;配置中断 &#xff08;5&#xff09;配置系统时钟 …

C# 与三菱PLC MC协议通讯

1. 引用HslCommunication Nuget包里边添加 HslCommunication包的引用 2.创建PLC连接对象&#xff0c;并通过 IP&#xff0c;端口进行连接 //PLC连接对象 var plc new MelsecMcNet(_ip, _port); plc.ConnectTimeOut 3000;var res plc.ConnectServer();//连接PLCisConnect …

JavaFX菜单(Menu)

菜单是桌面应用程序选择选项的标准方法。 菜单和菜单项可以与选择选项快捷键组合&#xff0c;称为键盘快捷键。 创建菜单和菜单项 必须创建一个菜单栏javafx.scene.control.MenuBar对象来保存javafx.scene.control.Menu对象。 菜单对象可以包含Menu和javafx.scene.control.Me…

思维+构造 CF1950F - 0, 1, 2, Tree!

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 1950F - 0, 1, 2, Tree! 二、解题报告 1、思路分析 考虑让构造n个结点的二叉树如何构造高度最小&#xff1f; 构造完全二叉树&#xff0c;即一层一层放 对于本题&#xff0c;显然我们要先放“2”结点&…

十六.吊打面试官系列-JVM优化-JVM性能调优实战

前言 在Java应用的开发和运维过程中&#xff0c;JVM的性能调优是一项至关重要的工作。随着业务的增长和复杂度的提升&#xff0c;线上问题排查、内存监控、参数优化以及压力测试成为每一位开发者和运维人员必须面对的挑战。 本篇文章将带您走进JVM性能调优的世界&#xff0c;…

agentsim流程分析

agentsim 前言 这里是类斯坦福小镇项目agentsim的一个调研。主要目的是寻找行为树模式的氛围npc不够智能的解决方案。下面会先简单介绍下一些关键的类&#xff0c;然后再讲解流程。该项目有段时间没维护了&#xff0c;没法直接运行&#xff0c;有兴趣的可以修修&#xff0c;主…

乘法与位运算

目录 描述 输入描述&#xff1a; 输出描述&#xff1a; 参考代码 描述 题目描述&#xff1a; 进行一个运算单元的电路设计&#xff0c;A[7:0]*11111011&#xff0c;尽量用最少的资源实现&#xff0c;写出对应的 RTL 代码。 信号示意&#xff1a; A信号输入 B 信号…

MySQL 的故事:一场 SQL 语句的戏剧演绎

本文由 ChatMoney团队出品 第一幕&#xff1a;解析与优化 - “翻译官与谋士” SQL 解析器是第一个上场的角色&#xff0c;任务就是把 SQL 请求翻译成 MySQL 能听懂的语言。就像你点餐时&#xff0c;服务员得听懂你到底要什么菜。不然你说“我要一盘炒青菜”&#xff0c;结果服…

gitlab2024最新版安装

系统&#xff1a;redhat9.0 gitlab版本&#xff1a;gitlab-ce-16.10.7-ce.0.el9.x86_64.rpm 安装组件&包依赖&#xff1a;https://packages.gitlab.com/gitlab/gitlab-ce/packages/ol/9/gitlab-ce-16.10.7-ce.0.el9.x86_64.rpm 参考&#xff1a; 前提&#xff1a; 下载gitl…

【车载开发系列】CAN通信总线再理解(上篇)

【车载开发系列】CAN通信总线再理解&#xff08;上篇&#xff09; 【车载开发系列】CAN通信总线再理解上篇 【车载开发系列】CAN通信总线再理解&#xff08;上篇&#xff09;一. CAN的概念1&#xff09;硬件组成2&#xff09;编码与负载3&#xff09;收发数据4&#xff09;半双…