计算机视觉|超详细!Meta视觉大模型Segment Anything(SAM)源码解剖
一、引言
在计算机视觉领域,图像分割是一个核心且具有挑战性的任务,旨在将图像中的不同物体或区域进行划分和识别,广泛应用于自动驾驶、医学影像分析、安防监控等领域。Segment Anything Model(SAM)由 Meta AI 实验室发布,其引入了基于 Prompt 的交互式分割能力,显著提升了图像分割的灵活性和泛化能力。
SAM 通过在海量且多样化的数据集上训练,具备处理未见过对象类别和场景的能力。这一特性使其在学术界引发广泛研究,如模型轻量化、领域适应、多模态融合等方向;在工业界也迅速应用于医学图像分析中的肿瘤检测、遥感图像处理中的卫星图像分析以及视频处理中的目标跟踪等领域。
对于计算机视觉爱好者和开发者而言,深入剖析 SAM 的源码有助于理解其核心技术原理,为进一步创新和应用提供基础。本文将从原理到源码逐步解析 SAM 的工作机制,探索其实现高效图像编码、提示编码及掩码解码的过程。
二、SAM 原理速览
(一)核心概念
SAM 的核心在于其 “分割一切” 的能力,这一能力依赖于基于 Prompt 的分割策略。Prompt 可以是点(points)、框(boxes)、掩码(masks)或文本(text),为模型提供分割目标的关键信息。例如,点击图像中的一个点,SAM 能够识别并分割该点所在物体;给定一个框,SAM 则专注于框内物体的分割。
(二)模型架构
SAM 的架构包含三个核心组件:Image Encoder(图像编码器)、Prompt Encoder(提示编码器) 和 Mask Decoder(掩码解码器),其协作方式如下图所示:
- Image Encoder:将输入图像转换为高维特征表示,通常使用预训练的 Vision Transformer(ViT),如 ViT-H、ViT-L、ViT-B。例如,对于分辨率为 1024 × 1024 1024 \times 1024 1024×1024 的图像,经过 Patch Embedding 操作划分为 16 × 16 16 \times 16 16×16 的 patches,特征图尺寸缩小为原来的 1 16 \frac{1}{16} 161,通道数从 3 映射到 768。
- Prompt Encoder:处理不同类型的 Prompt,将其编码为与图像嵌入兼容的特征。对点和框使用位置编码(Positional Encoding);对文本使用 CLIP 文本编码器;对掩码则通过轻量级卷积网络编码。
- Mask Decoder:融合图像嵌入和提示嵌入,通过 Transformer 结构解码为分割掩码,默认生成 3 个候选掩码并按置信度排序。
三、源码结构总览
(一)代码目录解析
SAM 的代码目录结构如下:
segment-anything/
├── assets # 示例图片等资源
├── demo # 前端部署代码
├── notebooks # Jupyter Notebook 示例
├── script # 模型导出脚本
├── segment_anything # 核心代码目录
│ ├── build_sam.py # 模型构建脚本
│ ├── config.py # 配置文件
│ ├── mask_decoder.py # 掩码解码器实现
│ ├── model_registry.py # 模型注册模块
│ ├── predictor.py # 预测接口
│ ├── sam.py # SAM 整体结构
│ ├── sam_arch.py # 架构细节
│ ├── utils.py # 工具函数
│ └── automatic_mask_generator.py # 自动掩码生成
└── setup.py # 安装脚本
segment_anything 是核心目录,后续分析将聚焦于此。
(二)关键文件与模块
- build_sam.py:定义模型构建函数,支持不同版本(如 vit_h、vit_l、vit_b)。示例代码:
def build_sam_vit_h(checkpoint=None):# 构建 vit_h 版本的 SAM 模型return _build_sam(encoder_embed_dim=1280, # 编码器嵌入维度encoder_depth=32, # 编码器层数encoder_num_heads=16, # 注意力头数encoder_global_attn_indexes=[7, 15, 23, 31], # 全局注意力层索引checkpoint=checkpoint, # 预训练权重文件路径)
- predictor.py:提供预测接口,
set_image
处理图像预处理,predict
根据提示生成掩码。核心代码:
def set_image(self, image: np.ndarray) -> None:# 检查输入图像维度和通道数是否符合要求if image.ndim != 3 or image.shape[2] not in [3, 4]:raise ValueError("Image must be 3D with 3 or 4 channels")# 应用图像变换(如缩放、归一化)input_image = self.transform.apply_image(image)# 转换为 PyTorch 张量并调整维度为 [1, C, H, W]input_image_torch = torch.as_tensor(input_image, device=self.device)self.set_torch_image(input_image_torch.permute(2, 0, 1)[None, :, :, :], image.shape[:2])
- automatic_mask_generator.py:自动生成所有物体掩码,基于点提示网格。核心代码:
def generate(self, image: np.ndarray) -> List[Dict[str, Any]]:# 预处理输入图像input_image = self.model.preprocess(image)# 使用无梯度计算图像嵌入with torch.no_grad():image_embedding = self.model.image_encoder(input_image)# 生成点提示网格points = self._generate_points(image.shape[:2])all_masks, all_scores = [], []# 按批次处理点提示并预测掩码for i in range(0, len(points), self.points_per_batch):batch_points = points[i:i + self.points_per_batch]batch_masks, batch_scores = self._predict_masks(image_embedding, batch_points)all_masks.extend(batch_masks)all_scores.extend(batch_scores)# 返回掩码和对应置信度列表return [{"segmentation": m, "score": s} for m, s in zip(all_masks, all_scores)]
四、核心代码深度剖析
(一)Image Encoder 源码解析
- Patch Embedding:将图像划分为 patches 并映射为特征向量:
class PatchEmbed(nn.Module):def __init__(self, kernel_size=(16, 16), stride=(16, 16), in_chans=3, embed_dim=768):# 初始化 Patch Embedding 模块super().__init__()# 定义卷积层,将图像划分为 patches 并映射到嵌入维度self.proj = nn.Conv2d(in_chans, embed_dim, kernel_size, stride)def forward(self, x: torch.Tensor) -> torch.Tensor:# 对输入图像进行卷积操作,生成特征图x = self.proj(x)# 调整维度顺序为 [B, H/16, W/16, C],适配 Transformer 输入return x.permute(0, 2, 3, 1)
输入图像 [ B , 3 , H , W ] [B, 3, H, W] [B,3,H,W] 转换为 [ B , H 16 , W 16 , 768 ] [B, \frac{H}{16}, \frac{W}{16}, 768] [B,16H,16W,768]。
- Transformer Encoder:堆叠多个 Transformer Block 提取特征:
class Block(nn.Module):def __init__(self, dim, num_heads, mlp_ratio):# 初始化 Transformer Blocksuper().__init__()# 第一层归一化self.norm1 = nn.LayerNorm(dim)# 多头注意力模块self.attn = Attention(dim, num_heads)# 第二层归一化self.norm2 = nn.LayerNorm(dim)# 多层感知机,隐藏层维度为 dim * mlp_ratioself.mlp = Mlp(dim, int(dim * mlp_ratio))def forward(self, x):# 自注意力计算并残差连接x = x + self.attn(self.norm1(x))# MLP 计算并残差连接x = x + self.mlp(self.norm2(x))return x
(二)Prompt Encoder 源码解析
编码不同类型提示:
class PromptEncoder(nn.Module):def __init__(self, embed_dim, image_embedding_size, input_image_size):# 初始化 Prompt Encoder 模块super().__init__()# 位置编码层,使用随机高斯矩阵生成self.pe_layer = PositionEmbeddingRandom(embed_dim // 2)# 提示嵌入层,处理点和框提示self.prompt_embed_layer = PromptEmbedding(embed_dim, input_image_size, image_embedding_size)def forward(self, points=None, boxes=None, masks=None):# 初始化稀疏嵌入张量,维度为 [batch_size, 0, embed_dim]sparse_embed = torch.zeros(bs, 0, self.embed_dim, device=self.device)if points:# 提取点提示的坐标和标签coords, labels = points# 生成点嵌入并拼接到稀疏嵌入中sparse_embed = torch.cat([sparse_embed, self.prompt_embed_layer.point_embedding(coords, labels)], dim=1)# 返回稀疏嵌入和密集嵌入(未完全展示 masks 处理部分)return sparse_embed, dense_embed
五、实战演练
(一)环境搭建与配置
- 安装 Python:版本 ≥ 3.8。
- 安装 PyTorch:
pip install torch==2.0.1+cu117 torchvision==0.15.2+cu117 -f https://download.pytorch.org/whl/cu117
- 安装 SAM:
pip install -U "git+https://github.com/facebookresearch/segment-anything.git"
(二)代码运行与结果分析
示例代码:
from segment_anything import sam_model_registry, SamPredictor
import cv2
import numpy as np
import matplotlib.pyplot as plt# 加载 vit_b 版本的 SAM 模型并移动到 GPU
sam = sam_model_registry["vit_b"](checkpoint="sam_vit_b_01ec64.pth").to("cuda")
# 初始化预测器
predictor = SamPredictor(sam)
# 读取图像并转换为 RGB 格式
image = cv2.cvtColor(cv2.imread("test_image.jpg"), cv2.COLOR_BGR2RGB)
# 设置输入图像,进行预处理和特征提取
predictor.set_image(image)
# 定义点提示坐标和标签(1 表示前景)
masks, scores, _ = predictor.predict(point_coords=np.array([[500, 375]]), point_labels=np.array([1]), multimask_output=True)# 遍历掩码和分数,显示结果
for i, (mask, score) in enumerate(zip(masks, scores)):plt.imshow(image) # 显示原始图像plt.imshow(mask, alpha=0.6) # 显示掩码,透明度为 0.6plt.title(f"Mask {i+1}, Score: {score:.3f}") # 设置标题,显示掩码编号和置信度plt.show() # 显示图像
结果分析:SAM 根据点提示生成多个掩码,分数反映置信度。高分掩码通常更准确,低分掩码可能包含错误分割。
六、总结与展望
SAM 通过高效的图像编码、提示编码和掩码解码实现了灵活的图像分割。未来,其在医学影像、自动驾驶和视频处理中的应用潜力巨大。技术发展方向包括模型轻量化、多模态融合和领域适应,为计算机视觉带来更多可能性。
延伸阅读
-
AI Agent 系列文章
-
计算机视觉系列文章
-
机器学习核心算法系列文章
-
深度学习系列文章
相关文章:
计算机视觉|超详细!Meta视觉大模型Segment Anything(SAM)源码解剖
一、引言 在计算机视觉领域,图像分割是一个核心且具有挑战性的任务,旨在将图像中的不同物体或区域进行划分和识别,广泛应用于自动驾驶、医学影像分析、安防监控等领域。Segment Anything Model(SAM)由 Meta AI 实验室…...
【不动产登记全解析】范围、内容与不予登记的情形
在现代经济社会中,不动产作为重要的资产形式,其权利的确立与流转离不开规范的登记制度。今天,我们就来深入探讨不动产登记的三大核心议题:登记的广泛范围、登记簿上的必备记载事项,以及在哪些情况下不动产登记将不会被…...
机器学习之距离度量方法
常见的距离度量方法及相关函数、图示如下: 1. 欧几里得距离(Euclidean Distance) 函数公式:对于两个 ( n ) 维向量 ( x = ( x 1 , x 2 , ⋯ ,...
2340单点修改、区间查询
2340单点修改、区间查询 ⭐️难度:中等 🌟考点:线段树 📖 📚 import java.util.Scanner;public class Main {static int N 100010;static int n;static int[] c new int[N];static int lowbit(int x){ // 求loub…...
Go语言 vs Java语言:核心差异与适用场景解析
在当今的软件开发领域,Go(Golang)和Java都是备受关注的后端开发语言。尽管二者都能构建高性能服务,但它们在设计哲学、语法特性和应用场景上存在显著差异。本文将从多个维度对比这两种语言,帮助开发者更好地理解它们的…...
18 | 实现简洁架构的 Handler 层
提示: 所有体系课见专栏:Go 项目开发极速入门实战课;欢迎加入 云原生 AI 实战 星球,12 高质量体系课、20 高质量实战项目助你在 AI 时代建立技术竞争力(聚焦于 Go、云原生、AI Infra);本节课最终…...
谷歌Gemma 3:开启AI新纪元的强大引擎
摘要 谷歌公司今日宣布推出最新版本的人工智能模型——Gemma 3。该模型基于Gemini AI技术,是继一年前两款“开放”Gemma AI模型后的进一步发展。Gemma 3以其卓越性能著称,能够在单个GPU上运行,成为迄今为止最强大的AI模型之一。这一技术升级标…...
【Java项目】基于JSP的电子商城系统
【Java项目】基于JSP的电子商城系统 技术简介:采用JSP技术、B/S结构、MYSQL数据库等实现。 系统简介:该电子商城系统包括用户、医生和管理员。其主要功能包括管理员:个人中心、用户管理、医生管理、药品信息管理、线上诊疗管理、医生信息管理…...
双 Token 无感刷新机制在前后端分离架构中实现
在前后端分离的架构中,双 Token 无感刷新是一种常见的身份验证机制,用于在 Access Token 过期时,通过 Refresh Token 自动获取新的 Access Token,从而避免用户频繁登录。 1. 双 Token 无感刷新的核心流程 1.1 核心流程 用户登录&…...
Linux中的基本指令(下)
目录 mv指令 more指令 less指令 head指令 tail 指令 继续理解文件 重定向和追加重定向操作 理解管道 find指令 whereis 指令 bc指令 uname ‒r指令 grep 指令 关机 扩展命令 zip/unzip 指令 tar指令 关于rzsz 系统间的文件互传 接上! mv指令 m…...
电子电气架构 --- 智能电动汽车概述
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 人生是一场骗局,最大的任务根本不是什么买车买房,也不是及时行乐,这就…...
Unity | 工具类:消息管理器-延迟分发
目录 一、消息管理器 二、获得新装备 三、UI面板创建 消息管理器除了简单的订阅(Subscribe)、取消订阅(Unsubscribe)操作以外,还需处理延迟分发(Dispatch)的情况。 (即时处理可参考:Unity | 工具类-利用事件系统进行业务串通-CSDN博客&…...
医院本地化DeepSeek R1对接混合数据库技术实战方案研讨
1. 引言 Deep SEEK R1是一个医疗智能化平台,通过本地化部署实现数据的安全性和可控性,同时提供高效的计算能力。随着医疗信息化的迅速发展,各种数据源的增加使得医院面临更多复杂的挑战,包括如何处理实时监测数据、如何进行大数据环境下的复杂查询以及如何整合多模态数据等…...
GPU加速的国密SM2算法实现
目录 GPU加速的国密SM2算法实现一、前言二、国密SM2算法概述2.1 国密SM2算法背景2.2 SM2的数学基础2.3 SM2数字签名流程三、GPU加速在SM2算法中的应用3.1 高性能运算需求3.2 GPU加速优势3.3 加速实现思路四、基于Python的SM2算法实现与GPU加速4.1 算法模块设计4.2 主要数学公式…...
《UE5_C++多人TPS完整教程》学习笔记35 ——《P36 武器类(Weapon Class)》
本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P36 武器类(Weapon Class)》 的学习笔记,该系列教学视频为计算机工程师、程序员、游戏开发者、作家(Engineer, Programmer, Game Developer, Author) Stephen …...
Linux——Shell运行原理以及Linux权限
目录 1. Shell的运行原理 2. Linux中的权限问题 2.1 Linux权限的概念 2.1.1 如何实现用户账号之间的切换 2.1.2 如何将普通用户添加到信任列表中 2.1.3 如何仅提升当前指令的权限 2.2 Linux权限管理 2.2.1 文件访问者的分类(人) 2.2.2 文件类型…...
SpringBoot注解驱动CRUD工具:spring-avue-plus
项目背景 作为一个后端小伙伴,最大的痛点就是写完的接口需要拥有一些可视化的页面去承载这些功能使用【如果是只给后端那么swagger也足够了,非后端有点呛】如果有专业前端去弄确实也快,但是小公司呀~~~ 学呗~妈呀,现在的前端也挺…...
Redis 数据持久化之AOF
AOF(Append Only File) 以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换…...
API调试工具的无解困境:白名单、动态IP与平台设计问题
引言 你是否曾经在开发中遇到过这样的尴尬情形:你打开了平台的API调试工具,准备一番操作,结果却发现根本无法连接到平台?别急,问题出在调试工具本身。今天我们要吐槽的就是那些神奇的开放平台API调试工具,…...
git commit messege 模板设置 (规范化管理git)
配置方法 git config --global core.editor vim (设置 Git 的默认编辑器为 Vim)在用户根目录下(~),创建一个.git_commit_msg文件,然后把下面的内容拷贝到文件中并保存。 [version][模块][类型]{解决xxx问题…...
串口通信ASCII码转16进制及C#串口编程完整源码下载
在工业自动化、嵌入式系统及物联网以行业中,串口编程非常重要。 串口编程,重点在于串口数据通信和数据处理。 在C#中,System.IO.Ports命名空间提供了SerialPort类,用于实现串口通信。 串口程序的开发主要包括以下几点 1.引用命…...
第十一届蓝桥杯单片机国赛
什么?4T模拟赛和省赛做起来轻轻松松?不妨来挑战一下第十一届国赛,这一届的国赛居然没考超声波、串口通信!只要你正确地理解了题目的意思,规避出题人挖的坑,拿个国一轻轻松松。 附件:第十一届蓝桥…...
Ateme在云端构建可扩展视频流播平台
Akamai Connected Cloud帮助Ateme客户向全球观众分发最高质量视频内容。 “付费电视运营商和内容提供商现在可以在Akamai Connected Cloud上通过高质量视频吸引观众,并轻松扩展。”── Ateme首席战略官Rmi Beaudouin Ateme是全球领先的视频压缩和传输解决方案提…...
QT系列教程(20) Qt 项目视图便捷类
视频连接 https://www.bilibili.com/video/BV1XY41127t3/?vd_source8be9e83424c2ed2c9b2a3ed1d01385e9 Qt项目视图便捷类 Qt项目视图提供了一些便捷类,包括QListWidget, QTableWidget, QTreeWidget等。我们分别介绍这几个便捷类。 我们先创建一个Qt …...
【最后203篇系列】014 AI机器人-1
说明 终于开张了,我觉得AI机器人是一件真正正确,具有商业价值的事。 把AI机器人当成一笔生意,我如何做好这笔生意?一端是业务价值,另一端是技术支撑。如何构造高质量的内容和服务,如何确保技术的广度和深度…...
cfi网络安全 网络安全hcip
目录 RIP (路由信息协议) 算法 开销 版本 开销值的计算方式 RIPV1和RIPV2的区别 RIP的数据包 Request(请求)包 Reponse(应答)包 RIP的特征 周期更新 RIP的计时器 1,周期更新计时器 2,失效计时器 3,垃圾回收计时器 RIP的核心思…...
HTML 基础
一、HTML 基本结构 <!DOCTYPE html> <html> <head><meta charset"utf-8"><title>页面标题</title> </head> <body><!-- 可见内容区域 --> </body> </html><!DOCTYPE html>:声明…...
数据结构与算法:归并排序
目录 归并排序的基本思想 归并排序的特性总结 代码 归并排序的非递归版 归并排序的基本思想 归并排序是建立在归并操作上的一种有效的排序算法。改算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列…...
Tweak Power:全方位电脑系统优化的高效工具
在日常使用电脑时,系统性能的下降、垃圾文件的堆积以及硬盘的老化等问题常常困扰着用户。为了提升电脑性能、优化系统运行,许多人会选择系统优化工具。然而,国内一些系统优化软件常常因为广告过多或功能冗杂而让人望而却步。此时,…...
stm32中分析UART中IDLE,RXNE,TC,TXE这些标志位的作用
下面将基于 STM32 标准库,结合之前提到的不同应用场景,给出使用 TXE、TC、IDLE 和 RXNE 标志位的代码示例及分析。 1. 连续数据发送(使用 TXE) 应用场景 向外部设备连续发送大量数据,如向显示屏发送显示数据、向传感…...
代码随想录算法训练营第十天,150.逆波兰表达式求值,239.滑动窗口最大值,347.前K个高频元素
今日内容:150.逆波兰表达式求值,239.滑动窗口最大值,347.前K个高频元素,栈与队列总结 心得:昨天休息了一天,栈与队列的题都比较典型,之前也是恶补过堆栈的知识,所以做起来相对kmp好一…...
【python】Flask web框架
文章目录 一、Flask 简介二、核心组件解析2.1 路由系统2. 模板引擎 (Jinja2)2.3 表单处理与请求上下文 三、现代开发实践3.1 应用工厂模式3.2 异步处理支持 四、安全最佳实践五、性能优化策略六、扩展生态精选七、部署方案对比 一、Flask 简介 Flask 是基于 Python 的微型 Web…...
Node.js:快速启动你的第一个Web服务器
Node.js 全面入门指南 文章目录 Node.js 全面入门指南一 安装Node.js1. Windows2. MacOS/Linux 二 配置开发环境1. VSCode集成 三 第一个Node.js程序1. 创建你的第一个Node.js程序 四 使用Express框架1. 快速搭建服务器 一 安装Node.js 1. Windows 以下是Windows环境下Node.j…...
3-003:在 MySQL 中建索引时需要注意哪些事项?
在 MySQL 中创建索引时,需要注意以下事项,以确保索引高效且合理: 1. 选择合适的索引类型 主键索引(PRIMARY KEY):每个表只能有一个,默认是聚簇索引。唯一索引(UNIQUE)&…...
基于WPF的雷达上位机系统开发实践
一、雷达上位机系统概述 1.1 系统功能需求 现代雷达上位机系统通常需要实现以下核心功能模块: 数据采集与解析 支持多种通信协议(TCP/IP、UDP、RS422等) 实时解析雷达原始数据(目标距离、方位、速度、RCS等) 典型数…...
版本号标识
Visual Studio 16 2019 是 Microsoft Visual Studio 2019 的版本号标识。具体来说: Visual Studio 是微软提供的一款集成开发环境(IDE),用于开发各种应用程序,如桌面软件、Web 应用、移动应用等,支持多种编…...
计算机考研C语言
C语言程序设计从入门到精通【2025完整版】考研复试 嵌入式 计算机二级 软考 专升本也适用_哔哩哔哩_bilibili 1、第一个C程序 helloC #include <stdio.h>int main(){printf("hehe");return 0;}每个C语言程序不管有多少行代码,都是从main函数开始执…...
STM32 内置的通讯协议
数据是以帧为单位发的 USART和UART的区别就是有没有同步功能 同步是两端设备有时钟连接,异步是没时钟连接,靠约定号的频率(波特率)接收发送数据 RTS和CTS是用来给外界发送已“可接收”或“可发送”信号的,一般用不到…...
QT:串口上位机
创建工程 布局UI界面 设置名称 设置数据 设置波特率 波特率默认9600 设置数据位 数据位默认8 设置停止位 设置校验位 调整串口设置、接收设置、发送设置为Group Box 修改配置 QT core gui serialport 代码详解 mianwindow.h 首先在mianwindow.h当中定义一个串口指…...
f QT测试
# 添加 Qt Test 模块,用于支持单元测试功能 QT testlib# 添加 Qt 的核心模块和 GUI 模块,这是构建 Qt 应用程序的基础模块 QT core gui# 如果 Qt 的主版本号大于 4,则添加 widgets 模块。 # 这是因为 Qt Widgets 模块是从 Qt 5 开始引…...
vue3在ts中动态添加DOM(1、使用render函数,2、使用tsx)
1、使用render函数和h函数 h函数创建虚拟节点(VNode),render函数实现虚拟节点生成真实DOM元素 实现添加一个el-button按钮 <script setup lang"ts"> import { ElButton } from "element-plus"; //需要在页面中引…...
C++基础(VScode环境安装)
MinGW Distro - nuwen.net 安装完成之后我们打开刚刚的安装路径,找到并打开MinGW -> bin,进入bin文件夹之后点一下这里,右键复制路径 之后我们进入设置,搜索“环境变量”,选择“编辑系统环境变量” 按WinR,输入cmd࿰…...
MySQL:SQL优化实际案例解析(持续更新)
文章目录 一、MySQL:SQL优化1、时间格式化问题(字符串)2、in/inner join的问题 一、MySQL:SQL优化 1、时间格式化问题(字符串) -- 优化前 SELECT * FROM test_table WHERE date_format( begin_time, %Y-%…...
代理(Delegate)、闭包(Closure)、Notification(通知中心) 和 swift_event_bus适用场景和工作方式
在 Swift 开发中,在 Swift 开发中,代理(Delegate)、闭包(Closure)、Notification(通知中心) 和 swift_event_bus 主要用于 组件之间的通信,但它们的适用场景和工作方式有…...
力扣第585题
with t as (select *, count(tiv_2015) over(partition by tiv_2015) cnt1 , count(*) over(partition by lat,lon) cnt2 from insurance) select round(sum(tiv_2016),2) tiv_2016 from t where cnt1>1 and cnt21; 以上代码的思路: ①明确查询需求:…...
C++学习——顺序表(四)
文章目录 前言一、最大连续1的个数二、差的绝对值为K的数对数目三、数组中两元素的最大乘积四、数组元素和与数字和的绝对值的差五、K个元素的最大和六、等差三元组的数目七、移除元素 前言 本文为《C学习》的第14篇文章,今天通过Leetcode的几道题来熟悉顺序表的大…...
java虚拟机(JVM)以及各种参数详解
Java 虚拟机(JVM)提供了许多参数来调整其行为和性能,以便更好地适应不同的应用场景。理解和使用这些参数对于优化 Java 应用程序的性能非常重要。以下是一些常用的 JVM 参数及其详细说明: 1. 内存管理参数 -Xms<size>&…...
Android电量与流量优化
Android电量与流量优化 一、电量优化基础 1.1 电量消耗原理 Android设备的电量消耗主要来源于以下几个方面: 屏幕显示:屏幕是耗电量最大的硬件之一,尤其是高亮度和高刷新率的屏幕。CPU处理:CPU执行计算任务时会消耗大量电量,尤其是高负载运算。网络通信:移动数据、Wi-…...
机器人运动学与动力学
在当今科技飞速发展的时代,机器人已逐渐渗透到我们生活的方方面面,从工业生产线上的高效作业,到医疗领域的精准辅助,再到家庭服务的贴心陪伴,机器人技术的广泛应用正深刻改变着我们的生活和工作方式。而在机器人技术的…...
【web前端开发】HTML排版标签、HTML语义化标签、常用的文本标签
1、HTML排版标签 标签名 标签含义 单/双标签 h1~h6 …...