当前位置: 首页 > news >正文

7、关于LoFTR

7、关于LoFTR

LoFTR论文链接:LoFTR

LoFTR的提出,是将Transformer模型的注意力机制在特征匹配方向的应用,Transformer的提取特征的机制,在自身进行,本文提出可以的两张图像之间进行特征计算,非常适合进行特征匹配。

一、传统匹配模式的局限
  1. 首先找到一些关键点(图像梯度较高,角点检测等),然后计算特征相似度来匹配,这种方法很依赖检测到的特征点,一旦点找不到,那就不用说匹配了

在这里插入图片描述

  1. 对于位置不同的两个点,如果它们的背景特征相似(与位置无关了),也无法匹配,两者差别不大的,就无法区分了

在这里插入图片描述

二、LoFTR解决方案
  1. 不需要先得到特征点,第一个问题就得到了解决
  2. 采用end2end(给一个输入,得到结果)方法,使用非常方便

在这里插入图片描述

三、模型架构图

模型进行特征匹配主要分为四步:

  1. Local Feature CNN,就是一个blockbone,对两张图特征图进行卷积,分别得到原来特征图大小的1/8(用来进行粗粒度的匹配)和1/2(用来进行细粒度的匹配) 大小特征图。
  2. Coarse-Level Local Feature Transformer,是对两张1/8的特征图(FA,FB)进行多个串联的self-attention(自己的q和k向量做内积)和cross-attention(FA提供q,FB提供V做内积)来计算自己每个区域内之间的关系和两张图不同区域内的关系。
  3. Matching Module,到目前位置都是进行粗粒度匹配,经过了多层的Coarse-Level Local Feature Transformer,FA,FB已经了解了自身的关系,同时也知道了和对方之间的关系,要进行关系的匹配了,采用互近邻(mutual nearest neighbor (MNN))的方式匹配,简单来说,假设FA对某个点信息概率值大, 但是同时也要某个点对A的概率值也大,必须双向的,源码阈值设置为0.2,也就是互相的结果都大于0.2才能匹配成功,筛选得到符合阈值点传入下一层。
  4. Coarse-to-Fine Module,在经过粗粒度匹配之后,会得到一些候选点区域,这些候选点区域会传到细粒度,细粒度其实就是在匹配的小区域上再做一次Coarse-Level Local Feature Transformer,同样会互相了解对方的特征,但是这里不是采用MNN机制,假设FA的小区域中的某个点有FB对应小区域中的所有点匹配的概率值,才将这写概率值绘制成类似于热力图,再对整个图计算期望值,得到最终的匹配点坐标。

在这里插入图片描述

