音视频学习(三十二):VP8和VP9
VP8
简介
- 全称:Video Processing 8
- 发布者:原 On2 Technologies(2010 被 Google 收购)
- 定位:开源视频压缩标准,主要竞争对手是 H.264
- 应用:
- WebRTC 视频通信
- HTML5
<video>
标签(WebM) - FFmpeg、SRS 支持
- YouTube(早期使用)
VP8编解码
VP8 是一种基于块的混合视频编码标准,整体思路类似 H.264。
编码核心步骤:
- 帧划分为宏块(Macroblock):16x16 像素
- 帧间预测(Inter)或帧内预测(Intra)
- 残差计算 + 变换编码(DCT)
- 量化
- 熵编码(基于概率模型的熵编码)
- 输出比特流
帧结构
组成结构
VP8 的每一帧(Frame)主要包括两个部分:
- 帧头(Frame Header)
- 帧数据(Frame Data)
帧头
帧头是帧的起始部分,包含了控制解码器如何处理该帧的各种信息。VP8 的帧头长度可变,分为 关键帧 和 非关键帧 两种情况:
共通帧头结构(Frame Tag, 3字节)
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
|I|P| Version | Partition 0 Length (19 bits) |
+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
-
I (1 bit): 关键帧标志。0 表示关键帧,1 表示非关键帧。
-
P (1 bit): 是否允许显示该帧(rarely used)。
-
Version (3 bits): 编码器版本号。
-
Partition Length (19 bits): 第一个分区(Partition 0)的长度。
关键帧附加信息(关键帧特有,附加 7 字节)
如果是关键帧(I=0),在上述 3 字节后再跟随:
0x9D 0x01 0x2A // Start code (固定标志)
2 字节: 宽度 + flags
2 字节: 高度 + flags
这部分包含图像的尺寸信息(宽度和高度)以及颜色空间标志(通常忽略)。
帧数据(Frame Partitions)
VP8 的帧数据采用分区结构(Partitioning),通常为:
- Partition 0:包含帧的控制信息、宏块模式等。必须完整接收后才能解码其余分区。
- Partition 1+:包含实际的宏块残差编码数据(Residual)。
分区结构如下:
[ Partition 0 ] [ Partition 1 ] [ Partition 2 ] ... [ Partition N ]
注意:
- Partition 0 通常为熵编码的语法元素,像预测模式、分区信息。
- Partition 1-N 是变换系数等实际视频数据。
简化结构图
VP8 Frame:
├── Frame Tag (3 bytes)
│ ├── Key Frame? (I bit)
│ └── Partition 0 Length
├── [If Key Frame]
│ ├── Start Code (0x9D012A)
│ ├── Width, Height
├── Partition 0 (mode, control info)
├── Partition 1+ (macroblock residuals)
VP8编码技术细节
宏块划分(Macroblock)
- 每帧划分为 16x16 的宏块
- 每个宏块支持:
- 4x4、8x8、16x16 子块
- 1-4 个运动矢量
- 多种预测模式
帧内预测(Intra Prediction)
- 预测方向(如 H.264 中的 Intra_4x4、Intra_16x16):
- 水平预测、垂直预测、DC 预测等
- 使用邻近像素估计当前块的值
帧间预测(Inter Prediction)
- 使用参考帧(last/golden/altref)中对应块
- 具备子像素运动估计(1/4 像素精度)
变换和量化
- 使用 DCT(Discrete Cosine Transform)
- 4x4 DCT、16x16 DCT
- 残差值 DCT 后进行量化
熵编码(Entropy Coding)
- Bool编码器(Boolean Arithmetic Coding)
- 类似算术编码,但更轻量
- 使用上下文建模(Context Modeling)
比特流结构
+----------------------------------+
| 帧标志位 (Frame Tag) |
| - 帧类型(1bit) |
| - 版本号(3bit) |
| - 显示标志(1bit) |
| - 帧长度(19bit) |
+----------------------------------+
| 帧头部数据 |
| - 分辨率 |
| - 色彩空间 |
| - 参考帧标识 |
| - Loop Filter 参数 |
| - Segment 参数 |
+----------------------------------+
| 编码宏块数据 |
+----------------------------------+
特点
特性 | 说明 |
---|---|
宏块大小 | 固定 16x16 |
支持子块划分 | 支持 |
多参考帧 | 支持(Last, Golden, AltRef) |
子像素精度 | 支持 1/4 像素 |
去块滤波器 | 内置 |
分辨率 | 无限制(理论上) |
CABAC / CAVLC | 无,使用 Bool 编码 |
B 帧 | 不支持 |
可扩展性 | 不支持 SVC(VP9 才支持) |
源码结构(libvpx)
libvpx 项目概览
GitHub 地址:https://github.com/webmproject/libvpx
libvpx/
├── build/ # 构建系统(make, cmake等)
├── configure # 自动配置脚本
├── examples/ # 示例代码(编码、解码、实时编码等)
├── test/ # 单元测试
├── tools/ # 工具,如 vpxdec/vpxenc 封装
├── vpx/ # 公共接口
├── vpxdec/ # 解码器主程序
├── vpxenc/ # 编码器主程序
├── vp8/ # ✅ VP8 专用核心代码目录
│ ├── common/ # 公共结构、宏块、DCT、IDCT等
│ ├── decoder/ # 解码器实现
│ ├── encoder/ # 编码器实现
│ └── wrapper/ # 封装接口(如 vpx_codec_iface_t)
└── vp9/ # VP9 对应目录
核心目录说明
vp8/common/
— 编解码公用模块
包含 VP8 的核心数据结构、算法实现:
文件/目录 | 功能 |
---|---|
blockd.h | 宏块(Macroblock)结构定义 |
entropymode.c/h | 熵编码模式表 |
entropy.c/h | Bool-based 熵编码实现 |
idctllm.c | 快速 IDCT 实现 |
loopfilter.c/h | 去块滤波器实现 |
mv.h | 运动矢量定义 |
modecont.h | 预测模式上下文表 |
treecoder.c | Huffman 树解码辅助模块 |
onyxc_int.h | 解码器内部数据结构 |
alloccommon.c | 内存分配器 |
postproc.c | 解码后处理滤波器 |
vp8/encoder/
— 编码器实现
文件/目录 | 功能 |
---|---|
onyx_if.c | 编码器主入口,初始化、编码过程 |
encodeframe.c | 帧编码主流程(帧内/帧间) |
ratectrl.c | 码率控制模块 |
rdopt.c | RDO(率失真优化)核心 |
modecosts.c | 模式代价估算 |
picklpf.c | 去块滤波器参数选择 |
quantize.c | 残差量化 |
motion_search.c | 运动估计核心(Diamond、Hexagon) |
variance.c | SAD/SSD 误差计算 |
firstpass.c | 首遍编码(为双遍做统计) |
temporal_filter.c | 临时帧过滤(可用于 AltRef) |
vp8/decoder/
— 解码器实现
文件/目录 | 功能 |
---|---|
onyxd_if.c | 解码器主流程 |
decodeframe.c | 解码单帧流程 |
detokenize.c | 熵编码解码器(Token -> 残差) |
idct_blk.c | IDCT 模块 |
reconinter.c | 帧间重建 |
reconintra.c | 帧内重建 |
vp8/wrapper/
对外接口(API)封装,实现 vpx_codec_iface_t
接口,供上层使用,比如 FFmpeg、WebRTC:
文件 | 功能 |
---|---|
vp8_cx_iface.c | VP8 编码器接口封装 |
vp8_dx_iface.c | VP8 解码器接口封装 |
这些接口被 vpx_codec_*()
系列函数调用,如:
c复制编辑vpx_codec_enc_config_default(&vpx_codec_vp8_cx_algo, &cfg, 0);
vpx_codec_enc_init(&codec, &vpx_codec_vp8_cx_algo, &cfg, 0);
编码流程简析(VP8)
文件核心在 vp8/encoder/encodeframe.c
和 onyx_if.c
:
编码主流程:
// onyx_if.c
vp8_get_compressed_data():-> encode_frame_to_data_rate() // 编码主流程-> vp8cx_encode_frame()-> vp8_first_pass() // 如果是两遍编码-> motion_estimation()-> mode decision / RDO-> DCT -> Quant -> Entropy encode-> loopfilter()
解码流程简析(VP8)
c// onyxd_if.c
vp8_decode_frame():-> read frame header-> token parsing (detokenize.c)-> decode macroblocks (decodeframe.c)-> IDCT, loop filter, reconstruction
实用命令:libvpx 编码示例
# 编码 VP8 视频(libvpx 提供的工具)
vpxenc input.y4m --codec=vp8 --output=output.webm --threads=4 --target-bitrate=1000# 解码 VP8 文件
vpxdec output.webm
VP9
简介
- 发布者:Google(2013年开源)
- 定位:开放的高效视频压缩标准(H.265 竞争者)
- 应用:
- YouTube(主流编码格式)
- Chrome、Firefox、Edge、Android 原生支持
- WebRTC(与 VP8 并存)
- 支持 WebM 封装格式(.webm)
核心特性(相较于 VP8)
特性 | VP8 | VP9 |
---|---|---|
参考帧 | 最多 3 帧 | 最多 8 帧 |
分区结构 | 固定 16x16 宏块 | 可递归划分至 4x4 子块 |
压缩效率 | 普通 | 提升约 30%-50% |
运动估计精度 | 1/4 像素 | 支持至 1/8 像素 |
并行解码 | 支持有限 | 支持 Tile 并行解码 |
色彩空间 | 8-bit YUV | 支持 10/12-bit、BT.2020 等 |
可扩展编码(SVC) | 不支持 | 支持 |
帧结构
组成结构
一个 VP9 Frame(画面)主要由以下部分组成:
[ Uncompressed Header ]
[ Compressed Header ]
[ Tile Data ]
Uncompressed Header(非压缩帧头)
非压缩帧头是 VP9 帧最前面的部分,不使用熵编码,含有控制信息。
主要字段说明:
字段名 | 位数(大致) | 含义 |
---|---|---|
Frame Marker | 2 bits | 固定值 0b10,用于标记 VP9 帧 |
Profile | 2 bits | 取值 0~3,表示 VP9 Profile(色深/采样) |
Show Existing Frame | 1 bit | 是否显示已有帧 |
Frame Type | 1 bit | 关键帧(0)/非关键帧(1) |
Show Frame | 1 bit | 是否显示该帧 |
Error Resilient | 1 bit | 错误恢复模式(影响帧间预测) |
Intra Only | 1 bit | 仅帧内预测(只对非关键帧) |
Reset Frame Context | 2 bits | 控制解码上下文的重置策略 |
Color Space | 3 bits | 颜色空间,如 BT.601/BT.709 等 |
Bit Depth | 1 bit | 8 / 10 / 12 bits |
Frame Width / Height | 32 bits | 图像宽高信息 |
Render Width / Height | 32 bits | 显示宽高(可能不同于编码宽高) |
Loop Filter Params | 可变 | 循环滤波配置 |
Quantization Params | 可变 | 量化参数 |
Segmentation Params | 可变 | 分块质量控制参数 |
Tile Info | 可变 | 瓦片划分信息(行数列数) |
注意:关键帧会包含完整帧宽高和颜色信息;非关键帧可以引用之前帧的元数据。
Compressed Header(压缩帧头)
使用熵编码(基于上下文概率表)压缩,包含预测模式、运动矢量、块划分模式等控制信息。
包含内容:
- 预测模式(帧内/帧间)
- 块划分方式
- 运动矢量参考索引(ref_frame_idx)
- skip_flags
- transform size 选择
- DCT/ADST 类型选择
- Token 语法表
这个部分决定了解码时如何还原帧。
Tile Data(图像数据部分)
VP9 使用 Tile(瓦片)结构进行并行解码,Tile 是按列分割的一块图像区域,具有独立编码结构。
Tile 特点:
- 每个 Tile 可独立解码(适合多线程)
- Tile 数据包括:
- 残差系数(变换块)
- skip 模式信息
- CDF 熵码表更新
- Tile 是 VP9 实际图像内容的主要组成部分
你可以认为一帧由多个 tile 按顺序拼成图像。
VP9 帧结构图示
┌──────────────────────────┐
│ Frame Marker (2 bits) │
│ Profile (2 bits) │
│ Show Frame / Keyframe │
├──────────────────────────┤
│ Uncompressed Header │
│ ├── Width / Height │
│ ├── Color Space │
│ ├── Loop Filter │
│ └── Quant Params │
├──────────────────────────┤
│ Compressed Header (熵编码)│
│ ├── Mode Info │
│ ├── Motion Vectors │
│ └── Token Partition │
├──────────────────────────┤
│ Tile Data │
│ ├── Tile 0 │
│ ├── Tile 1 │
│ └── Tile N │
└──────────────────────────┘
关键帧 vs 非关键帧 区别
项 | 关键帧(Keyframe) | 非关键帧(Inter Frame) |
---|---|---|
是否独立 | 是 | 否,需要参考前帧 |
包含信息 | 完整图像元信息 | 可复用前帧元信息 |
参考帧使用 | 无 | 多参考帧/双向预测 |
用途 | 场景切换、起始帧 | 正常视频传输帧 |
VP9编码技术细节
Raw Frame (YUV)↓
Block Partitioning(分块)↓
Prediction(预测:Intra / Inter)↓
Transform(变换:DCT / ADST)↓
Quantization(量化)↓
Entropy Coding(上下文熵编码)↓
Bitstream(VP9 Frame)
Superblock & Block Partitioning(超级块与分块)
Superblock
- 固定大小 64x64 像素
- VP9 使用 superblock 替代 VP8 的宏块(16x16)
分块模式
- 每个 superblock 可递归划分为更小块(最大到 4x4)
- 块划分支持 10 种模式,如:
64x64 → 32x32 → 16x16 → 8x8 → 4x4
+ 一些非对称划分(e.g. 32x16, 16x32)
优点
- 允许更细粒度的局部控制(纹理复杂区域划小块,背景区域保大块)
- 类似 HEVC 中 CU/PU/TU 的结构
Prediction(帧预测)
帧内预测(Intra Prediction)
- 预测当前块的数据来自当前帧已解码区域
- 支持 10 种帧内预测模式(DC、水平、垂直、方向模式等)
帧间预测(Inter Prediction)
- 预测当前块来自于 参考帧
- 参考帧支持:Last, Golden, AltRef(最多 3 个)
- 支持:
- 单向预测(Single Reference)
- 双向预测(Compound Prediction)
- 亚像素精度运动矢量(1/8 像素)
- 运动矢量预测与补偿(MVP)
- 全局运动建模(Global Motion)
优点
- 相较 VP8,大幅提升运动估计准确度和压缩效率
Transform(变换)
VP9 使用 DCT/ADST 进行频域转换,压缩空间冗余。
Block Size | 支持变换类型 |
---|---|
4x4 | DCT / ADST |
8x8 | DCT / ADST |
16x16 | DCT only |
32x32 | DCT only |
64x64 | DCT only |
水平/垂直可用不同变换类型,混合变换提升适应性。
Quantization(量化)
- 各个块的变换系数会进行量化压缩
- 使用 自适应量化参数,支持 segmentation(每块不同 QP)
- QP(量化参数)影响压缩率和质量:数值越大,压缩越强,画质越差
Loop Filters(环路滤波)
用于消除块边界伪影(blocking artifacts):
包括:
- Deblocking Filter(去块效应)
- Adaptive Loop Filter
- Clamping Filter
- CDEF / Sgrproj(在 AV1 中)
VP9 提供灵活的滤波控制参数,按块启用或关闭滤波器。
Segmentation(分段控制)
将图像划分为多个 segment,每个 segment 可设置不同参数:
- QP(量化参数)
- Loop filter 强度
- 预测模式约束
- 可用于 ROI 编码(重点区域更高质量)
Tile-based 并行处理
Tile 是图像按列划分的子区域(不是 macroblock)
- 每个 tile 可独立解码
- 支持并行编码(多线程)
- Tile Size 可调节(编码效率 vs 并行效率)
好处:
- 实时编码优化(尤其适用于 WebRTC)
- 硬件友好,可并行硬解
Entropy Coding(熵编码)
使用 上下文自适应二进制算术编码(Context Adaptive Binary Arithmetic Coding, CABAC) 类似结构:
- 每个语法元素使用概率模型编码
- 多个上下文模型(如 skip_flag、mv、transform_size 等)
- 兼容多参考帧、多块模式预测
VP9 Profiles & 色深支持
Profile | Bit Depth | 色度格式 | 用途 |
---|---|---|---|
0 | 8-bit | 4:2:0 | WebM, YouTube 默认 |
1 | 8-bit | 4:2:2 / 4:4:4 | 高质量视频 |
2 | 10/12-bit | 4:2:0 | HDR 视频 |
3 | 10/12-bit | 4:2:2 / 4:4:4 | 专业场景 |
比特流结构
[ Frame Header ]
[ Compressed Frame Data ]└── [ Tile Data ]└── [ Residual Data (Transformed & Quantized) ]└── [ Motion Vectors (for Inter Frames) ]└── [ Entropy-coded Data (Tokens) ]
特点
特性 | VP9 | H.264 | H.265 |
---|---|---|---|
压缩效率 | 高 | 中 | 很高 |
编码复杂度 | 高 | 低 | 很高 |
硬件支持 | 中(新设备支持) | 普遍 | 高 |
授权成本 | 免费 | 付费 | 付费 |
多线程支持 | 好(Tile) | 一般 | 优秀 |
源码结构(libvpx)
libvpx/
├── vp8/ # VP8 编解码器实现
├── vp9/ # VP9 编解码器实现 ✅ ← 重点
│ ├── encoder/ # VP9 编码器实现
│ ├── decoder/ # VP9 解码器实现
│ ├── common/ # 编码器 & 解码器共有的数据结构、工具函数
│ └── ...
├── build/ # 构建脚本
├── test/ # 单元测试代码
├── tools/ # 命令行工具(vpxenc/vpxdec)
├── examples/ # 示例代码(使用 libvpx 编解码)
├── vpx/ # 通用接口层
│ ├── vpx_encoder.h # 编码器 API 入口
│ ├── vpx_decoder.h # 解码器 API 入口
│ └── vpx_codec.h # 通用编解码框架
└──
编码器核心结构(vp9/encoder/
)
文件名 | 功能 |
---|---|
vp9_encoder.h/c | 编码器核心控制接口 |
vp9_encodeframe.c | 每帧编码主逻辑(块划分、预测、残差、熵编码) |
vp9_ratectrl.c | 码率控制模块(CBR/VBR) |
vp9_pickmode.c | 预测模式选择(Intra / Inter) |
vp9_rdopt.c | 率失真优化(Rate-Distortion)关键模块 ✅ |
vp9_quantize.c | DCT 系数量化 |
vp9_tokenize.c | 熵编码预处理(生成 token) |
vp9_mcomp.c | 运动估计(Motion Estimation) |
vp9_segmentation.c | 分段编码(不同 QP 区域) |
vp9_skin_detection.c | 人脸/肤色检测(可用于提升视觉质量) |
vp9_aq_variance.c | 自适应质量 AQ 策略 |
... | 其他模块如 tile、滤波器、变换 等 |
解码器核心结构(vp9/decoder/
)
文件名 | 功能 |
---|---|
vp9_decoder.h/c | 解码器核心控制逻辑 |
vp9_decodeframe.c | 解码主逻辑(解析帧头、构建帧) |
vp9_dboolhuff.c | 帧头解析 + 熵解码器 |
vp9_decodemv.c | 解码运动矢量相关信息 |
vp9_detokenize.c | 熵解码后的系数还原 |
vp9_reader.h | 比特流解析器(BitReader) |
... | 变换、滤波、预测、Tile 重建等 |
通用模块(vp9/common/
)
文件名 | 功能 |
---|---|
vp9_common.h | 公共定义(帧类型、块大小等) |
vp9_blockd.c/.h | 块级数据结构、预测模式枚举 |
vp9_mv.h | 运动矢量数据结构 |
vp9_entropy.c | 熵编码上下文模型(上下文概率表) |
vp9_loopfilter.c | 去块滤波器(Deblocking Filter) |
vp9_seg_common.c | 分段结构解析 |
vp9_tile_common.c | Tile 分区结构解析 |
vp9_pred_common.c | 预测函数(帧内帧间) |
vp9_inv_txfm.c | 反变换(IDCT / IADST) |
编码流程简析(VP9)
入口在 examples/vpxenc.c
-
main()
中设置参数后调用:vpx_codec_enc_init()
-
使用
vpx_codec_encode()
编码一帧 YUV,会调用:vp9_get_cx_interface() → vp9_encode() → vp9_encode_frame()
-
编码流程深入到:
vp9_rd_pick_inter_mode_sb()
:选最优 Inter 模式vp9_transform_block()
:DCT/ADSTvp9_quantize()
:量化vp9_entropy_coding()
:熵编码 tokenvp9_write_bitstream()
:写入 VP9 比特流
解码流程简析(VP9)
入口在 examples/vpxdec.c
:
-
初始化解码器
vpx_codec_dec_init()
-
调用
vpx_codec_decode()
解码 VP9 比特流 -
实际进入 VP9 解码器:
vp9_get_dx_interface() → vp9_decode() → vp9_decode_frame()
-
解码流程:
vp9_read_frame_header()
vp9_decode_tiles()
:Tile 并行重建vp9_loopfilter_frame()
:去块滤波- 输出 YUV 图像帧
FFMPEG推拉VP8/VP9
推流
推送 VP8 流(RTMP 协议)
ffmpeg -re -i input.mp4 -c:v libvpx -b:v 1M -c:a libopus -f flv rtmp://your-server-ip/live/stream_key
-re
:以实时速度读取输入文件-i input.mp4
:输入文件(可以是.mp4
、.y4m
、.avi
等)-c:v libvpx
:使用 VP8 编码器(libvpx)-b:v 1M
:设置视频比特率为 1Mbps-c:a libopus
:使用 Opus 编码器进行音频编码-f flv
:指定输出格式为 FLV(适用于 RTMP 流媒体)rtmp://your-server-ip/live/stream_key
:RTMP 流媒体服务器地址和流密钥
推送 VP9 流(RTMP 协议)
ffmpeg -re -i input.mp4 -c:v libvpx-vp9 -b:v 1M -c:a libopus -f flv rtmp://your-server-ip/live/stream_key
-c:v libvpx-vp9
:使用 VP9 编码器(libvpx-vp9)- 其他参数与推送 VP8 流类似
拉流
拉取 VP8 流(RTMP 协议)
ffmpeg -i rtmp://your-server-ip/live/stream_key -c:v libvpx -c:a libopus output.webm
-i rtmp://your-server-ip/live/stream_key
:指定 RTMP 流媒体源地址-c:v libvpx
:解码 VP8 视频流-c:a libopus
:解码音频流为 Opus 格式output.webm
:指定输出文件格式为 WebM
拉取 VP9 流(RTMP 协议)
ffmpeg -i rtmp://your-server-ip/live/stream_key -c:v libvpx-vp9 -c:a libopus output.webm
-c:v libvpx-vp9
:解码 VP9 视频流- 其他参数与拉取 VP8 流类似
其他协议
推流至 RTSP 服务器(VP8/VP9)
ffmpeg -re -i input.mp4 -c:v libvpx -b:v 1M -c:a libopus -f rtsp rtsp://your-server-ip:port/stream
-f rtsp
:设置 RTSP 协议输出rtsp://your-server-ip:port/stream
:指定 RTSP 流地址
拉取 RTSP 流(VP8/VP9)
ffmpeg -i rtsp://your-server-ip:port/stream -c:v libvpx -c:a libopus output.webm
拉取 HLS 流(VP8/VP9)
如果流源为 HLS(HTTP Live Streaming),可以使用以下命令来拉取 VP8 或 VP9 流:
ffmpeg -i http://your-server-ip/hls/stream.m3u8 -c:v libvpx -c:a libopus output.webm
-i http://your-server-ip/hls/stream.m3u8
:指定 HLS 流的 M3U8 播放列表output.webm
:输出为 WebM 格式
相关文章:
音视频学习(三十二):VP8和VP9
VP8 简介 全称:Video Processing 8发布者:原 On2 Technologies(2010 被 Google 收购)定位:开源视频压缩标准,主要竞争对手是 H.264应用: WebRTC 视频通信HTML5 <video> 标签(…...
美国mlb与韩国mlb的关系·棒球9号位
MLB(Major League Baseball,美国职业棒球大联盟)作为全球最高水平的职业棒球联赛,与韩国市场流行的“MLB”时尚品牌之间存在着授权合作关系,但两者在业务范畴和品牌定位上存在显著差异。 一、品牌授权背景:…...
免费在线PUA测试工具:识别情感操控,守护情感健康
免费在线PUA测试工具:识别情感操控,守护情感健康 你是否曾经在感情中感到困惑、不安,甚至怀疑自己?今天为大家推荐一个专业的PUA测试工具,帮助你识别是否正在经历情感操控。 测试工具链接:PUA测试工具 什么…...
nginx中的try_files指令
try_files 是 Nginx 中一个非常有用的指令,用于按顺序检查文件是否存在,并返回第一个找到的文件。如果所有指定的文件都不存在,则执行回退逻辑,如重定向到一个指定的 URI 或返回一个错误代码。 作用 文件查找:按顺序检…...
[特殊字符] 驱动开发硬核特训 · Day 4
主题:从硬件总线到驱动控制 —— I2C 协议与传感器驱动开发全解析 I2C(Inter-Integrated Circuit)总线是一种广泛用于嵌入式设备的串行通信协议,因其低成本、简单布线和多从设备支持,成为连接各种传感器(温…...
Python 实现玻璃期货数据处理、入库与分析:从代码到应用
Python 实现期货数据处理与分析:从代码到应用 引言 在金融市场中,期货数据的处理和分析对于投资者和分析师来说至关重要。Python 凭借其丰富的库和简洁的语法,成为了处理和分析期货数据的强大工具。本文将详细解读一段用于处理期货持仓和行…...
神经网络之损失函数
引言:损失函数 (Loss Function)是机器学习和深度学习中非常重要的一个概念。用于衡量模型的预测值与真实值之间的差异,从而指导模型优化其参数以最小化这种差异。 一、损失函数作用 量化误差:损失函数是将预测值和真实…...
在Ubuntu内网环境中为Gogs配置HTTPS访问(通过Apache反向代理使用IP地址)
一、准备工作 确保已安装Gogs并运行在HTTP模式(默认端口3000) 确认服务器内网IP地址(如192.168.1.100) 二、安装Apache和必要模块 sudo apt update sudo apt install apache2 -y sudo a2enmod ssl proxy proxy_http rewrite headers 三、创建SSL证书 1. 创建证书存储目录…...
printf
printf() 是 C 和 C 标准库中的一个输出函数,位于 <cstdio> 头文件中。下面为你详细介绍它的相关知识点。 1. 基本使用 printf() 函数的作用是按照指定格式将数据输出到标准输出设备(通常是控制台)。其基本语法如下: cpp …...
Leetcode 311 Sparse Matrix Multiplication 稀疏矩阵相乘
Problem Given two sparse matrices A and B, return the result of AB. You may assume that A’s column number is equal to B’s row number. Example: A [[ 1, 0, 0],[-1, 0, 3] ]B [[ 7, 0, 0 ],[ 0, 0, 0 ],[ 0, 0, 1 ] ]| 1 0 0 | | 7 0 0 | | 7 0 0 | AB …...
mysql和sqlite关于data数据的识别问题
<input type"date" name"birthday" value""> # 表单传入的日期 birthday request.form.get(birthday) # 获取日期 birthday Column(birthday, Date, comment出生日期, nullableTrue) # 数据库的数据字段模型 birthday_str request…...
2024 天梯赛——工业园区建设题解
思路 将点 i i i 视为固定点, 点 j j j 视为灵活点,其中 s i 1 s_{i} 1 si1, s j 0 s_{j} 0 sj0。维护四个队列,其中 q 0 q_{0} q0 和 q 1 q_{1} q1 分别维护还没有被选用的固定点 和 灵活点, Q 0 Q…...
亚马逊AI新功能上线:5大亮点解锁精准消费预测
在人工智能技术不断重塑跨境电商生态之际,全球电商巨头亚马逊(Amazon)再次迈出关键一步。近日,亚马逊正式对其卖家中心推出一系列基于AI的新功能,聚焦于消费数据预测、用户行为洞察、库存智能管理与个性化营销服务等方…...
opus+ffmpeg+c++实现录音
说明: opusffmpegc实现录音 效果图: step1:C:\Users\wangrusheng\source\repos\WindowsProject1\WindowsProject1\WindowsProject1.cpp // WindowsProject1.cpp : 定义应用程序的入口点。 //#include "framework.h" #include "Windows…...
ComfyUI的本地私有化部署使用Stable Diffusion文生图
什么是ComfyUI ? ComfyUI是一个基于节点流程的Stable Diffusion操作界面。以下是关于它的详细介绍: 特点与优势 高度可定制:提供丰富的节点类型,涵盖文本处理、图像处理、模型推理等功能。用户可根据需求自由组合节点࿰…...
【学习笔记17】Windows环境下安装RabbitMQ
一. 下载RabbitMQ( 需要按照 Erlang/OTP 环境的版本依赖来下载) (1) 先去 RabbitMQ 官网,查看 RabbitMQ 需要的 Erlang 支持:https://www.rabbitmq.com/ 进入官网,在 Docs -> Install and Upgrade -> Erlang V…...
【LeetCode 热题100】55:跳跃游戏(详细解析)(Go语言版)
🚀 LeetCode 热题 55:跳跃游戏(Jump Game)完整解析 📌 题目描述 给定一个非负整数数组 nums,你最初位于数组的第一个下标。 数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一…...
OpenCV轮廓检测全面解析:从基础到高级应用
一、概述 轮廓检测是计算机视觉中的基础技术,用于识别和提取图像中物体的边界。与边缘检测不同,轮廓检测更关注将边缘像素连接成有意义的整体,形成封闭的边界。 轮廓检测的核心价值 - 物体识别:通过轮廓可以识别图像中的独立物体…...
微服务入门:Spring Boot 初学者指南
大家好,这里是架构资源栈!点击上方关注,添加“星标”,一起学习大厂前沿架构! 微服务因其灵活性、可扩展性和易于维护性而成为现代软件架构的重要组成部分。在本博客中,我们将探讨如何使用 Spring Boot 构建…...
Windows环境下开发pyspark程序
Windows环境下开发pyspark程序 一、环境准备 1.1. Anaconda/Miniconda(Python环境) 如果不怕包的版本管理混乱,可以直接使用已有的Python环境。 需要安装anaconda/miniconda(python3.8版本以上):Anaconda…...
嵌入式学习笔记——大小端及跳转到绝对地址
大小端以及跳转到绝对地址 0x100000 嵌入式编程中的大小端详解一、大端模式与小端模式二、判断当前系统是大端还是小端方法一:指针强制类型转换方法二:使用联合体(union) 三、结构体位段和大小端的影响四、大小端影响内存的 memc…...
eprime相嵌模式实验设计
一、含义与模型结构 该模式的实验设计至少 由两个存储不同实验材料及 属性的List和一个核心实验 过程CEP组成。子list1和 list2相嵌在父List中,CEP 可以调用List中的材料,也 可以调用list1和list2中的材 料。 二、相嵌模式的应用 应用于解决“多重随…...
编译uboot的Makefile编写
make ARCHarm CROSS_COMPILEarm-linux-gnueabihf- distcleanmake ARCHarm CROSS_COMPILEarm-linux-gnueabihf- mx6ull_14x14_ddr512_emmc_defconfigmake V1 ARCHarm CROSS_COMPILEarm-linux-gnueabihf- -j12 这三条命令中 ARCHarm 设置目标为 arm 架构, CROSS_COMP…...
Go语言常用算法实现
以下是Go语言中常用的算法实现,涵盖排序、搜索、数据结构操作等核心算法。 一、排序算法 1. 快速排序 func QuickSort(arr []int) []int {if len(arr) < 1 {return arr}pivot : arr[0]var left, right []intfor i : 1; i < len(arr); i {if arr[i] < pi…...
Windows上使用NSSM注册定时服务
适用和不适用场景 适用场景 持续运行 的脚本或程序(如 Laravel 的 schedule:run 每分钟检查任务)后台常驻 的任务或服务(如监听服务、实时同步) 不适用场景 低频次任务(如每日/每周备份) NSSM 常驻内存…...
【Gorm】模型定义
intro package mainimport ("gorm.io/gorm""gorm.io/driver/sqlite" // GORM 使用该驱动来连接和操作 SQLite 数据库。 )type Product struct {gorm.Model // 嵌入GORM 内置的模型结构,包含 ID、CreatedAt、UpdatedAt、DeletedAt 四个字段Cod…...
程序化广告行业(65/89):AdX/SSP系统深度剖析与实战要点
程序化广告行业(65/89):AdX/SSP系统深度剖析与实战要点 大家好!一直以来,我都对程序化广告领域充满热情,这个领域发展迅速且不断涌现新的技术和模式。之前我们探讨了程序化广告的一些基础内容,…...
算法刷题记录——LeetCode篇(2.7) [第161~170题](持续更新)
更新时间:2025-04-06 算法题解目录汇总:算法刷题记录——题解目录汇总技术博客总目录:计算机技术系列博客——目录页 优先整理热门100及面试150,不定期持续更新,欢迎关注! 169. 多数元素 给定一个大小为…...
conda安装指定版本python环境
1. 创建指定 Python 版本的环境 使用以下命令创建环境,并将 <env_name> 替换为你的环境名称,<python_version> 替换为具体的 Python 版本(如 3.8, 3.9 等) conda create -n <env_name> python<python_vers…...
PH热榜 | 2025-04-05
1. Comp AI 标语:开源的 Vanta 和 Drata 替代方案 介绍:这款开源的 Drata 和 Vanta 替代方案,能够帮助你在几周内,轻松满足 SOC 2、ISO 27001 和 GDPR 等合规框架的要求,而不是像往常那样拖延数月。 产品网站&#…...
C++之红黑树
目录 一、红黑树的概念 1.1、红黑树的规则 1.2、红黑树如何确保最长路径不超过最短路径的二倍 1.3、红黑树的效率 二、红黑树的实现 2.1、红黑树的结构 2.2、红黑树的插入 2.2.1、红黑树插入一个值的大概过程 2.2.2、情况一:变色 2.2.3、情…...
各个语言对不同数据结构的叫法
一、基础数据结构对比 数组(Array) C/C:固定大小数组(int arr),动态数组通过vector(C)实现 Java:固定数组(int[]),动态数组…...
蓝桥杯 web 水果拼盘 (css3)
做题步骤: 看结构:html 、css 、f12 分析: f12 查看元素,你会发现水果的高度刚好和拼盘的高度一样,每一种水果的盘子刚好把页面填满了,所以咱们就只要让元素竖着排列,加上是竖着,排不下的换行…...
算法专题(八):分治-归并排序
目录 一、排序数组 1.1 题目 2.2 思路 2.3 代码实现 二、LCR 170. 交易逆序对的总数 (数组中的逆序对) 2.1 题目 2.2 思路 方法一:快速统计出某个数前面有多少个数比它大 方法二:快速统计出某个数后面有多少个数比它小 …...
51单片机使用定时器实现LCD1602的时间显示(STC89C52RC)
本文前半部分直接给出实现(注意进位问题是秒->分->小时,用 if 嵌套即可实现),后半部分讲解定时器和中断系统。 效果展示: LCD1602电路图: 项目结构: 代码实现: main.c #…...
微软2025年AI技术深度解析:从多模态大模型到企业级代理服务
微软2025年AI技术深度解析:从多模态大模型到企业级代理服务 一、微软AI技术全景概览 在2025年的AI领域,微软通过Azure AI Foundry、多模态大模型、企业级AI代理三大核心技术,构建了覆盖开发、部署、应用全流程的AI生态体系。根据最新财报数…...
24 设计模式总结
设计模式分类(意图) • 创建型模式:创建对象的机制,从所需要实例化的对象中解耦。 • 结构型模式:将对象或类组装到更大的结构中。 • 行为型模式:负责对象间的交互和分配职责。分类的目的是为了更抽象的了…...
【ARTS】2873.有序三元组中的最大值!
前言 仅做学习使用,侵删 什么是ARTS? 算法(Algorithm): 每周至少一道LeetCode算法题,加强编程训练和算法学习 阅读(Review): 阅读并点评至少一篇英文技术文章,提高英文水平 技巧 (Tip):学习至少一个技…...
Mysql进阶
目录 一.Mysql架构 1.连接层 2.服务层 3.引擎层 4.物理文件存储层 二.Mysql引擎 1.InnoDB 2.MyISAM 三.索引 1.什么是索引 2.为什么要有索引 3.索引的原理 4.索引优势 5.索引劣势 6.索引分类 主键索引 唯一索引 单值索引 组合索引(复合索引&#…...
探秘JVM内部
在我们编写Java代码,点击运行后,会发生什么事呢? 首先,Java源代码会经过Java编译器将其编译成字节码,放在.class文件中 然后这些字节码文件就会被加载到jvm中,然后jvm会读取这些文件,调用相关…...
c语言学习12天
c语言的宏定义:宏定义单纯的文本替换不会检查语法是否合法 #include #pragma 以及开头的#都属于预处理指令 预处理指令:在gcc编译套件中的cpp预处理器对程序进行编译之前所做的一些动作,如#include预处理指令就是在程序编译之前有预处理器…...
公司内网部署离线deepseek本地模型实战
企业内部可能有些数据比较敏感,不能连接互联网。deepseek来提高工作效率,这个时候你可以利用ollama在内网本地部署来实现。 本式样是先在自己电脑上用虚拟机部署好,再用U盘把虚拟机文件复制到内网去。 一、使用VMware新建WIN2022虚拟机 &a…...
rocketmq中的延迟队列使用详解
RocketMQ的延迟队列通过预设的延迟等级实现消息的定时投递,适用于订单超时、定时通知等高并发场景。以下是其核心原理、使用方式及优化策略的详细解析: 一、实现原理 延迟等级机制 RocketMQ默认提供18个固定延迟等级(1s、5s、10s、30s、1m、2…...
VB.NET Asp.Net Core模板WebAPI应用-宝塔面板Linux系统通过Docker部署
宝塔面板支持在Linux系统上部署Docker容器吗? 如何在宝塔面板上通过Docker部署VB.NET应用? Docker容器中的VB.NET Asp.Net Core WebAPI应用如何配置? 一,首先,创建一个ASP.NET Core测试项目 1.1 打开VS2019/2022,创建一个.NTE6 Core控制台应…...
4985 蜗牛
4985 蜗牛 ⭐️难度:中等 ⭐️考点:2023、省赛、动态规划 📖 📚 import java.util.Scanner; // 1:无需package // 2: 类名必须Main, 不可修改public class Main {public static void main(String[] args) {Scanner sc new Sc…...
springboot多模块工程打包部署运行
1、问题概述? 基于实际项目打包过程,各种配置面面俱到,已配置的可跳过。 本文以打包jar包为模板进行操作,部署方便。 在实际的开发中,项目的模块可能较多,如果都放在一个项目的目录中,势必会造成项目包中的文件冗余,难以管理,这个时候就需要使用多模块管理项目。 …...
吴恩达深度学习复盘(8)神经网络中激活函数的建模
激活函数的建模原理 到目前为止,在隐藏层等一直使用激活函数,最初通过逻辑回归建立新网络,组合多个逻辑回归单元。这表明激活函数在神经网络构建中一直存在,且最初的网络构建方式与逻辑回归相关。实际上,激活函数的种类…...
1-linux的基础知识
一.linux的文件系统结构 windows文件系统 微软windows系统将硬盘上的几个分区,用A: B: C: D:等符号标识。存取文件时一定要清楚放在那个磁盘的那个目录下。 linux文件系统 linux文件系统的组织模式犹如一颗倒置的树,这与windows文件系统有很大的差别…...
docker 常用命令
文章目录 一、帮助启动类命令启动docker停止docker重启docker查看docker状态开机自启查看docker概要信息 二、镜像命令列出本地主机上的镜像搜索镜像拉取镜像查看镜像所占空间删除镜像 三、容器命令新建运行容器交互式启动容器守护进程式启动容器列出当前所有的容器进入容器之后…...
使用docker搭建redis镜像时云服务器无法访问到国外的docker官网时如何解决
下载redis镜像 docker redis:版本号 此时截图中无法访问到国外的docker官网 解决方案: 通过更换镜像源来正常下载redis镜像 sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<EOF {"registry-mirrors": ["https://docker.1…...