【论文阅读】BEVFormer论文解析及Temporal Self-Attention、Spatial Cross-Attention注意力机制详解及代码示例

BEVFormer: Learning Bird’s-Eye-ViewRepresentation from Multi-Camera Images via Spatiotemporal Transformers|Temporal Self-Attention、Spatial Cross-Attention注意力机制详解

BEVFormer(Bird’s-Eye-View Former)是一种先进的计算机视觉模型,旨在从多摄像头图像序列中生成鸟瞰图(BEV)表示。它通过时空变换器融合多视角和时间信息,实现高效的3D场景理解。广泛应用于自动驾驶等领域。以下从模型结构、创新点、训练方法和模型实验四个方面进行详细总结。

一. 模型结构

BEVFormer的整体架构分为输入层、特征提取层、时空变换器层和输出层,处理多摄像头图像序列(如6个摄像头)以生成BEV特征图。
在这里插入图片描述

  • 输入层:输入为多摄像头图像序列,记为I={Itc∣c∈{1,2,…,C},t∈{1,2,…,T}}I = \{I_t^c | c \in \{1, 2, \dots, C\}, t \in \{1, 2, \dots, T\}\}I={Itcc{1,2,,C},t{1,2,,T}},其中CCC是摄像头数量,TTT是时间步长。例如,在nuScenes数据集中,C=6C=6C=6TTT通常取3-5帧。
  • 特征提取层:使用卷积神经网络(CNN)backbone(如ResNet或EfficientNet)提取每帧图像的2D特征。特征图记为F2DcF_{2D}^cF2Dc,维度为H×W×DH \times W \times DH×W×D,其中DDD是特征维度。
  • 时空变换器层:这是核心模块,包括空间交叉注意力和时间自注意力机制。空间交叉注意力融合多摄像头视角,时间自注意力建模时间依赖性。公式如下:
    • 空间交叉注意力:对于每个BEV网格点qqq,查询所有摄像头特征:
      Attention(Q,K,V)=softmax(QKTdk)V \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V Attention(Q,K,V)=softmax(dkQKT)V
      其中QQQ是BEV查询,KKKVVV是2D特征图的键和值。
    • 时间自注意力:在时间维度上聚合信息:
      Attention(Qt,Kt−1,Vt−1)=softmax(QtKt−1Tdk)Vt−1 \text{Attention}(Q_t, K_{t-1}, V_{t-1}) = \text{softmax}\left(\frac{Q_t K_{t-1}^T}{\sqrt{d_k}}\right)V_{t-1} Attention(Qt,Kt1,Vt1)=softmax(dkQtKt1T)Vt1
      这允许模型从历史帧中学习运动信息。
  • 输出层:生成BEV特征图FbevF_{bev}Fbev,维度为Hbev×Wbev×DbevH_{bev} \times W_{bev} \times D_{bev}Hbev×Wbev×Dbev。该特征图可直接用于下游任务,如3D目标检测或分割。

整个模型是端到端的,输入图像序列,输出BEV表示,中间通过多层变换器堆叠实现高效融合。

二. 创新点详解:Temporal Self-Attention 与 Spatial Cross-Attention 注意力机制

注意力机制是深度学习中处理序列数据的关键技术,通过计算输入元素之间的相关性权重,实现动态特征聚焦。逐步解释 Temporal Self-Attention 和 Spatial Cross-Attention 的原理、数学表达和应用场景。

1) 注意力机制基础

注意力机制的核心是计算查询(Query)、键(Key)和值(Value)之间的相似度,生成加权输出。通用公式为:
Attention(Q,K,V)=softmax(QKTdk)V \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V Attention(Q,K,V)=softmax(dkQKT)V
其中:

  • Q∈Rn×dkQ \in \mathbb{R}^{n \times d_k}QRn×dk 是查询矩阵。
  • K∈Rm×dkK \in \mathbb{R}^{m \times d_k}KRm×dk 是键矩阵。
  • V∈Rm×dvV \in \mathbb{R}^{m \times d_v}VRm×dv 是值矩阵。
  • dkd_kdk 是键的维度,用于缩放点积防止梯度爆炸。
  • softmax\text{softmax}softmax 函数确保权重和为 1。

Temporal Self-Attention 和 Spatial Cross-Attention 是该机制的变体,分别针对时间和空间维度优化。

2) Temporal Self-Attention 详解