核心代码
class LoFTR(nn.Module):# ... 省略初始化代码def forward(self, data):""" 前向传播函数:参数:data (dict): 包含图像和可选掩码的字典'image0': (torch.Tensor): (N, 1, H, W) 第一张图像'image1': (torch.Tensor): (N, 1, H, W) 第二张图像'mask0' (可选): (torch.Tensor): (N, H, W) 第一张图像的掩码,'0' 表示填充位置'mask1' (可选): (torch.Tensor): (N, H, W) 第二张图像的掩码"""# 更新数据字典,添加批次大小和图像尺寸data.update({'bs': data['image0'].size(0),  # 批次大小'hw0_i': data['image0'].shape[2:],  # 第一张图像的高度和宽度'hw1_i': data['image1'].shape[2:]   # 第二张图像的高度和宽度})# 如果两张图像的尺寸相同,进行联合处理if data['hw0_i'] == data['hw1_i']:print("Concatenated Images Shape:", torch.cat([data['image0'], data['image1']], dim=0).shape) # ([2, 1, 480, 640])feats_c, feats_f = self.backbone(torch.cat([data['image0'], data['image1']], dim=0))print("Feature Coarse Shape:", feats_c.shape) # 1/8  ([2, 256, 60, 80])print("Feature Fine Shape:", feats_f.shape) # 1/2  ([2, 128, 240, 320])# 分离两张图像的特征(feat_c0, feat_c1), (feat_f0, feat_f1) = feats_c.split(data['bs']), feats_f.split(data['bs'])print("Feature Coarse Image 0 Shape:", feat_c0.shape) # ([1, 256, 60, 80])print("Feature Coarse Image 1 Shape:", feat_c1.shape) # ([1, 256, 60, 80])print("Feature Fine Image 0 Shape:", feat_f0.shape) # ([1, 128, 240, 320])print("Feature Fine Image 1 Shape:", feat_f1.shape) # ([1, 128, 240, 320])else:# 处理不同尺寸的图像(feat_c0, feat_f0), (feat_c1, feat_f1) = self.backbone(data['image0']), self.backbone(data['image1'])print("Feature Coarse Image 0 Shape:", feat_c0.shape)print("Feature Coarse Image 1 Shape:", feat_c1.shape)print("Feature Fine Image 0 Shape:", feat_f0.shape)print("Feature Fine Image 1 Shape:", feat_f1.shape)# 更新数据字典,添加特征图的尺寸data.update({'hw0_c': feat_c0.shape[2:],  # 第一张图像粗特征的高度和宽度'hw1_c': feat_c1.shape[2:],  # 第二张图像粗特征的高度和宽度'hw0_f': feat_f0.shape[2:],  # 第一张图像细特征的高度和宽度'hw1_f': feat_f1.shape[2:]   # 第二张图像细特征的高度和宽度})# 2. 粗级别局部变换模块# 添加位置编码信息feat_c0 = rearrange(self.pos_encoding(feat_c0), 'n c h w -> n (h w) c')print("Encoded Coarse Feature Image 0 Shape:", feat_c0.shape) # ([1, 4800, 256]) # 总共4800个点,每个点事256维向量feat_c1 = rearrange(self.pos_encoding(feat_c1), 'n c h w -> n (h w) c')print("Encoded Coarse Feature Image 1 Shape:", feat_c1.shape) # ([1, 4800, 256])mask_c0 = mask_c1 = None  # 掩码在训练中有用if 'mask0' in data:mask_c0, mask_c1 = data['mask0'].flatten(-2), data['mask1'].flatten(-2)# 进行粗级别局部变换feat_c0, feat_c1 = self.loftr_coarse(feat_c0, feat_c1, mask_c0, mask_c1) print("Transformed Coarse Feature Image 0 Shape:", feat_c0.shape) # ([1, 4800, 256]) # 计算后输出结果不变print("Transformed Coarse Feature Image 1 Shape:", feat_c1.shape) # ([1, 4800, 256]) # 计算后输出结果不变# 3. 粗级别匹配self.coarse_matching(feat_c0, feat_c1, data, mask_c0=mask_c0, mask_c1=mask_c1) # 4. 细级别细化feat_f0_unfold, feat_f1_unfold = self.fine_preprocess(feat_f0, feat_f1, feat_c0, feat_c1, data)if feat_f0_unfold.size(0) != 0:  # 至少有一个粗级别预测feat_f0_unfold, feat_f1_unfold = self.loftr_fine(feat_f0_unfold, feat_f1_unfold)# 5. 细级别匹配self.fine_matching(feat_f0_unfold, feat_f1_unfold, data)return x
Local Feature CNN

Local Feature CNN,就是一个blockbone,对两张图特征图进行卷积,分别得到原来特征图大小的1/8(用来进行粗粒度的匹配)和1/2(用来进行细粒度的匹配) 大小特征图。

# 来源 feats_c, feats_f = self.backbone(torch.cat([data['image0'], data['image1']], dim=0))
def build_backbone(config):if config['backbone_type'] == 'ResNetFPN':if config['resolution'] == (8, 2):return  ResNetFPN_8_2(config['resnetfpn'])# ...
class ResNetFPN_8_2(nn.Module):"""ResNet+FPN, output resolution are 1/8 and 1/2.Each block has 2 layers."""# 使用ResNet+FPN获得特征图1/8 和 1/2# 关于FPN,FPN(Feature Pyramid Networks)是一种用于目标检测和分割任务的神经网络架构,# 特别适用于处理多尺度的图像特征。它通过建立特征金字塔来捕捉不同尺度的图像信息,增强了模型对不同尺度目标的检测能力。def __init__(self, config):# ... 具体代码太长不展示
Coarse-Level Local Transformer

