使用python进行人员轨迹跟踪

news2025/5/18 22:21:54

一、系统概述

该系统基于计算机视觉技术,实现对视频或摄像头画面中的人员进行检测、跟踪,并生成轨迹数据。支持透视变换校准(鸟瞰图显示)、多目标跟踪、轨迹存储及视频录制功能,适用于安防监控、行为分析等场景。

二、依赖库

python

运行

import cv2         # 计算机视觉处理(OpenCV库)
import numpy as np # 数值计算
import time        # 时间处理
import os          # 文件与目录操作
from datetime import datetime # 日期时间处理

三、类定义:PersonTracker

3.1 构造函数 __init__

功能

初始化人员跟踪器,配置视频源、输出参数、背景减除器及跟踪参数。

参数说明
参数名类型默认值描述
video_sourceint/str0视频源(0为默认摄像头,或指定视频文件路径)
save_videoboolFalse是否保存处理后的视频
show_warpedboolTrue是否显示透视变换后的鸟瞰图
内部属性
  • 视频源与基础参数
    • cap:视频捕获对象(cv2.VideoCapture实例)
    • frame_width/frame_height:视频帧宽高
    • fps:帧率
  • 输出配置
    • output_folder:输出文件夹(默认output
    • out:视频写入对象(cv2.VideoWriter实例,仅当save_video=True时创建)
  • 背景减除
    • fgbg:使用MOG2算法的背景减除器,支持阴影检测
  • 跟踪参数
    • min_contour_area/max_contour_area:过滤轮廓的面积阈值(单位像素)
    • trajectories:存储轨迹的字典(键为人员 ID,值为轨迹信息)
    • max_disappeared_frames:允许目标消失的最大帧数(超过则删除轨迹)
    • max_distance:轨迹匹配的最大距离(像素)
  • 透视变换
    • perspective_transform:透视变换矩阵(校准后生成)
    • warped_width/warped_height:鸟瞰图尺寸(宽度固定 500,高度与原始帧一致)

3.2 方法列表

3.2.1 calibrate_perspective()
  • 功能:通过鼠标点击选择 4 个点,校准透视变换矩阵,生成鸟瞰图。
  • 操作说明
    1. 显示视频第一帧,按顺序点击左上、右上、右下、左下四个点,形成矩形区域。
    2. q键退出校准。
  • 返回值boolTrue为校准成功,False为取消或失败)
3.2.2 detect_persons(frame)
  • 功能:在输入帧中检测人员,返回检测结果和二值化掩码。
  • 输入frame(BGR 格式图像)
  • 处理流程
    1. 应用背景减除,生成前景掩码。
    2. 形态学操作(开运算 + 闭运算)去除噪声。
    3. 查找轮廓,过滤面积不符合阈值的轮廓。
    4. 计算每个轮廓的中心点和边界框。
  • 返回值(persons, thresh),其中:
    • persons:检测到的人员列表(每个元素为字典,包含bboxcentercontourarea
    • thresh:二值化掩码图像
3.2.3 track_persons(detected_persons)
  • 功能:根据检测结果更新人员轨迹。
  • 输入detected_personsdetect_persons返回的人员列表)
  • 算法逻辑
    1. 计算现有轨迹与新检测的匹配距离(欧氏距离),优先匹配近距离目标。
    2. 未匹配的轨迹:若连续消失超过max_disappeared_frames,则删除。
    3. 未匹配的检测:创建新轨迹,分配唯一 ID。
3.2.4 draw_results(frame, persons, thresh)
  • 功能:在图像上绘制检测框、轨迹、ID 及统计信息,支持鸟瞰图显示。
  • 输入
    • frame:原始帧
    • persons:检测到的人员列表
    • thresh:二值化掩码(未使用,仅保留接口)
  • 输出:绘制后的结果图像(若show_warped=True,则为原始帧与鸟瞰图的横向拼接图)
3.2.5 save_trajectories()
  • 功能:将当前所有轨迹数据保存到文本文件,包含 ID、起始时间、轨迹点坐标等。
  • 存储路径output_folder/trajectories_时间戳.txt
3.2.6 run()
  • 功能:运行跟踪主循环,处理视频流并实时显示结果。
  • 操作说明
    • q键退出程序。
    • s键保存当前轨迹数据。
  • 流程
    1. 调用calibrate_perspective()进行透视校准(可选)。
    2. 逐帧读取视频,检测、跟踪人员,绘制结果。
    3. 释放资源并关闭窗口。