定义:Temporal Self-Attention 是一种自注意力机制,专注于时间序列数据(如视频帧、传感器读数)。它在同一序列的时间步之间计算注意力,捕捉长期依赖关系,忽略空间位置信息。

数学原理

  • 输入序列:X∈RT×dX \in \mathbb{R}^{T \times d}XRT×d,其中 TTT 为时间步数,ddd 为特征维度。
  • 通过可学习权重矩阵生成 Q,K,VQ, K, VQ,K,V
    Q=XWQ,K=XWK,V=XWV Q = X W^Q, \quad K = X W^K, \quad V = X W^V Q=XWQ,K=XWK,V=XWV
    其中 WQ,WK∈Rd×dkW^Q, W^K \in \mathbb{R}^{d \times d_k}WQ,WKRd×dk, WV∈Rd×dvW^V \in \mathbb{R}^{d \times d_v}WVRd×dv
  • 注意力计算:
    Attention(Q,K,V)=softmax(QKTdk)V \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V Attention(Q,K,V)=softmax(dkQKT)V
    输出 O∈RT×dvO \in \mathbb{R}^{T \times d_v}ORT×dv,每个时间步的值为其他时间步的加权和。
  • 示例:对于时间步 ttt,输出 oto_tot 计算为:
    ot=∑j=1Tαtjvj,αtj=exp⁡(qt⋅kjdk)∑k=1Texp⁡(qt⋅kkdk) o_t = \sum_{j=1}^{T} \alpha_{tj} v_j, \quad \alpha_{tj} = \frac{\exp\left(\frac{q_t \cdot k_j}{\sqrt{d_k}}\right)}{\sum_{k=1}^{T} \exp\left(\frac{q_t \cdot k_k}{\sqrt{d_k}}\right)} ot=j=1Tαtjvj,αtj=k=1Texp(dkqtkk)exp(dkqtkj)
    其中 αtj\alpha_{tj}αtj 是时间步 tttjjj 的注意力权重,qtq_tqtkjk_jkjQQQKKK 的行向量。

特点

  • 优点:高效处理长序列,捕捉时间动态(如视频中的运动模式)。
  • 缺点:计算复杂度为 O(T2)O(T^2)O(T2),对长序列可能昂贵。
  • 应用场景:视频动作识别(分析帧间关系)、时间序列预测(如股票数据)、语音处理(建模音频时序)。

简单代码示例(Python)
以下是一个简化实现,展示 Temporal Self-Attention 的核心逻辑:

import torch
import torch.nn.functional as Fdef temporal_self_attention(X):# X: 输入序列, shape [batch_size, T, d]d_k = X.size(-1)  # 键维度Q = torch.matmul(X, W_Q)  # W_Q 是可学习权重K = torch.matmul(X, W_K)V = torch.matmul(X, W_V)# 计算注意力分数scores = torch.matmul(Q, K.transpose(-2, -1)) / (d_k ** 0.5)attn_weights = F.softmax(scores, dim=-1)# 加权输出output = torch.matmul(attn_weights, V)return output# 示例使用
batch_size, T, d = 2, 10, 64  # 批大小、时间步、特征维度
X = torch.randn(batch_size, T, d)
W_Q = torch.randn(d, d)
W_K = torch.randn(d, d)
W_V = torch.randn(d, d)
output = temporal_self_attention(X)
print(output.shape)  # 输出: torch.Size([2, 10, 64])
3) Spatial Cross-Attention 详解

定义:Spatial Cross-Attention 是一种交叉注意力机制,专注于空间数据(如图像、特征图)。它在不同序列的空间位置之间计算注意力,例如查询序列来自一个模态(如文本),键值序列来自另一个模态(如图像),实现跨模态信息融合。