Coarse-Level Local Feature Transformer,是对两张1/8的特征图(FA,FB)进行多个串联的self-attention(自己的q和k向量做内积)和cross-attention(FA提供q,FB提供V做内积)来计算自己每个区域内之间的关系和两张图不同区域内的关系。

# 来源核心代码中  feat_c0, feat_c1 = self.loftr_coarse(feat_c0, feat_c1, mask_c0, mask_c1)
class LocalFeatureTransformer(nn.Module):def forward(self, feat0, feat1, mask0=None, mask1=None):"""前向传播函数:参数:feat0 (torch.Tensor): 特征图 0,形状为 [N, L, C]feat1 (torch.Tensor): 特征图 1,形状为 [N, S, C]mask0 (torch.Tensor): 特征图 0 的掩码,形状为 [N, L](可选)mask1 (torch.Tensor): 特征图 1 的掩码,形状为 [N, S](可选)"""# 确保特征图的通道数与 transformer 的模型维度一致assert self.d_model == feat0.size(2), "the feature number of src and transformer must be equal"# 迭代处理每一层,根据名称决定操作,总共4个self-cross,两个额为一组for layer, name in zip(self.layers, self.layer_names):  # ['self', 'cross', 'self', 'cross', 'self', 'cross', 'self', 'cross']if name == 'self':# 自注意力机制:feat0 本身计算 q 和 kfeat0 = layer(feat0, feat0, mask0, mask0)print("Self Attention Output feat0 Shape:", feat0.shape) # ([1, 4800, 256])# 自注意力机制:feat1 本身计算 q 和 kfeat1 = layer(feat1, feat1, mask1, mask1)print("Self Attention Output feat1 Shape:", feat1.shape) # ([1, 4800, 256])elif name == 'cross':# 交叉注意力机制:feat0 提供 q,feat1 提供 k 和 vfeat0 = layer(feat0, feat1, mask0, mask1)print("Cross Attention Output feat0 Shape:", feat0.shape) # ([1, 4800, 256])# 交叉注意力机制:feat1 提供 q,feat0 提供 k 和 vfeat1 = layer(feat1, feat0, mask1, mask0)print("Cross Attention Output feat1 Shape:", feat1.shape) # ([1, 4800, 256])else:raise KeyError("Unknown layer type")print("Final feat0 Shape:", feat0.shape) # ([1, 4800, 256]) 计算后向量维度是不变的print("Final feat1 Shape:", feat1.shape) # ([1, 4800, 256])return feat0, feat1
Matching Module

Matching Module,到目前位置都是进行粗粒度匹配,经过了多层的Coarse-Level Local Feature Transformer,FA,FB已经了解了自身的关系,同时也知道了和对方之间的关系,要进行关系的匹配了,采用互近邻(mutual nearest neighbor (MNN))的方式匹配,简单来说,假设FA对某个点信息概率值大, 但是同时也要某个点对A的概率值也大,必须双向的,源码阈值设置为0.2,也就是互相的结果都大于0.2才能匹配成功,筛选得到符合阈值点传入下一层。