四、主程序入口

python

运行

if __name__ == "__main__":
    tracker = PersonTracker(
        video_source=0,       # 0为摄像头,或指定视频文件路径(如"video.mp4")
        save_video=True,      # 启用视频录制
        show_warped=True      # 显示鸟瞰图
    )
    tracker.run()

五、使用说明

5.1 环境配置

  1. 安装依赖库:

    bash

    pip install opencv-python numpy
    
  2. 确保摄像头或视频文件可用。

5.2 透视校准操作

  1. 运行程序后,会弹出窗口提示选择 4 个点。
  2. 按顺序点击视频中的矩形区域四角(如地面区域),生成鸟瞰图。
  3. 校准完成后,右侧会显示鸟瞰图中的轨迹。

5.3 输出文件

  • 视频文件:若save_video=True,生成output/tracking_时间戳.avi
  • 轨迹文件:按s键生成output/trajectories_时间戳.txt,包含各 ID 的坐标序列。

六、参数调整建议

参数名作用调整场景
min_contour_area过滤小目标(如噪声)目标较小时调小,反之调大
max_contour_area过滤大目标(如多人重叠)目标较大时调大,反之调小
max_disappeared_frames目标消失后保留轨迹的帧数目标运动间隔较长时调大
max_distance轨迹匹配的最大允许距离目标运动速度快时调大
warped_width鸟瞰图宽度显示区域宽窄调整

七、注意事项

  1. 背景减除器MOG2需要一定时间学习背景(前几秒可能检测不稳定)。
  2. 透视校准的四点应选择实际场景中的矩形区域(如地面边框),以确保鸟瞰图坐标准确。
  3. 若视频帧率较低,可尝试降低warped_width或关闭show_warped以减少计算量。

完成代码

import cv2
import numpy as np
import time
import os
from datetime import datetime