数学原理

  • 输入:两个独立序列,查询序列 Qseq∈RN×dqQ_{\text{seq}} \in \mathbb{R}^{N \times d_q}QseqRN×dq 和键值序列 KVseq∈RM×dkvKV_{\text{seq}} \in \mathbb{R}^{M \times d_{kv}}KVseqRM×dkv,其中 NNNMMM 为空间位置数(如图像像素或区域)。
  • 生成 Q,K,VQ, K, VQ,K,V
    Q=QseqWQ,K=KVseqWK,V=KVseqWV Q = Q_{\text{seq}} W^Q, \quad K = KV_{\text{seq}} W^K, \quad V = KV_{\text{seq}} W^V Q=QseqWQ,K=KVseqWK,V=KVseqWV
    其中 WQ∈Rdq×dkW^Q \in \mathbb{R}^{d_q \times d_k}WQRdq×dk, WK,WV∈Rdkv×dkW^K, W^V \in \mathbb{R}^{d_{kv} \times d_k}WK,WVRdkv×dk
  • 注意力计算:
    Attention(Q,K,V)=softmax(QKTdk)V \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V Attention(Q,K,V)=softmax(dkQKT)V
    输出 O∈RN×dvO \in \mathbb{R}^{N \times d_v}ORN×dv,每个查询位置的值是键值序列位置的加权和。
  • 示例:对于查询位置 iii,输出 oio_ioi 计算为:
    oi=∑j=1Mβijvj,βij=exp⁡(qi⋅kjdk)∑k=1Mexp⁡(qi⋅kkdk) o_i = \sum_{j=1}^{M} \beta_{ij} v_j, \quad \beta_{ij} = \frac{\exp\left(\frac{q_i \cdot k_j}{\sqrt{d_k}}\right)}{\sum_{k=1}^{M} \exp\left(\frac{q_i \cdot k_k}{\sqrt{d_k}}\right)} oi=j=1Mβijvj,βij=k=1Mexp(dkqikk)exp(dkqikj)
    其中 βij\beta_{ij}βij 是查询位置 iii 对键值位置 jjj 的注意力权重。

特点

  • 优点:支持异构数据交互,增强空间上下文理解(如物体定位)。
  • 缺点:需对齐不同序列的空间维度,计算复杂度 O(N×M)O(N \times M)O(N×M)
  • 应用场景:视觉问答(文本查询关注图像区域)、图像生成(草图到照片的转换)、多模态融合(视频和音频的空间对齐)。

简单代码示例(Python)
以下是一个简化实现,展示 Spatial Cross-Attention 的核心逻辑:

import torch
import torch.nn.functional as Fdef spatial_cross_attention(query_seq, kv_seq):# query_seq: 查询序列, shape [batch_size, N, d_q]# kv_seq: 键值序列, shape [batch_size, M, d_kv]d_k = query_seq.size(-1)  # 键维度Q = torch.matmul(query_seq, W_Q)  # W_Q 是可学习权重K = torch.matmul(kv_seq, W_K)V = torch.matmul(kv_seq, W_V)# 计算注意力分数scores = torch.matmul(Q, K.transpose(-2, -1)) / (d_k ** 0.5)attn_weights = F.softmax(scores, dim=-1)# 加权输出output = torch.matmul(attn_weights, V)return output# 示例使用
batch_size, N, M, d_q, d_kv = 2, 16, 32, 64, 128  # N: 查询位置数, M: 键值位置数
query_seq = torch.randn(batch_size, N, d_q)
kv_seq = torch.randn(batch_size, M, d_kv)
W_Q = torch.randn(d_q, d_k)
W_K = torch.randn(d_kv, d_k)
W_V = torch.randn(d_kv, d_k)
output = spatial_cross_attention(query_seq, kv_seq)
print(output.shape)  # 输出: torch.Size([2, 16, d_k])

整体原版代码推理结构,将此2种结构重复叠加并执行6次进行encoder操作:
operation_order=(‘self_attn’, ‘norm’, ‘cross_attn’, ‘norm’, ‘ffn’, ‘norm’)

