大模型开发:源码分析 Qwen 2.5-VL 视频抽帧模块(附加FFmpeg 性能对比测试)
目录
qwen 视频理解能力
messages 构建 demo
qwen 抽帧代码分析
验证两个实际 case
官网介绍图
性能对比:ffmpeg 抽帧、decord 库抽帧
介绍
联系
对比
测试结果
测试明细
ffmpeg
100 qps 测试(CPU)
decord
100 qps 测试(CPU)
100 qps 测试(GPU)
本文也录制了详细的视频讲解:
[IT超016] 大模型:源码分析Qwen2.5VL视频抽帧模块(附加FFmpeg性能对比测试)_哔哩哔哩_bilibili
[IT超016] 大模型:源码分析Qwen2.5VL视频抽帧模块(附加FFmpeg性能对比测试)
qwen 视频理解能力
Qwen2.5-VL 是由阿里云 Qwen 团队开发的多模态大型语言模型系列,仓库地址:https://github.com/QwenLM/Qwen2.5-VL
messages 构建 demo
# 方式一:输入视频文件(这种才会走抽帧逻辑)
messages = [{"role": "user","content": [{"type": "video","video": "file:///path/to/video1.mp4","max_pixels": 360 * 420,"fps": 1.0,},{"type": "text", "text": "Describe this video."},],}
]# 方式二:直接输入多图
messages = [{"role": "user","content": [{"type": "video","video": ["file:///path/to/frame1.jpg","file:///path/to/frame2.jpg","file:///path/to/frame3.jpg","file:///path/to/frame4.jpg",],},{"type": "text", "text": "Describe this video."},],}
]
qwen 抽帧代码分析
视频 message 处理的核心代码:https://github.com/QwenLM/Qwen2.5-VL/blob/main/qwen-vl-utils/src/qwen_vl_utils/vision_process.py
视频解析抽帧能力依赖——decord 库:https://github.com/dmlc/decord?tab=readme-ov-file#install-from-source
Decord 是一个专门为视频数据处理和深度学习设计的轻量级、高性能的视频解码库,擅长处理帧的随机访问模式,避免了像 FFmpeg 那样从头开始逐帧解码——Qwen 抽帧模块用的这个库
1、vision_process.py # process_vision_info:处理 messages 中的 图像 / 视频 输入
2、vision_process.py # fetch_video:处理 messages 中的 视频 输入
🚩 核心抽帧逻辑(简单来说:0.5 秒抽一张)(30 秒视频,最终抽帧是 60 张)
根据 FPS 常数(默认 2)、视频总帧数(秒时长 * 原始 fps)计算抽帧数量 nframes,之后等距离/步长抽取 nframes 张帧图
- 可解析总帧数 = 秒时长 * 原始 fps ———— 例如 30s 视频,24 fps,值为 720
- 抽帧数 = FPS 常数(默认 2)* 秒时长 ————例如 30s 视频,值为 60张
- 抽帧步长:默认 0.5 秒————(等距步长平均分割,和 FPS 常数有关)
验证两个实际 case
录屏设置:24 fps
方案 | 30秒 的视频 | 1分30秒 的视频 |
qwen 抽帧 | 加入日志
... | 加入日志
... |
摘出 qwen 2.5-vl 抽帧模块代码(增加自定义日志)
import torch
import time
import math
from typing import Tuple
from torchvision.utils import save_imageIMAGE_FACTOR = 28
MIN_PIXELS = 4 * 28 * 28
MAX_PIXELS = 16384 * 28 * 28
MAX_RATIO = 200VIDEO_MIN_PIXELS = 128 * 28 * 28
VIDEO_MAX_PIXELS = 768 * 28 * 28
FRAME_FACTOR = 2
FPS = 2.0
FPS_MIN_FRAMES = 4
FPS_MAX_FRAMES = 768def _read_video_decord(ele: dict,
) -> Tuple[torch.Tensor, float]:"""read video using decord.VideoReaderArgs:ele (dict): a dict contains the configuration of video.support keys:- video: the path of video. support "file://", "http://", "https://" and local path.- video_start: the start time of video.- video_end: the end time of video.Returns:torch.Tensor: the video tensor with shape (T, C, H, W)."""import decordvideo_path = ele["video"]st = time.time()vr = decord.VideoReader(video_path)# TODO: support start_pts and end_ptsif 'video_start' in ele or 'video_end' in ele:raise NotImplementedError("not support start_pts and end_pts in decord for now.")total_frames, video_fps = len(vr), vr.get_avg_fps()print(f"==11: {video_path=}, {total_frames=}, {video_fps=}, time={time.time() - st:.3f}s\n")nframes = smart_nframes(ele, total_frames=total_frames, video_fps=video_fps)idx = torch.linspace(0, total_frames - 1, nframes).round().long().tolist()video = vr.get_batch(idx).asnumpy()print(f"==22: {nframes=}, {idx=}, {len(idx)=}, video: ")print("Type:", type(video))print("Shape:", video.shape)print("Data Type:", video.dtype)print("Number of dimensions:", video.ndim)print("Number of elements:", video.size)print("Size in bytes:", video.nbytes)print('\n')video = torch.tensor(video).permute(0, 3, 1, 2) # Convert to TCHW formatsample_fps = nframes / max(total_frames, 1e-6) * video_fpsreturn video, sample_fpsdef smart_nframes(ele: dict,total_frames: int,video_fps: float,
) -> int:"""calculate the number of frames for video used for model inputs.Args:ele (dict): a dict contains the configuration of video.support either `fps` or `nframes`:- nframes: the number of frames to extract for model inputs.- fps: the fps to extract frames for model inputs.- min_frames: the minimum number of frames of the video, only used when fps is provided.- max_frames: the maximum number of frames of the video, only used when fps is provided.total_frames (int): the original total number of frames of the video.video_fps (int | float): the original fps of the video.Raises:ValueError: nframes should in interval [FRAME_FACTOR, total_frames].Returns:int: the number of frames for video used for model inputs."""assert not ("fps" in ele and "nframes" in ele), "Only accept either `fps` or `nframes`"if "nframes" in ele:nframes = round_by_factor(ele["nframes"], FRAME_FACTOR)else:fps = ele.get("fps", FPS)min_frames = ceil_by_factor(ele.get("min_frames", FPS_MIN_FRAMES), FRAME_FACTOR)max_frames = floor_by_factor(ele.get("max_frames", min(FPS_MAX_FRAMES, total_frames)), FRAME_FACTOR)nframes = total_frames / video_fps * fpsif nframes > total_frames:print(f"smart_nframes: nframes[{nframes}] > total_frames[{total_frames}]")nframes = min(min(max(nframes, min_frames), max_frames), total_frames)nframes = floor_by_factor(nframes, FRAME_FACTOR)if not (FRAME_FACTOR <= nframes and nframes <= total_frames):raise ValueError(f"nframes should in interval [{FRAME_FACTOR}, {total_frames}], but got {nframes}.")return nframesdef round_by_factor(number: int, factor: int) -> int:"""Returns the closest integer to 'number' that is divisible by 'factor'."""return round(number / factor) * factordef ceil_by_factor(number: int, factor: int) -> int:"""Returns the smallest integer greater than or equal to 'number' that is divisible by 'factor'."""return math.ceil(number / factor) * factordef floor_by_factor(number: int, factor: int) -> int:"""Returns the largest integer less than or equal to 'number' that is divisible by 'factor'."""return math.floor(number / factor) * factorvideo, sample_fps = _read_video_decord(ele={"video": "150108580006469_30s.mp4"})
print(f"read_video_decord result: {video=}, {sample_fps=}\n")# 将视频帧保存为本地图片
for i, frame in enumerate(video):# 将像素值缩放到 [0, 1] 范围frame = frame.float() / 255.0save_image(frame, f'./video-frame-30s/frame_{i}.png')# save_image(frame, f'./video-frame-1m30s/frame_{i}.png')print(f"Frame {i} saved as frame_{i}.png")
官网介绍图
性能对比:ffmpeg 抽帧、decord 库抽帧
介绍
ffmpeg 是一个强大且广泛使用的开源多媒体框架,它由多个库和工具组成,例如libavformat(处理音视频封装格式)、libavcodec(进行音视频编解码)、libavutil(提供通用的工具函数)等。在抽帧时,FFmpeg 会利用这些库协同工作。
Decord 是一个专门为视频数据处理和深度学习设计的轻量级、高性能的视频解码库,擅长处理帧的随机访问模式,避免了像 FFmpeg 那样从头开始逐帧解码
联系
decord 依赖 ffmpeg 的核心库
对比
- 速度:ffmpeg 更优,比 decord 快 16%
- 资源消耗:ffmpeg 更优,比 decord 节省资源 25%(只测了下 cpu 抽帧)
- 官方维护:
-
- ffmpeg 一直在更新,社区也更活跃,48.9k star
- decord 库已经 3 年未更新,2.1k star
测试结果
测试指标:
- 100 batch 视频文件测试
- 开发机:train-A100-6 配置为 94核 - 860GiB - 4卡A100
| 抽帧方案 | 测试样本(37秒视频) video_150108527915923_37s.mp4 | 测试样本(1分21秒视频)video_150108525914511_1m21s.mp4 |
现状 | ffmpeg - cpu | 总耗时: 4.18 秒 平均耗时: 2829.07 毫秒 成功数: 100 失败数: 0
抽出 37 张 + 写入磁盘
CPU核数换算——需 7 核(94*6%*120%) | 总耗时: 12.09 秒 平均耗时: 9383.33 毫秒 成功数: 100 失败数: 0
抽出 81 张 + 写入磁盘
CPU核数换算——需 23 核(94*22%*120%) |
新方案 | decord - cpu | 总耗时: 5.33 秒 平均耗时: 3352.33 毫秒 成功数: 100 失败数: 0
抽出 38 张 + 写入磁盘
CPU核数换算——需 7 核(94*7%*120%) | 总耗时: 15.89 秒 平均耗时: 12617.40 毫秒 成功数: 100 失败数: 0
抽出 85 张 + 写入磁盘
CPU核数换算——需 24 核(94*25%*120%) |
| decord - gpu | 环境不兼容 | 环境不兼容 |
测试明细
ffmpeg
# 登陆开发机
ffmpeg -i /root/zhoulongchao/script/resource/video_150108527915923_37s.mp4 -map 0:v -q:v 3 -vsync 0 -f image2 -vf fps=1 -y ./%d.jpg
100 qps 测试(CPU)
cd /root/zhoulongchao/script/ffmpeg
vim demo-ffmpeg.py
python demo-ffmpeg.py
import subprocess
import time
from concurrent.futures import ThreadPoolExecutordef run_ffmpeg_command():# FFmpeg 命令command = ['ffmpeg', '-i', '/root/zhoulongchao/script/resource/video_150108525914511_1m21s.mp4','-map', '0:v', '-q:v', '3', '-vsync', '0', '-f', 'image2', '-vf', 'fps=1', '-y', './%d.jpg']start_time = time.time()# 运行 FFmpeg 命令result = subprocess.run(command, capture_output=True, text=True)end_time = time.time()# 计算耗时(毫秒)elapsed_time_ms = (end_time - start_time) * 1000print("FFmpeg 输出:")print(result.stdout)print("错误信息:")print(result.stderr)print(f"耗时: {elapsed_time_ms:.2f} 毫秒")# 根据返回码判断是否成功success = result.returncode == 0return elapsed_time_ms, successif __name__ == "__main__":# 目标 QPStarget_qps = 100# 每个请求的间隔时间(秒)interval = 1 / target_qpstotal_elapsed_time = 0all_elapsed_times = []success_count = 0failure_count = 0with ThreadPoolExecutor(max_workers=target_qps) as executor:start_time = time.time()futures = []for _ in range(target_qps):future = executor.submit(run_ffmpeg_command)futures.append(future)time.sleep(interval)for future in futures:elapsed_time, success = future.result()all_elapsed_times.append(elapsed_time)total_elapsed_time += elapsed_timeif success:success_count += 1else:failure_count += 1end_time = time.time()average_elapsed_time = total_elapsed_time / target_qps if target_qps > 0 else 0print(f"总耗时: {end_time - start_time:.2f} 秒")print(f"平均耗时: {average_elapsed_time:.2f} 毫秒")print(f"成功数: {success_count}")print(f"失败数: {failure_count}")
decord
cd /root/zhoulongchao/script/decord
vim main.py
python main.py
100 qps 测试(CPU)
import cv2
import time
from decord import VideoReader
from decord import cpu
from concurrent.futures import ProcessPoolExecutor
import multiprocessingdef process_video(video_path):start_time = time.time()try:vr = VideoReader(video_path, ctx=cpu(0))fps = vr.get_avg_fps()interval = int(fps)for i in range(0, len(vr), interval):frame = vr[i].asnumpy()frame_bgr = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)cv2.imwrite(f'frame_{i}.jpg', frame_bgr)end_time = time.time()elapsed_time = (end_time - start_time) * 1000return elapsed_time, Trueexcept Exception:end_time = time.time()elapsed_time = (end_time - start_time) * 1000return elapsed_time, Falseif __name__ == "__main__":video_path = '/root/zhoulongchao/script/resource/video_150108527915923_37s.mp4'target_qps = 100interval = 1 / target_qpstotal_elapsed_time = 0success_count = 0failure_count = 0# 获取系统的 CPU 核心数量cpu_count = multiprocessing.cpu_count()with ProcessPoolExecutor(max_workers=cpu_count) as executor:start_time = time.time()futures = []for _ in range(target_qps):future = executor.submit(process_video, video_path)futures.append(future)time.sleep(interval)for future in futures:elapsed_time, success = future.result()total_elapsed_time += elapsed_timeif success:success_count += 1else:failure_count += 1end_time = time.time()average_elapsed_time = total_elapsed_time / target_qps if target_qps > 0 else 0print(f"总耗时: {end_time - start_time:.2f} 秒")print(f"平均耗时: {average_elapsed_time:.2f} 毫秒")print(f"成功数: {success_count}")print(f"失败数: {failure_count}")
100 qps 测试(GPU)
》这种方式环境配置失败了,暂时只写了一半
1、安装用于构建共享库的系统包 Ubuntu 运行:
# official PPA comes with ffmpeg 2.8, which lacks tons of features, we use ffmpeg 4.0 here
add-apt-repository ppa:jonathonf/ffmpeg-4 # for ubuntu20.04 official PPA is already version 4.2, you may skip this step
apt-get update
apt-get install -y build-essential python3-dev python3-setuptools make cmake
apt-get install -y ffmpeg libavcodec-dev libavfilter-dev libavformat-dev libavutil-dev
# note: make sure you have cmake 3.8 or later, you can install from cmake official website if it's too old
2、递归克隆 repo(重要)
git clone --recursivehttps://github.com/dmlc/decord
3、在源根目录中构建共享库(指定-DUSE_CUDA=ON或-DUSE_CUDA=/path/to/cuda或-DUSE_CUDA=ON-DCMAKE_CUDA_COMPILER=/path/to/cuda/nvcc启用 NVDEC 硬件加速解码)(要指定自定义的 FFMPEG 库路径,请使用“-DFFMPEG_DIR=/path/to/ffmpeg”):
cd /root/zhoulongchao/script/decord
cd decord
mkdir build && cd build
cmake .. -DUSE_CUDA=ON -DCMAKE_BUILD_TYPE=Release
make
请注意,如果您遇到了问题libnvcuvid.so,可能是由于缺少链接 libnvcuvid.so,可以手动找到它(ldconfig -p | grep libnvcuvid)并将库链接到,CUDA_TOOLKIT_ROOT_DIR\lib64以便decord顺利检测并链接正确的库。或者——
Video Codec SDK - Get Started | NVIDIA Developer
mv libnvcuvid.so /usr/local/cuda/lib64/
4、安装python绑定:
cd ../python
# option 1: add python path to $PYTHONPATH, you will need to install numpy separately
pwd=$PWD
echo "PYTHONPATH=$PYTHONPATH:$pwd" >> ~/.bashrc
source ~/.bashrc
# option 2: install with setuptools
python3 setup.py install --user
make
import cv2
import time
from decord import VideoReader
from decord import gpu
from concurrent.futures import ProcessPoolExecutor
import multiprocessingdef process_video(video_path):start_time = time.time()try:# 修改为使用 GPU 进行解码vr = VideoReader(video_path, ctx=gpu(0))fps = vr.get_avg_fps()interval = int(fps)for i in range(0, len(vr), interval):frame = vr[i].asnumpy()frame_bgr = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)cv2.imwrite(f'frame_{i}.jpg', frame_bgr)end_time = time.time()elapsed_time = (end_time - start_time) * 1000return elapsed_time, Trueexcept Exception:end_time = time.time()elapsed_time = (end_time - start_time) * 1000return elapsed_time, Falseif __name__ == "__main__":video_path = '/root/zhoulongchao/script/resource/video_150108527915923_37s.mp4'target_qps = 100interval = 1 / target_qpstotal_elapsed_time = 0success_count = 0failure_count = 0# 获取系统的 CPU 核心数量cpu_count = multiprocessing.cpu_count()with ProcessPoolExecutor(max_workers=cpu_count) as executor:start_time = time.time()futures = []for _ in range(target_qps):future = executor.submit(process_video, video_path)futures.append(future)time.sleep(interval)for future in futures:elapsed_time, success = future.result()total_elapsed_time += elapsed_timeif success:success_count += 1else:failure_count += 1end_time = time.time()average_elapsed_time = total_elapsed_time / target_qps if target_qps > 0 else 0print(f"总耗时: {end_time - start_time:.2f} 秒")print(f"平均耗时: {average_elapsed_time:.2f} 毫秒")print(f"成功数: {success_count}")print(f"失败数: {failure_count}")
相关文章:
大模型开发:源码分析 Qwen 2.5-VL 视频抽帧模块(附加FFmpeg 性能对比测试)
目录 qwen 视频理解能力 messages 构建 demo qwen 抽帧代码分析 验证两个实际 case 官网介绍图 性能对比:ffmpeg 抽帧、decord 库抽帧 介绍 联系 对比 测试结果 测试明细 ffmpeg 100 qps 测试(CPU) decord 100 qps 测试&#x…...
单调栈 —— 1.基本概念与核心算法
1. 基本概念 1.1 知识预备 在理解单调栈之前,我们需要先掌握两个基础概念:栈(Stack) 和 单调性(Monotonicity)。 什么是栈(Stack) 栈是一种**后进先出(LIFO, Last-In…...
Ollama部署大模型 (完整版本、网速慢处理、聊天界面)
切记!切记!切记! Ollama软件下载的模型一般都是别人微调好的,且模型文件与HuggingFace等平台不一样,使用为主,没有官方API可以对模型微调(教程都是cpp这类的,没必要这么麻烦去操作&a…...
CMake中add_custom_command用法详解
add_custom_command 是 CMake 中用于在构建过程中添加自定义命令的工具。它通常用于生成文件或在构建特定目标前后执行操作。其行为和执行时机取决于具体使用场景。 主要用法 add_custom_command 有两种典型用法: 1. 生成文件(Generating Files&#x…...
基于疾风大模型的新能源储能优化系统:方法、实现与案例分析
一、引言 随着可再生能源渗透率不断提高,储能系统在电力系统中的重要性日益凸显。传统储能控制方法主要基于规则策略和简单优化算法,难以应对高比例新能源场景下的复杂决策需求。本文将详细介绍如何利用疾风大模型(Gale Model)构建智能化的新能源储能优化系统,包含核心方…...
Large Language Model(LLM)的训练和微调
之前一个偏工程向的论文中了,但是当时对工程理论其实不算很了解,就来了解一下 工程流程 横轴叫智能追寻 竖轴上下文优化 Prompt不行的情况下加shot(提示),如果每次都要加提示,就可以试试知识库增强检索来给提示。 如果希望增强…...
Windows 系统中安装 Git 并配置 GitHub 账户
由于电脑重装系统,重新配置了git. 以下是在 Windows 系统中安装 Git 并配置 GitHub 账户的详细步骤: 1. 安装 Git 访问 Git 官网下载页面下载 Windows 版本的 Git 安装程序运行安装程序,使用默认选项即可 2. 配置 Git 用户信息 打开命令…...
KWDB创作者计划—KWDB场景化创新实践:多模态数据融合与边缘智能的突破性应用
引言:AIoT时代的数据库范式重构 在工业物联网设备数量突破千亿、边缘计算节点覆盖率达75%的2025年,传统数据库面临多模态数据处理效率低下、边缘端算力利用率不足、跨域数据协同困难等核心挑战。KWDB(KaiwuDB Community Edition)通…...
波束形成(BF)从算法仿真到工程源码实现-第四节-最小方差无失真响应波束形成(MVDR)
一、概述 本节我们讨论最 小 方 差 无 失 真 响 应 (Minimum Variance Distortionless Response, MVDR)波束形成算法,包括原理分析及代码实现。 更多资料和代码可以进入https://t.zsxq.com/qgmoN ,同时欢迎大家提出宝贵的建议,以共同探讨学习…...
初阶数据结构--链式二叉树
二叉树(链式结构) 前面的文章首先介绍了树的相关概念,阐述了树的存储结构是分为顺序结构和链式结构。其中顺序结构存储的方式叫做堆,并且对堆这个数据结构进行了模拟实现,并进行了相关拓展,接下来会针对链…...
嵌入式硬件篇---单片机周期
文章目录 前言 前言 在单片机中,时序控制是其执行指令和协调外设的核心基础。以下是单片机中常见的各种周期及其详细说明,以层次结构展开: 时钟周期(Clock Cycle) 定义: 时钟周期是单片机的最小时间单位&a…...
嵌入式硬件篇---加法减法积分微分器
文章目录 前言 前言 在模拟电子技术中,加法器、减法器、积分器和微分器是基本的运算电路,通常基于运算放大器(运放)实现。以下是它们的核心原理、典型结构和应用场景: 加法器(Summing Amplifier࿰…...
解决使用VsCode远程ssh连接虚拟机ubuntu需要重复输入密码
1. windows打开windows powershell并输入如下命令 ssh-keygen -t ed25519 -C 你的随意一个邮箱2. 从路径C:\Users\PC.ssh下找到id_ed25519.pub并打开 复制里面全部内容 3. 切换到ubuntu $ cd .ssh/ $ vi authorized_keys 将前一步复制的内容粘贴进去并保存4. vscode重新连接…...
1558 找素数
1558 找素数 ⭐️难度:中等 🌟考点:质数 📖 📚 import java.util.Scanner; import java.util.Arrays;public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int a sc.…...
[Android] PDF编辑器 Xodo PDF Reader 9.13.3 (不完全汉化,能用)
[Android] PDF编辑器 Xodo PDF 链接:https://pan.xunlei.com/s/VONeDpxJVwfmeSZu36RvZzSfA1?pwdv67d# 全面的 PDF 查看和批注 支持多种文件格式,包括 PDF 和 Microsoft Office 文档。提供用于添加注释、突出显示文本和为内容添加下划线的工具。包括夜…...
STM32LL库编程系列第八讲——ADC模数转换
系列文章目录 往期文章 STM32LL库编程系列第一讲——Delay精准延时函数(详细,适合新手) STM32LL库编程系列第二讲——蓝牙USART串口通信(步骤详细、原理清晰) STM32LL库编程系列第三讲——USARTDMA通信 STM32LL库编程…...
forms+windows添加激活水印
formswindows添加激活水印 多语言水印文本,根据系统语言自动切换。水印显示在每个屏幕的右下角,位置动态调整。半透明灰色文字,微软雅黑字体。窗口无边框、置顶、透明背景,不干扰用户操作。支持多显示器。高DPI适配。 效果图&am…...
ubuntu 服务器版本网络安全
1. 系统更新与补丁管理 定期更新系统 sudo apt update && sudo apt upgrade -y # 更新所有软件包 sudo apt autoremove # 清理旧内核和依赖启用自动安全更新 修改 /etc/apt/apt.conf.d/50unattended-upgrades,确保安全更新自动安装: Unatt…...
C++之map,set的实现
目录 一、红黑树的修改 1.1、节点结构 1.2、迭代器 1.3、红黑树的结构 二、map的封装 三、set的封装 一、红黑树的修改 首先,我们使用红黑树来封装map和set,其次我们实现的map和set想要复用同一个红黑树,所以我们需要对之…...
Elasticsearch:使用稀疏向量提升相关性
作者:来自 Elastic Vincent Bosc 学习如何在 Elasticsearch 中使用稀疏向量,以最小的复杂性提升相关性并实现搜索结果个性化。 稀疏向量是 ELSER 中的关键组件,但它们的用途远不止于此。在这篇文章中,我们将探讨稀疏向量如何在电商…...
SQL:Normalization(范式化)
目录 Normalization(范式化) 为什么需要 Normalization? 🧩 表格分析: 第一范式(1NF) 什么是第一范式(First Normal Form)? 第二范式(2NF&am…...
在pycharm中搭建yolo11分类检测系统1--PyQt5学习(一)
实验条件:pycharm24.3autodlyolov11环境PyQt5 如果pycharm还没有配PyQt5的话就先去看我原先写的这篇博文: PyQT5安装搭配QT DesignerPycharm)-CSDN博客 跟练参考文章: 目标检测系列(四)利用pyqt5实现yo…...
Neo4j GDS-12-neo4j GDS 库中节点插入(Node Embedding)算法介绍
neo4j GDS 系列 Neo4j APOC-01-图数据库 apoc 插件介绍 Neo4j GDS-01-graph-data-science 图数据科学插件库概览 Neo4j GDS-02-graph-data-science 插件库安装实战笔记 Neo4j GDS-03-graph-data-science 简单聊一聊图数据科学插件库 Neo4j GDS-04-图的中心性分析介绍 Neo…...
【论文阅读】RMA: Rapid Motor Adaptation for Legged Robots
Paper: https://arxiv.org/abs/2107.04034Project: https://ashish-kmr.github.io/rma-legged-robots/Code: https://github.com/antonilo/rl_locomotion训练环境:Raisim 1.方法 RMA(Rapid Motor Adaptation)算法通过两阶段训练实现四足机器…...
C语言数据结构:树的实现、前序、中序、后序遍历
一、什么是树 树是一种非线性的数据结构,由若干个节点组成。每个节点都包含数据,并且可以有多个子节点。树的最顶端是一个特殊的节点,叫根节点,它没有父节点。从根节点开始,树不断向下分叉,形成不同的层次…...
PostgreSQL:逻辑复制与物理复制
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…...
单片机Day05---动态数码管显示01234567
一、原理图 数组索引段码值二进制显示内容00x3f0011 1111010x060000 0110120x5b0101 1011230x4f0100 1111340x660110 0110450x6d0110 1101560x7d0111 1101670x070000 0111780x7f0111 1111890x6f0110 11119100x770111 0111A110x7c0111 1100B120x390011 1001C130x5e0101 1110D140…...
STM32江科大-----SPI
声明:本人跟随b站江科大学习,本文章是观看完视频后的一些个人总结和经验分享,也同时为了方便日后的复习,如果有错误请各位大佬指出,如果对你有帮助可以点个赞小小鼓励一下,本文章建议配合原视频使用❤️ 如…...
OBS SDK 中 ffmpeg_muxer 与 ffmpeg_output 的区别与使用 QSV 编码器的正确方式
在使用 OBS SDK 开发录制或推流功能时,开发者可能会遇到两个看似相似却完全不同的输出类型:ffmpeg_muxer 和 ffmpeg_output。它们的使用方式、编码器支持范围以及配置方式都有显著区别,特别是在使用硬件编码器(如 Intel QSV)时,选择正确的输出类型至关重要。 本文将重点…...
基于AOP+Log4Net+AutoFac日志框架
1.项目概述 这是一个基于 C# 的 WPF 项目 WpfApp12log4net,它综合运用了依赖注入、日志记录和接口实现等多种技术,同时使用了 Autofac、Castle.Core 和 log4net 等第三方库。 2.配置log4net 新建一个Log4Net.config,配置需要记录的日志信息…...
【Hadoop入门】Hadoop生态之Yarn简介
1 什么是Yarn? Yarn(Yet Another Resource Negotiator) 是Hadoop生态系统中的资源管理和调度框架,负责为上层应用提供统一的资源管理和调度服务。 是Hadoop 2.0引入的重要架构改进,成为Hadoop集群的资源管理层…...
猫咪如厕检测与分类识别系统系列【三】融合yolov11目标检测
✅ 前情提要 家里养了三只猫咪,其中一只布偶猫经常出入厕所。但因为平时忙于学业,没法时刻关注牠的行为。我知道猫咪的如厕频率和时长与健康状况密切相关,频繁如厕可能是泌尿问题,停留过久也可能是便秘或不适。为了更科学地了解牠…...
qt的基本使用
先教大家如何基本使用qt,这样是为了后面的服务器使用做铺垫 安装测试用例的创建创建qt界面程序后讲解各文件的作用qt的界面控件实现逻辑功能的流程测试效果 我会写一个测试用例方便大家了解与使用 安装 参考这个文章来安装,链接: qt安装 测试用例的创建…...
Spring AI使用tool Calling和MCP
深入探索 Spring AI Spring AI版本1.0.0.M6 在人工智能与软件开发深度融合的时代,Spring AI 作为一个强大的框架,持续为开发者提供着高效且便捷的工具,以实现与大语言模型(LLM)的无缝交互。Spring AI 的最新版本引入了…...
【前端】webpack一本通
今日更新完毕,不定期补充,建议关注收藏点赞。 目录 简介使用webpack默认只能处理js文件 ->引入加载器对JS语法降级,兼容低版本语法合并文件再次打包进阶 工作原理html-webpack-plugin插件webpack开发服务器引入使用webpack-dev-server模块…...
STM32蓝牙连接Android实现云端数据通信(电机控制-开源)
引言 基于 STM32F103C8T6 最小系统板完成电机控制。这个小项目采用 HAL 库方法实现,通过 CubeMAX 配置相关引脚,步进电机使用 28BYJ-48 (四相五线式步进电机),程序通过蓝牙连接手机 APP 端进行数据收发, OL…...
OpenHarmony Camera开发指导(二):相机设备管理(ArkTS)
在开发一个相机应用前,需要先通过调用Camera接口获取支持的相机设备列表,然后创建相机设备对象做后续处理。 开发步骤 1、导入camera接口,接口中提供了相机相关的属性和方法,导入方法如下。 import { camera } from kit.Camera…...
安卓 手机拨打电话录音保存地址适配
今天来聊一聊各大厂商拨打电话自动录音保存地址适配,希望同学们积极参与评论,把自己的手机型号、Android版本及拨打电话录音地址发一下,众人拾柴火焰高啊,这样有利于后期的同学积累经验,为中国的手机适配做一次贡献。 …...
spring cloud微服务断路器详解及主流断路器框架对比
微服务断路器详解 1. 核心概念 定义:断路器模式通过快速失败机制防止故障扩散,当服务调用出现异常或超时时,自动切换到降级逻辑,避免级联故障。核心功能: 熔断:在故障阈值(如错误率)…...
idea在线离线安装插件教程
概述 对于小白来说,刚使用idea时,还有很多不懂的地方,这里,简单介绍下如何安装插件。让小白能容易上手全盘idea。 1、File -> Settings 2、找到 Plugins -> Marketplace 3、安装 3.1、在线安装 输入想搜索的内容&#x…...
项目管理(高软56)
系列文章目录 项目管理 文章目录 系列文章目录前言一、进度管理二、配置管理三、质量四、风险管理五、真题总结 前言 本节主要讲项目管理知识,这些知识听的有点意思啊。对于技术人想创业,单干的都很有必要听听。 一、进度管理 二、配置管理 三、质量 四…...
通过类似数据蒸馏或主动学习采样的方法,更加高效地学习良品数据分布
好的,我们先聚焦第一个突破点: 通过类似数据蒸馏或主动学习采样的方法,更加高效地学习良品数据分布。 这里我提供一个完整的代码示例: ✅ Masked图像重建 残差热力图 这属于自监督蒸馏方法的一个变体: 使用一个 预…...
Java设计模式实战:策略模式在SimUDuck问题中的应用
一、前言 在面向对象编程中,设计模式是解决常见问题的可重用方案。今天,我将通过经典的SimUDuck问题,向大家展示如何使用策略模式(Strategy Pattern)来设计灵活、可扩展的鸭子模拟程序。 二、问题描述 SimUDuck是一个模拟鸭子行为的程序。最…...
考虑蒙特卡洛考虑风光不确定性的配电网运行风险评估—Matlab
目录 一、主要内容: 二、实际运行效果: 三、理论介绍: 四、完整代码数据下载: 一、主要内容: 由于风电光伏出力的不确定性,造成配电网运行风险,运用蒙特卡洛概率潮流计算分析电压和线路支路…...
如何统一多条曲线的 x 轴并进行插值处理
在数据处理和分析中,我们经常遇到需要将多条曲线的 x 轴统一的情况。这种需求通常出现在需要对不同来源的数据进行比较或整合时。本文将通过一个具体的例子,展示如何使用 C 实现这一功能,并通过插值计算新的 y 值,同时确保结果分段…...
【全队项目】智能学术海报生成系统PosterGenius--多智能体辩论
🌈 个人主页:十二月的猫-CSDN博客 🔥 系列专栏🏀大模型实战训练营 💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光 文章目录 [toc]1. 前言2. 项目进度3. 本周核心进展3…...
PostIn安装及入门教程
PostIn是一款国产开源免费的接口管理工具,包含项目管理、接口调试、接口文档设计、接口数据MOCK等模块,支持常见的HTTP协议、websocket协议等,支持免登陆本地接口调试,本文将介绍如何快速安装配置及入门使用教程。 1、安装 私有…...
解决电脑问题——突然断网!
电脑如果突然断网是怎么回事 电脑突然断网可能由多种原因造成,以下是常见的因素: 网络连接与权限问题 路由器或调制解调器故障:路由器或调制解调器可能出现硬件故障、软件故障或设置错误。可以尝试重启设备,如果问题依旧&#…...
codeforces B2. The Strict Teacher
目录 题目 思路简述: 总代码: 题目 B1. 严厉的老师(困难版) 每个测试用例时间限制:1.5 秒 每个测试用例内存限制:256 兆字节 纳雷克和措索瓦克忙着准备这一轮(活动),…...
Linux:35.其他IPC和IPC原理+信号量入门
通过命名管道队共享内存的数据发送进行保护的bug: 命名管道挂掉后,进程也挂掉了。 6.systemV消息队列 原理:进程间IPC:原理->看到同一份资源->维护成为一个队列。 过程: 进程A,进程B进行通信。 让操作系统提供一个队列结构,…...