# 来源核心代码中  self.coarse_matching(feat_c0, feat_c1, data, mask_c0=mask_c0, mask_c1=mask_c1) 
class CoarseMatching(nn.Module):def forward(self, feat_c0, feat_c1, data, mask_c0=None, mask_c1=None):"""前向传播函数:参数:feat_c0 (torch.Tensor): 特征图 0,形状为 [N, L, C]feat_c1 (torch.Tensor): 特征图 1,形状为 [N, S, C]data (dict): 额外数据字典mask_c0 (torch.Tensor): 特征图 0 的掩码,形状为 [N, L](可选)mask_c1 (torch.Tensor): 特征图 1 的掩码,形状为 [N, S](可选)"""# 提取批次大小、特征图 0 的长度、特征图 1 的长度和特征图的通道数N, L, S, C = feat_c0.size(0), feat_c0.size(1), feat_c1.size(1), feat_c0.size(2)print(feat_c0.shape) # ([1, 4800, 256])# 对特征图进行归一化feat_c0, feat_c1 = map(lambda feat: feat / feat.shape[-1]**.5, [feat_c0, feat_c1])if self.match_type == 'dual_softmax':# 计算相似度矩阵sim_matrix = torch.einsum("nlc,nsc->nls", feat_c0, feat_c1) / self.temperatureprint("Similarity Matrix Shape:", sim_matrix.shape) # ([1, 4800, 4800]) ,feat_c0中的4800和feat_c1进行计算得到([1, 4800, 4800])if mask_c0 is not None:# 应用掩码,将不需要的位置填充为负无穷大sim_matrix.masked_fill_(~(mask_c0[..., None] * mask_c1[:, None]).bool(),-float('inf'))# 计算置信度矩阵conf_matrix = F.softmax(sim_matrix, 1) * F.softmax(sim_matrix, 2)print("Confidence Matrix Shape:", conf_matrix.shape) # ([1, 4800, 4800])# ... 省略部分没走的代码# 更新数据字典data.update({'conf_matrix': conf_matrix})# 从置信度矩阵中预测粗略匹配data.update(**self.get_coarse_match(conf_matrix, data))

再进行下一步细粒度匹配之前,需要将粗粒度匹配出来结果和1/2特征图大小,进行处理,找出所有待细粒度处理的各个区域

# 来源核心代码中  feat_f0_unfold, feat_f1_unfold = self.fine_preprocess(feat_f0, feat_f1, feat_c0, feat_c1, data)
class FinePreprocess(nn.Module):def forward(self, feat_f0, feat_f1, feat_c0, feat_c1, data):"""前向传播函数:参数:feat_f0 (torch.Tensor): 特征图 0,形状为 [N, C, H, W]feat_f1 (torch.Tensor): 特征图 1,形状为 [N, C, H, W]feat_c0 (torch.Tensor): 粗级特征图 0,形状为 [N, L, C]feat_c1 (torch.Tensor): 粗级特征图 1,形状为 [N, L, C]data (dict): 包含额外信息的数据字典更新:data (dict): 更新数据字典,包括:'W' (int): 窗口大小"""# 获取窗口大小和步幅W = self.Wstride = data['hw0_f'][0] // data['hw0_c'][0]# 更新数据字典data.update({'W': W})# 如果没有有效的批次 ID,返回空张量if data['b_ids'].shape[0] == 0:feat0 = torch.empty(0, self.W**2, self.d_model_f, device=feat_f0.device)feat1 = torch.empty(0, self.W**2, self.d_model_f, device=feat_f0.device)return feat0, feat1# 1. 展开所有局部窗口# 使用 unfold 函数提取特征图中的局部窗口feat_f0_unfold = F.unfold(feat_f0, kernel_size=(W, W), stride=stride, padding=W//2)feat_f0_unfold = rearrange(feat_f0_unfold, 'n (c ww) l -> n l ww c', ww=W**2)feat_f1_unfold = F.unfold(feat_f1, kernel_size=(W, W), stride=stride, padding=W//2)feat_f1_unfold = rearrange(feat_f1_unfold, 'n (c ww) l -> n l ww c', ww=W**2)# 2. 仅选择预测的匹配# 根据数据中的批次 ID 和点 ID 选择特定的匹配特征feat_f0_unfold = feat_f0_unfold[data['b_ids'], data['i_ids']]  # [n, ww, cf]feat_f1_unfold = feat_f1_unfold[data['b_ids'], data['j_ids']]  # [n, ww, cf]# 选项:使用粗级别的 Loftr 特征作为上下文信息:连接和线性变换if self.cat_c_feat:# 从粗级别特征中选择窗口,并进行线性变换feat_c_win = self.down_proj(torch.cat([feat_c0[data['b_ids'], data['i_ids']],feat_c1[data['b_ids'], data['j_ids']]], 0))  # [2n, c]# 合并特征图feat_cf_win = self.merge_feat(torch.cat([torch.cat([feat_f0_unfold, feat_f1_unfold], 0),  # [2n, ww, cf]repeat(feat_c_win, 'n c -> n ww c', ww=W**2),  # [2n, ww, cf]], -1))# 将合并后的特征图分为两部分feat_f0_unfold, feat_f1_unfold = torch.chunk(feat_cf_win, 2, dim=0)return feat_f0_unfold, feat_f1_unfold
Coarse-to-Fine Module