class PersonTracker:
    def __init__(self, video_source=0, save_video=False, show_warped=True):
        """初始化人员跟踪器"""
        # 视频源设置
        self.video_source = video_source
        self.cap = cv2.VideoCapture(video_source)
        if not self.cap.isOpened():
            raise ValueError("无法打开视频源", video_source)
        
        # 获取视频的宽度、高度和帧率
        self.frame_width = int(self.cap.get(3))
        self.frame_height = int(self.cap.get(4))
        self.fps = self.cap.get(cv2.CAP_PROP_FPS)
        
        # 输出设置
        self.save_video = save_video
        self.output_folder = "output"
        self.show_warped = show_warped
        
        # 创建输出文件夹
        if not os.path.exists(self.output_folder):
            os.makedirs(self.output_folder)
        
        # 背景减除器
        self.fgbg = cv2.createBackgroundSubtractorMOG2(
            history=500, varThreshold=100, detectShadows=True)
        
        # 人员检测参数
        self.min_contour_area = 1000  # 最小轮廓面积
        self.max_contour_area = 50000  # 最大轮廓面积
        
        # 轨迹存储
        self.trajectories = {}  # 存储每个人的轨迹
        self.next_person_id = 1  # 下一个可用的人员ID
        self.max_disappeared_frames = 10  # 最大消失帧数
        self.max_distance = 100  # 最大匹配距离
        
        # 透视变换参数
        self.perspective_transform = None
        self.warped_width = 500
        self.warped_height = self.frame_height  # 与原始帧高度一致

        
        # 录制设置
        self.out = None
        if save_video:
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            output_path = os.path.join(self.output_folder, f"tracking_{timestamp}.avi")
            fourcc = cv2.VideoWriter_fourcc(*'XVID')
            self.out = cv2.VideoWriter(output_path, fourcc, self.fps, 
                                      (self.frame_width, self.frame_height))
    
    def calibrate_perspective(self):
        """校准透视变换,创建鸟瞰图"""
        print("请在图像中选择4个点,形成一个矩形区域,用于透视变换")
        print("按顺序点击:左上、右上、右下、左下")
        
        # 读取一帧用于选择点
        ret, frame = self.cap.read()
        if not ret:
            print("无法读取视频帧")
            return False
        
        # 创建窗口并设置鼠标回调
        cv2.namedWindow("选择透视变换点 (按 'q' 退出)")
        points = []
        
        def click_event(event, x, y, flags, param):
            if event == cv2.EVENT_LBUTTONDOWN:
                points.append((x, y))
                cv2.circle(frame, (x, y), 5, (0, 255, 0), -1)
                cv2.imshow("选择透视变换点 (按 'q' 退出)", frame)
        
        cv2.setMouseCallback("选择透视变换点 (按 'q' 退出)", click_event)
        
        # 显示图像并等待点击
        cv2.imshow("选择透视变换点 (按 'q' 退出)", frame)
        while len(points) < 4:
            key = cv2.waitKey(1) & 0xFF
            if key == ord('q'):
                cv2.destroyAllWindows()
                return False
        
        cv2.destroyAllWindows()
        
        # 定义目标矩形
        src = np.float32(points)
        dst = np.float32([
            [0, 0],
            [self.warped_width, 0],
            [self.warped_width, self.warped_height],
            [0, self.warped_height]
        ])
        
        # 计算透视变换矩阵
        self.perspective_transform = cv2.getPerspectiveTransform(src, dst)
        return True
    
    def detect_persons(self, frame):
        """检测图像中的人物"""
        # 应用背景减除
        fgmask = self.fgbg.apply(frame)
        
        # 图像预处理
        _, thresh = cv2.threshold(fgmask, 127, 255, cv2.THRESH_BINARY)
        kernel = np.ones((5, 5), np.uint8)
        thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
        thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=3)
        
        # 查找轮廓
        contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        
        persons = []
        for contour in contours:
            area = cv2.contourArea(contour)
            if area < self.min_contour_area or area > self.max_contour_area:
                continue
            
            # 计算边界框
            x, y, w, h = cv2.boundingRect(contour)
            center = (int(x + w/2), int(y + h/2))
            
            # 计算轮廓的中心点
            M = cv2.moments(contour)
            if M["m00"] != 0:
                cX = int(M["m10"] / M["m00"])
                cY = int(M["m01"] / M["m00"])
                center = (cX, cY)
            
            persons.append({
                'bbox': (x, y, w, h),
                'center': center,
                'contour': contour,
                'area': area
            })
        
        return persons, thresh
    
    def track_persons(self, detected_persons):
        """跟踪检测到的人员"""
        # 计算当前检测点与现有轨迹的距离
        unmatched_tracks = list(self.trajectories.keys())
        unmatched_detections = list(range(len(detected_persons)))
        matches = []
        
        # 计算所有可能的匹配
        for track_id in self.trajectories:
            trajectory = self.trajectories[track_id]
            last_position = trajectory['positions'][-1]
            
            min_distance = float('inf')
            min_index = -1
            
            for i, person in enumerate(detected_persons):
                if i in unmatched_detections:
                    distance = np.sqrt((last_position[0] - person['center'][0])**2 + 
                                      (last_position[1] - person['center'][1])**2)
                    
                    if distance < min_distance and distance < self.max_distance:
                        min_distance = distance
                        min_index = i
            
            # 如果找到匹配
            if min_index != -1:
                matches.append((track_id, min_index, min_distance))
        
        # 按距离排序,优先处理距离近的匹配
        matches.sort(key=lambda x: x[2])
        
        # 应用匹配
        for match in matches:
            track_id, detection_index, _ = match
            if track_id in unmatched_tracks and detection_index in unmatched_detections:
                # 更新轨迹
                self.trajectories[track_id]['positions'].append(detected_persons[detection_index]['center'])
                self.trajectories[track_id]['last_seen'] = 0
                self.trajectories[track_id]['bbox'] = detected_persons[detection_index]['bbox']
                
                # 从待匹配列表中移除
                unmatched_tracks.remove(track_id)
                unmatched_detections.remove(detection_index)
        
        # 处理未匹配的轨迹
        for track_id in unmatched_tracks:
            self.trajectories[track_id]['last_seen'] += 1
            if self.trajectories[track_id]['last_seen'] > self.max_disappeared_frames:
                del self.trajectories[track_id]
        
        # 处理未匹配的检测结果
        for detection_index in unmatched_detections:
            # 创建新轨迹
            self.trajectories[self.next_person_id] = {
                'positions': [detected_persons[detection_index]['center']],
                'last_seen': 0,
                'bbox': detected_persons[detection_index]['bbox'],
                'start_time': time.time()
            }
            self.next_person_id += 1
    
    def draw_results(self, frame, persons, thresh):
        """在图像上绘制检测和跟踪结果"""
        output = frame.copy()
        
        # 绘制检测到的人物
        for person in persons:
            x, y, w, h = person['bbox']
            cv2.rectangle(output, (x, y), (x + w, y + h), (0, 255, 0), 2)
            cv2.circle(output, person['center'], 5, (0, 0, 255), -1)
        
        # 绘制轨迹
        for track_id, trajectory in self.trajectories.items():
            positions = trajectory['positions']
            
            # 绘制轨迹线
            for i in range(1, len(positions)):
                cv2.line(output, positions[i-1], positions[i], (255, 0, 0), 2)
            
            # 绘制轨迹点
            for pos in positions:
                cv2.circle(output, pos, 3, (255, 0, 0), -1)
            
            # 绘制ID和轨迹长度
            if len(positions) > 0:
                last_pos = positions[-1]
                cv2.putText(output, f"ID: {track_id}", 
                           (last_pos[0] + 10, last_pos[1] - 20),
                           cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 0, 0), 2)
                cv2.putText(output, f"Points: {len(positions)}", 
                           (last_pos[0] + 10, last_pos[1]),
                           cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 0, 0), 2)
        
        # 显示统计信息
        cv2.putText(output, f"Persons: {len(self.trajectories)}", 
                   (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
        cv2.putText(output, f"FPS: {int(self.fps)}", 
                   (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
        
        # 创建结果显示窗口
        if self.show_warped and self.perspective_transform is not None:
            # 创建鸟瞰图
            warped = cv2.warpPerspective(output, self.perspective_transform, 
                                        (self.warped_width, self.warped_height))
            
            # 在鸟瞰图上绘制轨迹
            for track_id, trajectory in self.trajectories.items():
                positions = trajectory['positions']
                for i in range(1, len(positions)):
                    # 将原始坐标转换为鸟瞰图坐标
                    pos1 = np.array([[positions[i-1][0], positions[i-1][1]]], dtype=np.float32).reshape(-1, 1, 2)
                    pos2 = np.array([[positions[i][0], positions[i][1]]], dtype=np.float32).reshape(-1, 1, 2)
                    
                    warped_pos1 = cv2.perspectiveTransform(pos1, self.perspective_transform)[0][0]
                    warped_pos2 = cv2.perspectiveTransform(pos2, self.perspective_transform)[0][0]
                    
                    cv2.line(warped, (int(warped_pos1[0]), int(warped_pos1[1])),
                            (int(warped_pos2[0]), int(warped_pos2[1])), (255, 0, 0), 2)
            
            # 合并显示
            combined = np.hstack((output, warped))
            return combined
        
        return output
    
    def save_trajectories(self):
        """保存轨迹数据到文件"""
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        output_path = os.path.join(self.output_folder, f"trajectories_{timestamp}.txt")
        
        with open(output_path, 'w') as f:
            f.write("Person Trajectories\n")
            f.write(f"Recorded on: {datetime.now()}\n\n")
            
            for track_id, trajectory in self.trajectories.items():
                f.write(f"Person ID: {track_id}\n")
                f.write(f"Start Time: {time.ctime(trajectory['start_time'])}\n")
                f.write(f"Duration: {time.time() - trajectory['start_time']:.2f} seconds\n")
                f.write(f"Trajectory Points: {len(trajectory['positions'])}\n")
                f.write("Positions:\n")
                
                for pos in trajectory['positions']:
                    f.write(f"  ({pos[0]}, {pos[1]})\n")
                
                f.write("\n")
        
        print(f"轨迹数据已保存到: {output_path}")
    
    def run(self):
        """运行人员跟踪系统"""
        # 首先进行透视校准
        if not self.calibrate_perspective():
            print("透视校准失败,使用原始视角")
        
        print("开始人员跟踪...")
        print("按 'q' 退出,按 's' 保存轨迹数据")
        
        frame_count = 0
        start_time = time.time()
        
        while True:
            ret, frame = self.cap.read()
            if not ret:
                break
            
            # 计算实际帧率
            frame_count += 1
            if frame_count % 10 == 0:
                elapsed_time = time.time() - start_time
                self.fps = frame_count / elapsed_time
            
            # 检测人员
            persons, thresh = self.detect_persons(frame)
            
            # 跟踪人员
            self.track_persons(persons)
            
            # 绘制结果
            result = self.draw_results(frame, persons, thresh)
            
            # 保存视频
            if self.save_video:
                self.out.write(result)
            
            # 显示结果
            cv2.imshow("人员轨迹跟踪系统 (按 'q' 退出,按 's' 保存轨迹)", result)
            
            # 按键处理
            key = cv2.waitKey(1) & 0xFF
            if key == ord('q'):
                break
            elif key == ord('s'):
                self.save_trajectories()
        
        # 释放资源
        self.cap.release()
        if self.out:
            self.out.release()
        cv2.destroyAllWindows()
        print("人员跟踪系统已关闭")

# 主程序入口
if __name__ == "__main__":
    # 创建人员跟踪器实例
    tracker = PersonTracker(
        video_source=0,  # 0表示默认摄像头,也可以指定视频文件路径
        save_video=True,  # 是否保存视频
        show_warped=True  # 是否显示鸟瞰图
    )
    
    # 运行跟踪器
    tracker.run()    

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

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

相关文章

强化学习入门:马尔科夫奖励过程二

文章目录 前言1、动作2、策略总结 前言 最近想开一个关于强化学习专栏&#xff0c;因为DeepSeek-R1很火&#xff0c;但本人对于LLM连门都没入。因此&#xff0c;只是记录一些类似的读书笔记&#xff0c;内容不深&#xff0c;大多数只是一些概念的东西&#xff0c;数学公式也不会…

JVM 双亲委派机制

一、从 JDK 到 JVM&#xff1a;Java 运行环境的基石 在 Java 开发领域&#xff0c;JDK&#xff08;Java Development Kit&#xff09;是开发者的核心工具包。它不仅包含了编译 Java 代码的工具&#xff08;如 javac&#xff09;&#xff0c;还内置了 JRE&#xff08;Java Run…

uniapp -- uCharts 仪表盘刻度显示 0.9999999 这样的值问题处理。

文章目录 🍉问题🍉解决方案🍉问题 在仪表盘上,23.8变成了 23.799999999999997 🍉解决方案 formatter格式化问题 1:在 config-ucharts.js 或 config-echarts.js 配置对应的 formatter 方法 formatter: {yAxisDemo1: function (

BGP团体属性

团体属性&#xff1a; 1、用于限制BGP路由的传递范围 2、类似于IGP协议中的tag值&#xff0c;用于对BGP路由实现标记。 团体属性的分类&#xff1a; 1、公共团体属性&#xff1a; Internet&#xff1a;默认所有路由都有该属性&#xff0c;具有该属性BGP路由发送给所有的BGP邻居…

Redis——三大策略

过期删除策略 Redis可以对key设置过期时间&#xff0c;因此需要有相应的机制将已过期的键值对删除 设置了过期时间的key会存放在过期字典中&#xff0c;可以用presist命令取消key过期时间 过期字典存储在redisDb结构中&#xff1a; typedef struct redisDb {dict *dict; …

Windows 操作系统使用 Tcping 命令检查目标主机端口是否开放

检查目标主机端口是否开放的方法已经很多了&#xff0c;网络上也有第三方网页版的检查工具&#xff0c;这篇文章给大家介绍一个实用小工具 Tcping 。 一、下载安装 Tcping 命令 Tcping 非 Windows 自带命令&#xff0c;我们需要下载 Tcping 可执行文件&#xff0c;然后将该文…

开源RTOS(实时操作系统):nuttx 编译

开源RTOS&#xff08;实时操作系统&#xff09;&#xff1a;nuttx 编译 手册&#xff1a;Installing — NuttX latest documentation 源码&#xff1a;GitHub - apache/nuttx: Apache NuttX is a mature, real-time embedded operating system (RTOS) Installing The fir…

python打包exe报错:处理文件时错误:Excel xlsx file; not supported

背景&#xff1a;最近用python写一个excel解析工具&#xff0c;然后打包成exe可执行文件的时候&#xff0c;遇到这样的问题 1.在我自己编译器运行是可以正常将上传后的excel进行解析&#xff0c;但是在打包成exe后&#xff0c;就无法正常解析excel 问题排查&#xff1a; 1.切换…

VUE3 -综合实践(Mock+Axios+ElementPlus)

目录 前言 目标 1.工程创建 2.Mock 2.1 配置Mock 扩 展 2.2 定义模拟数据 2.3 创建Mock服务器 3.导入ElementPlus 4.表格页面搭建 5.动态路由跳转 6.详情页面的制作 前言 基于前文 VUE3详细入门&#xff0c;我们对VUE3的基本使用有了初步的了解&#xff0c;下…

NDS3211HV单路H.264/HEVC/HD视频编码器

1产品概述 NDS3211HV单路高清编码器是一款功能强大的音/视频编码设备&#xff0c;支持2组立体声&#xff0c;同时还支持CC(CVBS)字幕。支持多种音频编码方式。该设备配备了多种音/视频输入接口&#xff1a;HD-SDI数字视频输入、HDMI高清输入&#xff08;支持CC&#xff09;、A…

LeetCode热题100--206.反转链表--简单

1. 题目 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1] 示例 2&#xff1a; 输入&#xff1a;head [1,2] 输出&#xff1a;[2,1] 示例 3&…

来一个复古的技术FTP

背景 10年前的老代码&#xff0c;需要升级springboot框架&#xff0c;在升级过程中&#xff0c;测试业务流程里&#xff0c;有FTP的下载业务&#xff0c;不管测试环境如何测试&#xff0c;都没有成功&#xff0c;最后只能自己搭建一个FTP服务器&#xff0c;写一个ftp-demo来测试…

OpenWebUI新突破,MCPO框架解锁MCP工具新玩法

大家好&#xff0c;Open WebUI 迎来重要更新&#xff0c;现已正式支持 MCP 工具服务器&#xff0c;但 MCP 工具服务器需由兼容 OpenAPI 的代理作为前端。mcpo 是一款实用代理&#xff0c;经测试&#xff0c;它能让开发者使用 MCP 服务器命令和标准 OpenAPI 服务器工具&#xff…

TRTC实时对话式AI解决方案,助力人机语音交互极致体验

近年来&#xff0c;AI热度持续攀升&#xff0c;无论是融资规模还是用户热度都大幅增长。2023 年&#xff0c;中国 AI 行业融资规模达2631亿人民币&#xff0c;较2022年上升51%&#xff1b;2024年第二季度&#xff0c;全球 AI 初创企业融资规模为 240 亿美金&#xff0c;较第一季…

Linux安全篇 --firewalld

一、Firewalld 防火墙概述 1、Firewalld 简介 firewalld 的作用是为包过滤机制提供匹配规则(或称为策略)&#xff0c;通过各种不同的规则告诉netfilter 对来自指定源、前往指定目的或具有某些协议特征的数据包采取何种处理方式为了更加方便地组织和管理防火墙,firewalld 提供…

系分论文《论系统需求分析方法及应用》

系统分析师论文范文系列 【摘要】 2022年6月&#xff0c;我作为系统分析师参与了某金融机构“智能信贷风控系统”的建设项目。该系统旨在通过对业务流程的数字化重构&#xff0c;优化信贷审批效率并降低风险。项目涉及信贷申请、资质审核、风险评估、额度审批等核心流程&#x…

LIIGO ❤️ RUST: 12 YEARS

LIIGO &#x1f496; RUST: 12 YEARS 今天是RUST语言1.0发布十周年纪念日。十年前的今天&#xff0c;2015年的今天&#xff0c;Rust 1.0 正式发行。这是值得全球Rust支持者隆重纪念的日子。我借此机会衷心感谢Rust语言创始人Graydon Hoare&#xff0c;Mozilla公司&#xff0c;…

Trivy:让你时刻掌控的开源安全扫描器

深入了解 Trivy:全面的安全扫描工具 在如今互联网快速发展的时代,软件的安全性显得尤为重要。随着应用程序的复杂性增加,其可能带来的安全漏洞也在不断增多。如何快速、准确地发现这些潜在威胁是每个开发者和运维人员心中的课题。今天,我们将为大家介绍一个开源的安全扫描…

LlamaIndex 第八篇 MilvusVectorStore

本指南演示了如何使用 LlamaIndex 和 Milvus 构建一个检索增强生成&#xff08;RAG&#xff09;系统。 RAG 系统将检索系统与生成模型相结合&#xff0c;根据给定的提示生成新的文本。该系统首先使用 Milvus 等向量相似性搜索引擎从语料库中检索相关文档&#xff0c;然后使用生…

2022河南CCPC(前四题)

签到题目 #include <bits/stdc.h> using namespace std; #define int long long #define PII pair<int,int> #define fi first #define se second #define endl \n #define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);void solve() {int n;cin>>…