def attn_bev_encode(self,mlvl_feats,bev_queries,bev_h,bev_w,grid_length=[0.512, 0.512],bev_pos=None,prev_bev=None,**kwargs):bs = mlvl_feats[0].size(0)bev_queries = bev_queries.unsqueeze(1).repeat(1, bs, 1)bev_pos = bev_pos.flatten(2).permute(2, 0, 1)#[4,256,3200]->[3200,4,256]# obtain rotation angle and shift with ego motiondelta_x = np.array([each['can_bus'][0]for each in kwargs['img_metas']])delta_y = np.array([each['can_bus'][1]for each in kwargs['img_metas']])ego_angle = np.array([each['can_bus'][-2] / np.pi * 180 for each in kwargs['img_metas']])grid_length_y = grid_length[0]grid_length_x = grid_length[1]translation_length = np.sqrt(delta_x ** 2 + delta_y ** 2)translation_angle = np.arctan2(delta_y, delta_x) / np.pi * 180bev_angle = ego_angle - translation_angleshift_y = translation_length * \np.cos(bev_angle / 180 * np.pi) / grid_length_y / bev_hshift_x = translation_length * \np.sin(bev_angle / 180 * np.pi) / grid_length_x / bev_wshift_y = shift_y * self.use_shiftshift_x = shift_x * self.use_shiftshift = bev_queries.new_tensor([shift_x, shift_y]).permute(1, 0)  # xy, bs -> bs, xy# 通过`旋转`和`平移`变换实现 BEV 特征的对齐,对于平移部分是通过对参考点加上偏移量`shift`体现的if prev_bev is not None:if prev_bev.shape[1] == bev_h * bev_w:prev_bev = prev_bev.permute(1, 0, 2)if self.rotate_prev_bev:for i in range(bs):# num_prev_bev = prev_bev.size(1)rotation_angle = kwargs['img_metas'][i]['can_bus'][-1]tmp_prev_bev = prev_bev[:, i].reshape(bev_h, bev_w, -1).permute(2, 0, 1)tmp_prev_bev = rotate(tmp_prev_bev, rotation_angle,center=self.rotate_center) tmp_prev_bev = tmp_prev_bev.permute(1, 2, 0).reshape(bev_h * bev_w, 1, -1)prev_bev[:, i] = tmp_prev_bev[:, 0]# add can bus signalscan_bus = bev_queries.new_tensor([each['can_bus'] for each in kwargs['img_metas']])can_bus = self.can_bus_mlp(can_bus)[None, :, :] #编码为高维特征bev_queries = bev_queries + can_bus * self.use_can_busfeat_flatten = []spatial_shapes = []for lvl, feat in enumerate(mlvl_feats):bs, num_cam, c, h, w = feat.shapespatial_shape = (h, w)feat = feat.flatten(3).permute(1, 0, 3, 2)if self.use_cams_embeds:feat = feat + self.cams_embeds[:, None, None, :].to(feat.dtype) #self.cams_embeds摄像头位置编码feat = feat + self.level_embeds[None,None, lvl:lvl + 1, :].to(feat.dtype)spatial_shapes.append(spatial_shape)feat_flatten.append(feat)feat_flatten = torch.cat(feat_flatten, 2)spatial_shapes = torch.as_tensor(spatial_shapes, dtype=torch.long, device=bev_pos.device)level_start_index = torch.cat((spatial_shapes.new_zeros((1,)), spatial_shapes.prod(1).cumsum(0)[:-1]))feat_flatten = feat_flatten.permute(0, 2, 1, 3)  # (num_cam, H*W, bs, embed_dims)ret_dict = self.encoder(bev_queries,feat_flatten,feat_flatten,mlvl_feats=mlvl_feats,bev_h=bev_h,bev_w=bev_w,bev_pos=bev_pos,spatial_shapes=spatial_shapes,level_start_index=level_start_index,prev_bev=prev_bev,shift=shift,**kwargs)return ret_dictdef forward(self,query,key=None,value=None,bev_pos=None,query_pos=None,key_pos=None,attn_masks=None,query_key_padding_mask=None,key_padding_mask=None,ref_2d=None,ref_3d=None,bev_h=None,bev_w=None,reference_points_cam=None,mask=None,spatial_shapes=None,level_start_index=None,prev_bev=None,**kwargs):"""Forward function for `TransformerDecoderLayer`.**kwargs contains some specific arguments of attentions.Args:query (Tensor): The input query with shape[num_queries, bs, embed_dims] ifself.batch_first is False, else[bs, num_queries embed_dims].key (Tensor): The key tensor with shape [num_keys, bs,embed_dims] if self.batch_first is False, else[bs, num_keys, embed_dims] .value (Tensor): The value tensor with same shape as `key`.query_pos (Tensor): The positional encoding for `query`.Default: None.key_pos (Tensor): The positional encoding for `key`.Default: None.attn_masks (List[Tensor] | None): 2D Tensor used incalculation of corresponding attention. The length ofit should equal to the number of `attention` in`operation_order`. Default: None.query_key_padding_mask (Tensor): ByteTensor for `query`, withshape [bs, num_queries]. Only used in `self_attn` layer.Defaults to None.key_padding_mask (Tensor): ByteTensor for `query`, withshape [bs, num_keys]. Default: None.Returns:Tensor: forwarded results with shape [num_queries, bs, embed_dims]."""norm_index = 0attn_index = 0ffn_index = 0identity = queryif attn_masks is None:attn_masks = [None for _ in range(self.num_attn)]elif isinstance(attn_masks, torch.Tensor):attn_masks = [copy.deepcopy(attn_masks) for _ in range(self.num_attn)]warnings.warn(f'Use same attn_mask in all attentions in 'f'{self.__class__.__name__} ')else:assert len(attn_masks) == self.num_attn, f'The length of ' \f'attn_masks {len(attn_masks)} must be equal ' \f'to the number of attention in ' \f'operation_order {self.num_attn}'for layer in self.operation_order:# temporal self attentionif layer == 'self_attn':query = self.attentions[attn_index](query,prev_bev,prev_bev,identity if self.pre_norm else None,query_pos=bev_pos,key_pos=bev_pos,attn_mask=attn_masks[attn_index],key_padding_mask=query_key_padding_mask,reference_points=ref_2d,spatial_shapes=torch.tensor([[bev_h, bev_w]], device=query.device),level_start_index=torch.tensor([0], device=query.device),**kwargs)attn_index += 1identity = queryelif layer == 'norm':query = self.norms[norm_index](query)norm_index += 1# spaital cross attentionelif layer == 'cross_attn':query = self.attentions[attn_index](query,key,value,identity if self.pre_norm else None,query_pos=query_pos,key_pos=key_pos,reference_points=ref_3d,reference_points_cam=reference_points_cam,mask=mask,attn_mask=attn_masks[attn_index],key_padding_mask=key_padding_mask,spatial_shapes=spatial_shapes,level_start_index=level_start_index,**kwargs)attn_index += 1identity = queryelif layer == 'ffn':query = self.ffns[ffn_index](query, identity if self.pre_norm else None)ffn_index += 1return query
三. 训练方法