Coarse-to-Fine Module,在经过粗粒度匹配之后,会得到一些候选点区域,这些候选点区域会传到细粒度,细粒度其实就是在匹配的小区域上再做一次Coarse-Level Local Feature Transformer,同样会互相了解对方的特征,但是这里不是采用MNN机制,假设FA的小区域中的某个点有FB对应小区域中的所有点匹配的概率值,才将这写概率值绘制成类似于热力图,再对整个图计算期望值,得到最终的匹配点坐标。

# 来源核心代码中 self.fine_matching(feat_f0_unfold, feat_f1_unfold, data)
class FineMatching(nn.Module):def forward(self, feat_f0, feat_f1, data):"""前向传播函数:参数:feat_f0 (torch.Tensor): 特征图 0,形状为 [M, WW, C],其中 M 是匹配的数量,WW 是窗口大小的平方,C 是通道数feat_f1 (torch.Tensor): 特征图 1,形状为 [M, WW, C]data (dict): 包含额外信息的数据字典"""M, WW, C = feat_f0.shape  # 提取特征图的形状信息W = int(math.sqrt(WW))  # 计算窗口的边长scale = data['hw0_i'][0] / data['hw0_f'][0]  # 计算缩放因子self.M, self.W, self.WW, self.C, self.scale = M, W, WW, C, scale# 特殊情况处理:如果没有找到粗级别匹配if M == 0:assert not self.training, "在训练阶段,M 应始终大于0,请检查 coarse_matching.py"# logger.warning('在粗级别没有找到匹配。')data.update({'expec_f': torch.empty(0, 3, device=feat_f0.device),  # 返回空的期望位置和标准差'mkpts0_f': data['mkpts0_c'],  # 使用粗级别的关键点作为回退'mkpts1_f': data['mkpts1_c'],})return# 选择特征图中心的特征feat_f0_picked = feat_f0[:, WW//2, :]print(feat_f0_picked.shape) # ([1541, 128]) 全部待计算的特征区域个数# 计算特征之间的相似度矩阵sim_matrix = torch.einsum('mc,mrc->mr', feat_f0_picked, feat_f1)print(sim_matrix.shape) # ([1541, 128]) # 使用 softmax 函数计算热图softmax_temp = 1. / C**.5heatmap = torch.softmax(softmax_temp * sim_matrix, dim=1).view(-1, W, W)print(heatmap.shape) # ([1541, 5, 5]) # 1541 个 5x5的热力图矩阵# 从热图中计算坐标,计算期望值coords_normalized = dsnt.spatial_expectation2d(heatmap[None], True)[0]  # 计算归一化坐标print(coords_normalized.shape) #([1541, 2]) # 1541 个(x,y)坐标,都是小数,表示占图大小比例grid_normalized = create_meshgrid(W, W, True, heatmap.device).reshape(1, -1, 2)  # 创建网格print(grid_normalized.shape) #([1, 25, 2])# 计算标准差var = torch.sum(grid_normalized**2 * heatmap.view(-1, WW, 1), dim=1) - coords_normalized**2  # 计算方差std = torch.sum(torch.sqrt(torch.clamp(var, min=1e-10)), -1)  # 计算标准差,使用 clamp 以保证数值稳定性# 更新数据字典以用于精细级别的监督data.update({'expec_f': torch.cat([coords_normalized, std.unsqueeze(1)], -1)})# 计算绝对的关键点坐标,按图长宽比例还原位置坐标self.get_fine_match(coords_normalized, data)

相关文章:

7、关于LoFTR