BEVFormer采用端到端监督学习,训练过程包括数据准备、损失函数和优化策略:

  • 数据准备:使用大规模3D数据集(如nuScenes),数据集提供多摄像头图像序列和对应的3D标注(如边界框)。数据增强包括随机裁剪、旋转和颜色抖动,以提高鲁棒性。
  • 损失函数:主要针对下游任务设计。例如,对于3D目标检测,采用多任务损失:
    L=λclsLcls+λregLreg+λiouLiou \mathcal{L} = \lambda_{cls} \mathcal{L}_{cls} + \lambda_{reg} \mathcal{L}_{reg} + \lambda_{iou} \mathcal{L}_{iou} L=λclsLcls+λregLreg+λiouLiou
    其中Lcls\mathcal{L}_{cls}Lcls是分类损失(如Focal Loss),Lreg\mathcal{L}_{reg}Lreg是边界框回归损失(如Smooth L1),Liou\mathcal{L}_{iou}Liou是IoU损失。权重λ\lambdaλ通过网格搜索优化。
  • 优化策略:使用AdamW优化器,学习率采用余弦衰减调度。初始学习率为10−410^{-4}104,批量大小设置为8-16(取决于GPU内存)。训练通常在100-200个epoch内收敛,使用预训练CNN backbone(如ImageNet权重)加速收敛。
  • 实现细节:在PyTorch中实现,支持分布式训练。模型参数量约为50M,训练时需注意内存管理(如梯度累积)。

该方法确保了模型从原始图像中学习鲁棒的BEV表示,支持实时推理。

四. 模型实验

BEVFormer在标准数据集上进行了全面实验,验证其有效性:

  • 数据集:主要在nuScenes数据集上评估,该数据集包含1000个驾驶场景,每个场景有6个摄像头和3D标注。

  • 评估指标:核心指标包括:

    • mAP(平均精度):用于3D目标检测,计算不同距离阈值下的平均精度。
    • NDS(nuScenes Detection Score):综合指标,考虑mAP、位置误差和方向误差。
    • 推理速度:FPS(帧每秒)评估实时性。
  • 实验结果

    • BEVFormer在nuScenes测试集上达到SOTA(state-of-the-art)性能,例如mAP为48.1%,NDS为53.5%,显著优于基线模型(如LSS或DETR3D)。
    • 消融实验证明:时空变换器贡献最大,mAP提升约8%;时间建模模块(T=3T=3T=3帧)比单帧提升5%。
    • 效率方面:在NVIDIA V100 GPU上,推理速度达15 FPS,适合实时系统。
      在这里插入图片描述
  • 对比分析:与同类模型(如PolarFormer或PETR)相比,BEVFormer在复杂场景(如雨雾天气)下鲁棒性更强,归功于其时空融合设计。实验还扩展到其他任务(如BEV分割),性能一致优异。

总结

BEVFormer通过创新的时空变换器架构,高效地从多摄像头图像生成BEV表示,解决了自动驾驶中的3D感知挑战。其核心优势在于端到端学习、实时性和高精度。实验表明,它在nuScenes等基准上领先,为实际应用提供了可靠基础。未来工作可探索轻量化版本或扩展到更多传感器融合。

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

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

相关文章

在 Ubuntu 中docker容器化操作来使用新建的 glibc-2.32

在 Ubuntu 中使用容器化操作来使用新建的 glibc-2.32,可以通过创建自定义 Docker 镜像来实现。以下是完整的解决方案: 方案 1:创建包含 glibc-2.32 的 Docker 镜像 1. 创建 Dockerfile dockerfile # 使用 Ubuntu 基础镜像 FROM ubuntu:20.04# 安装编译依赖 RUN apt-get …

GOOUUU ESP32-S3-CAM 果云科技开发板开发指南(二)(超详细!)Vscode+espidf 摄像头拍摄视频实时传输到LCD,文末附源码

书接上回,上一篇blog是使用esp32s3通过ov2640摄像头拍摄到一帧照片,并把它保存到了SD卡中,这第二篇就通过LCD将拍摄到的图片显示到LCD上,本次分享硬件使用的 ESP32-S3-CAM 果云科技开发板,并且使用了配套的LCD扩展板&a…

攻防世界-ics-05(远程文件执行)

一.审题大致浏览一下网页,发现就这边会有东西。看一下源码会不会有东西或者稍微点击一下这个页面的内容看会不会出现东西。点击了一下这个云平台设备维护中心发现url变了,是get的方法传page参数二.尝试漏洞类型自己这边试了sql注入发现不是,试…

Dell PowerEdge: Servers by generation (按代系划分的服务器)

Dell PowerEdge: Servers by generation {按代系划分的服务器}1. Table of 17th, 16th, 15th, and 14th Generation PowerEdge servers2. List of all PowerEdge server models including Type, CPU vendor, Generation, and Remote ManagementReferencesPowerEdge: Servers by…

Rust学习笔记(二)|变量、函数与控制流

本篇文章包含的内容1 变量与常量2 类型2.1 标量类型2.2 复合类型3 函数4 控制流4.1 分支4.2 循环1 变量与常量 在Rust中,使用let关键字声明一个变量,变量默认是不可变的。如果要声明可变变量,需要使用mut关键字将其声明为可变变量。 let x …

【渲染流水线】[几何阶段]-[图元装配]以UnityURP为例