7、关于LoFTR LoFTR论文链接:LoFTR LoFTR的提出,是将Transformer模型的注意力机制在特征匹配方向的应用,Transformer的提取特征的机制,在自身进行,本文提出可以的两张图像之间进行特征计算,非常适合进行特…...

硬件工程师笔试面试知识器件篇——电感

目录​​​​​​​ 3、电感 3.1、基础 电感原理图 电感实物图 3.1.1、定义与单位 1)定义: 2) 单位: 3.1.2、物理原理 1)法拉第电磁感应定律: 2)楞次定律: 3.1.3、电感器的构造 3.1.4、类型 3.1.5、应用 3.1.6、特性 3.1.7、设计考虑 3.2、相关问题 3.…...

代码随想录八股训练营第三十六天| C++

前言 一、push_back()和emplace_back()的区别? 1.1.push_back(): 1.2.emplace_back(): 1.3.区别总结: 1.4.使用场景: 二、map dequeu list 的实现原理? 2.1.std::map: 2.2. std::deque: 2.3. std::list: 2.4. 区别总结: 总结 前言…...

学习计算机网络

a类0~127,b类128~191,c类192~223 网络地址:看子网掩码,分网络位和主机位,后面是主机位,主机位全部为0,网络地址。 直接广播地址:看子网掩码,分网络位和主机位&#xff…...

Django发送邮件

【图书介绍】《Django 5企业级Web应用开发实战(视频教学版)》_django 5企业级web应用开发实战(视频教学版)-CSDN博客 Django 5框架Web应用开发_夏天又到了的博客-CSDN博客 本文学习怎么使用Django发送邮件。 尽管使用Python的smtplib模块发送电子邮件…...

T7:咖啡豆识别

T7:咖啡豆识别 **一、前期工作**1.设置GPU,导入库2.导入数据3.查看数据 **二、数据预处理**1.加载数据2.可视化数据3.配置数据集 **三、构建CNN网络模型**1、手动搭建2、直接调用官方模型 **四、编译模型****五、训练模型****六、模型评估****七、预测**八、暂时总结…...

【MATLAB】FIR滤波器的MATLAB实现

FIR滤波器的MATLAB实现 FIR滤波器的设计fir1函数fir2函数 与IIR滤波器相比,FIR滤波器既有其优势也有其局限性。FIR滤波器的主要优点包括: 精确的线性相位响应;永远保持稳定性;设计方法通常是线性的;在硬件实现中具有更…...

【RabbitMQ之一:windows环境下安装RabbitMQ】

目录 一、下载并安装Erlang1、下载Erlang2、安装Erlang3、配置环境变量4、验证erlang是否安装成功 二、下载并安装RabbitMQ1、下载RabbitMQ2、安装RabbitMQ3、配置环境变量4、验证RabbitMQ是否安装成功5、启动RabbitMQ服务(安装后服务默认自启动) 三、安…...

ISO26262和Aspice之间的关联

ASPICE 介绍: ASPICE(Automotive Software Process Improvement and Capability dEtermination)是汽车软件过程改进及能力评定的模型,它侧重于汽车软件的开发过程。ASPICE 定义了一系列的过程和活动,包括需求管理、软…...

对极约束及其性质 —— 公式详细推导