【从UnityURP开始探索游戏渲染】专栏-直达 前情提要 【渲染流水线】主线索引-从数据到图像以UnityURP为例-CSDN博客 图元装配负责将离散顶点组装成完整几何图元(如点、线、三角形、三角形条带) (对渲染的探索是个持续不断完善的过程&#x…

jvm有哪些垃圾回收器,实际中如何选择?

7.G1收集器一款面向服务端应用的垃圾收集器。 特点如下: 并行与并发:G1能充分利用多CPU、多核环境下的硬 件优势,使用多个CPU来缩短Stop-The-World停顿时间。部分收集器原本需要停顿Java线程来执行GC动作,G1收 集器仍然可以通过并…

多语言与隐形攻击:LLM安全防线为何被频频突破?

你是否曾以为,只要加装了“防火墙”,大型语言模型(LLM)就能高枕无忧?Trendoyl 的实际测试却让我大吃一惊:即便部署了 Meta 的 Llama Guard,攻击者还是能轻松用多语种、字符混淆,甚至…

分布式光伏气象站:为光伏电站的 “气象感知眼”

分布式光伏气象站:为光伏电站的 “气象感知眼”柏峰 【BF-GFQX】在全球能源转型的浪潮中,分布式光伏发电凭借其就近消纳、清洁高效的优势,成为能源结构优化的重要力量。而分布式光伏气象站,作为光伏电站的 “智慧感知眼”&#xf…

TCP与UDP:如何选择最佳传输协议

应用场景选择如果需要可靠传输,首选 TCP如果需要传输的数据包很大,也首选 TCP绝大部分的场景,都可以优先考虑 TCPUDP 相比于 TCP,最大的优点在于传输效率有些情况,既需要可靠性又需要性能,这个时候时候就需…

《Leetcode》-面试题-hot100-栈

题目列表 20. 有效的括号 简单难度 leetcode链接 155. 最小栈 中等难度 leetcode链接 394. 字符串解码 中等难度 leetcode链接 739. 每日温度 中等难度 leetcode链接 84. 柱状图中最大的矩形 困难难度 leetcode链接 题目 (1)有效的括号 题目 给…

GPT-5、Claude-4 同台亮相!OneEval发布全新“大模型+知识库”评测白皮书!

OneEval官网地址:http://OneEval.OpenKG.cnOneEval文章链接:https://arxiv.org/abs/2506.12577要点导读 今年4月,OpenKG发布“大模型知识库”融合能力评估榜单OneEval v1.0。近期,OpenKG在此基础上,组织撰写了OneEv…

【最新版】沃德云商协系统全开源+uniapp小程序

一.介绍沃德云商协是一款基于FastAdmin(thinkphp)Uniapp开发的“多组织”的云服务平台,打造总商会、总协会、总校友会、工商联等多组织无障碍沟通合作平台,让各大分会、各大分校友会、分组织实现轻松管理,线上宣传展示…

Wireshark专家模式定位网络故障:14种TCP异常深度解剖

TCP连接如同精密运转的传送带,每一个异常数据包都是故障的早期信号。作为网络工程师的“外科手术刀”,Wireshark在TCP故障诊断领域的价值无可替代。本文将通过14个真实故障场景,揭示如何利用Wireshark专家系统(Expert System&…

Python Day28 HTML 与 CSS 核心知识点 及例题分析

一、HTML 布局标签(含 H5 语义化标签)传统布局多使用div标签,H5 新增语义化标签增强可读性:核心知识点header:替代div#header,用于页面头部(如标题、导航)。footer:替代d…

MySQL 数据库表操作与查询实战案例

MySQL 数据库表操作与查询实战案例 在数据库学习过程中,熟练掌握表的创建、数据插入及各类查询操作是基础且重要的技能。本文将通过实际案例,详细介绍 MySQL 中数据库表的设计、数据插入以及常用的查询操作,帮助初学者快速上手。 项目一&…

THCV215一种高速视频数据收发器,采用低电压差分信号(LVDS)技术支持高速串行数据传输,支持1080p/60Hz高分辨率传输

THCV215 是一款符合 V-by-One HS 标准的 高速视频数据收发器。THCV215和THCV216被设计为支持主机和显示器之间的视频数据传输。该芯片组可以在20MHz至100MHz的LVDS时钟频率下,仅通过一根差分电缆传输39bit视频数据和3bit同步数据。该芯片组有两个高速数据通道&#…

Linux 系统下 VS Code 降级至 1.85 版本教程:通过历史版本网站解决兼容性问题

一、问题背景 当前使用的 VS Code 版本为 1.102.3,这一版本可能是未来版本、内部测试版或 Insiders 版本,而目前最新的稳定版属于 1.8x 系列。由于版本过新,可能导致与部分插件(如旧版 Remote-SSH)或系统环境不兼容。…

一个基于 PyTorch 的完整模型训练流程

一个基于 PyTorch 的完整模型训练流程 flyfish训练步骤具体操作目的1. 训练前准备设置随机种子、配置超参数(batch size、学习率等)、选择计算设备(CPU/GPU)确保实验可复现;统一控制训练关键参数;利用硬件加…

ffmpeg,ffplay, vlc,rtsp-simple-server,推拉流命令使用方法,及测试(二)

一、常用命令 ffmpeg 推流命令 : ffmpeg -re -i input.mp4 -c copy -f flv rtmp://39.105.129.233/myapp/ffmpeg -re -i input.mp4 -c copy -f flv rtsp://39.105.129.233/myapp/-re 读取流 -i 输入文件 -f # 指定推流formatffplay 拉流命令 : ffplay rtmp://39.105.129.233/m…