Title: 对极约束及其性质 —— 公式详细推导 文章目录 前言1. 对极约束 (Epipolar Constraint)2. 坐标转换 (Coordinate Transformations)3. 像素坐标 (Pixel Coordinates)4. 像素坐标转换 (Transformations of Pixel Coordinates)5. 本质矩阵 (Essential Matrix)6. 线坐标 (Co…...

【论文精读】SCINet-基于降采样和交互学习的时序卷积模型

《SCINet: Time Series Modeling and Forecasting with Sample Convolution and Interaction》的作者团队来自香港中文大学,发表在NeurIPS 2022会议上。 动机 该论文的出发点是观察到时间序列数据具有独特的属性:即使在将时间序列下采样成两个子序列后,时间关系(例如数据…...

深度学习与大模型第1课环境搭建

文章目录 深度学习与大模型第1课环境搭建1. 安装 Anaconda2. 修改环境变量2.1 修改 .condarc 文件2.2 使用 Anaconda Prompt 修改环境变量 3. 新建 .ipynb 文件 机器学习基础编程:常见问题: 深度学习与大模型第1课 环境搭建 1. 安装 Anaconda 首先&am…...

JDK新特性

LTS Record jdk16 不是方法 是一个定 # Sealed Class/Interface jdk17 限制只能由某些类继承 CompletableFuture jkd8 PatternMatching of instanceOf jdk16 switch expressions jdk14 Stream.collect() Collector Collector API Collector.groupBy Collector实战 1. …...

数据处理与数据填充在Pandas中的应用

在数据分析和机器学习项目中,数据处理是至关重要的一步。Pandas作为Python中用于数据分析和操作的一个强大库,提供了丰富的功能来处理和清洗数据。本文将深入探讨Pandas在数据处理,特别是数据填充方面的应用。 在实际的数据集中,…...

【百日算法计划】:每日一题,见证成长(010)

题目 合并两个排序的链表 输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的 示例1: 输入:1->2->4, 1->3->4 输出:1->1->2->3->4->4 思路 引入一个带虚拟头结点和tail指针的…...

【WPF】WPF学习之【二】布局学习

WPF布局学习 常用布局Grid网格布局StackPanel 布局CanvasDockPanel布局WrapPanel布局 常用布局 1、StackPanel: 学习如何使用StackPanel进行垂直和水平布局。 2、Grid: 掌握Grid的网格布局技术。 3、Canvas: 了解Canvas的绝对定位布局。 4、DockPanel: 学习DockPanel的停靠…...

KEIL中编译51程序 算法计算异常的疑问

KEIL开发 51 单片机程序 算法处理过程中遇到的问题 ...... by 矜辰所致前言 因为产品的更新换代, 把所有温湿度传感器都换成 SHT40 ,替换以前的 SHT21。在 STM32 系列产品上的替换都正常,但是在一块 51 内核的无线产品上面,数据…...

pikachu文件包含漏洞靶场

本地文件包含 1、先随意进行提交 可以得出是GET传参 可以在filename参数进行文件包含 2、准备一个2.jpg文件 内容为<?php phpinfo();?> 3、上传2.jpg文件 4、访问文件保存的路径uploads/2.jpg 5、将我们上传的文件包含进来 使用../返回上级目录 来进行包含木马文件 …...

基于DPU与SmartNIC的K8s Service解决方案

1. 方案背景 1.1. Kubernetes Service介绍 Kubernetes Service是Kubernetes中的一个核心概念&#xff0c;它定义了一种抽象&#xff0c;用于表示一组提供相同功能的Pods&#xff08;容器组&#xff09;的逻辑集合&#xff0c;并提供了一种方式让这些Pods能够被系统内的其他组…...

SLM561A​​系列 60V 10mA到50mA线性恒流LED驱动芯片 为智能家居照明注入新活力

SLM561A系列选型参考&#xff1a; SLM561A10ae-7G SOD123 SLM561A15ae-7G SOD123 SLM561A20ae-7G SOD123 SLM561A25ae-7G SOD123 SLM561A30ae-7G SOD123 SLM561A35ae-7G SOD123 SLM561A40ae-7G SOD123 SLM561A45ae-7G SOD123 SLM561A50ae-7G SOD123 …...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

测试markdown--肇兴

day1&#xff1a; 1、去程&#xff1a;7:04 --11:32高铁 高铁右转上售票大厅2楼&#xff0c;穿过候车厅下一楼&#xff0c;上大巴车 &#xffe5;10/人 **2、到达&#xff1a;**12点多到达寨子&#xff0c;买门票&#xff0c;美团/抖音&#xff1a;&#xffe5;78人 3、中饭&a…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践

6月5日&#xff0c;2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席&#xff0c;并作《智能体在安全领域的应用实践》主题演讲&#xff0c;分享了在智能体在安全领域的突破性实践。他指出&#xff0c;百度通过将安全能力…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...

如何更改默认 Crontab 编辑器 ?

在 Linux 领域中&#xff0c;crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用&#xff0c;用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益&#xff0c;允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...