Atlas 300V实战:从零部署YOLO推理全流程

发布时间:2026/9/25 9:22:57

Atlas 300V实战:从零部署YOLO推理全流程 拿到Atlas 300V 24G这块卡的时候我第一反应其实是有点懵的。群里有人问这是不是运算加速卡还有人问能不能拿来跑YOLO但官方手册写得云里雾里社区里的帖子又零散得很。我花了差不多两周时间从刷固件、配CANN到把YOLOv5的ONNX模型转成OM格式再写代码把推理跑通中间踩的坑比过去一年加起来都多。这篇文章就是想把Atlas到底怎么用起来这件事完整捋一遍特别围绕YOLO部署这条主线给正准备入坑的人一条能直接照着走的路。1. Atlas 300V 24G这块卡先把它说透1.1 它到底是什么性质的硬件先回答热搜里那个问题Atlas 300V 24G是不是运算加速卡是但不是GPU那种通用加速卡。它本质上是华为昇腾系列的AI推理加速卡核心芯片是昇腾310P系列主打的是INT8精度下的神经网络推理加速。你可以把训练理解为出题推理理解为做题——这块卡就是专门用来大规模快速做题的不是用来出题的。这也就意味着如果你拿它去跑训练会非常难受。虽然它理论上有FP16能力但驱动、软件栈、算子优化全都是朝着推理场景优化的。真正适合它的活儿是视频流里跑目标检测YOLO系列是典型场景图像分类、特征提取这类CV推理转码加推理一体化的视频分析应用多路并发的在线推理服务我个人是拿它来做边缘侧视频结构化服务的一路视频流接入实时跑YOLOv5检测行人车辆再输出结构化结果。这个场景用这块卡很合适因为它功耗低、体积也不夸张能塞进2U服务器里做高密度推理。1.2 24G显存版与常见型号的参数对照Atlas 300V这个家族不算复杂但从型号看很容易眼晕。我做了个表把我接触过的几款放在一起对比方便你判断自己手里的卡到底是哪个档次型号显存标称INT8算力功耗典型定位Atlas 300V24GB LPDDR4X约140 TOPS72W左右标准推理卡24G大显存是卖点Atlas 300V Pro24GB LPDDR4X约140 TOPS72W左右增强版接口和编解码能力略强Atlas 300I Pro24GB约140 TOPS72W左右主打视频图像分析Atlas 300I Duo48GB双芯约280 TOPS150W左右两张300I Pro合体这里要划个重点24G这个显存看似不大但对于推理场景真的够用。YOLOv5s的INT8模型转成OM格式后大小只有十几MB就算YOLOv8l这种大模型INT8量化完也就几十MB。24G显存意味着你可以同时塞进几十上百路视频流的模型副本或者跑一个很大的batch这是这块卡性价比的核心来源。算力方面140 TOPS是INT8稀疏算力实际拿到的有效算力要看模型结构、算子融合情况、是否开启多batch等等。别被宣传数字冲昏头脑后面我会放实测数据给你参考。1.3 什么场景该选它什么场景别碰它先泼一盆冷水如果你的需求是我要用PyTorch随便训练一个模型不要买Atlas直接买NVIDIA显卡省心。昇腾的训练栈虽然现在也能用了但生态成熟度跟CUDA比还是有差距。反过来如果你是以下情况Atlas 300V就非常香手头有训练好的ONNX模型YOLO、ResNet、BERT等要做推理部署对功耗有硬性要求机房或边缘机柜电费敏感需要高密度部署一台机器插多张卡产品面向信创或国产化场景硬件选型有合规要求Atlas 300V 24G还有一个优点是好买。相比Atlas 800训练服务器那种动辄几十万的大家伙单张推理卡的价格亲民得多个人开发者搞一张研究研究也算能承受。我这张就是公司采购的测试卡渠道走的是正规代理到手还带了全套线材和转接板。2. 部署YOLO前的环境底子驱动、固件、CANN的版本搭配2.1 拿到卡片后第一步刷固件和装驱动的顺序这块卡不是你插上就能用的。我先把正确的顺序给你再讲为什么必须按这个顺序来安装物理卡确认被系统识别lspci能看到设备安装NPU驱动Driver安装固件Firmware安装CANN工具包配置环境变量并验证顺序错一步后面全白搭。我最开始就是先装了CANN再装驱动结果ascend-dmi工具跑不起来报了一堆设备节点错误查了半天才反应过来是顺序问题。驱动和固件的获取路径是华为昇腾社区的软件包下载页面。需要注意下载的时候选对硬件型号和操作系统版本这两者的匹配矩阵官方有一个兼容性列表务必对照着查。我用的环境是Ubuntu 20.04 x86_64 内核5.4驱动选的对应版本固件选的配套版本。安装驱动比较简单chmod x Ascend-hdk-*.run ./Ascend-hdk-*.run --full --install-for-all装完驱动后用npu-smi info命令验证一下能看到卡的温度、显存占用、算力状态说明驱动层OK了。2.2 CANN工具包到底装哪个版本CANN是昇腾的计算架构全称是Compute Architecture for Neural Networks类似CUDA在NVIDIA生态里的位置。模型转换工具ATC、AI推理框架、算子库全都在CANN里。CANN的版本迭代比较快社区版基本上半年左右就有一个大版本。我的建议是别追最新版选稳定版。新版本往往伴随着算子行为变化老旧模型可能出现意想不到的兼容问题。我目前用的是CANN 7.0版本系列配合Atlas 300V系列稳定性不错。CANN安装也走.run包chmod x Ascend-cann-toolkit_*.run ./Ascend-cann-toolkit_*.run --install装完之后最重要的一件事是source环境变量source /usr/local/Ascend/ascend-toolkit/set_env.sh这个环境变量不source后面ATC工具找不到、python导入acl报错全都会冒出来。我习惯把它写进~/.bashrc省得每次开终端都手动敲一遍。2.3 环境变量配置里最容易翻车的地方环境变量这块有两个点特别容易被忽略我单独拎出来说。第一个是PYTHONPATH。CANN的python接口叫pyACL它在toolkit里的python目录下。如果你用的是虚拟环境conda venv之类一定要把CANN的python路径加进去否则import acl会直接报ModuleNotFoundError。第二个是芯片型号的标识。ATC转换模型时需要一个--soc_version参数它决定了生成OM格式时针对哪个芯片做算子优化。Atlas 300V 24G对应的是Ascend310P3或Ascend310P4视具体Pro版本而定。这个参数填错了比如填成Ascend310转换能成功但跑起来性能会差很多因为算子没有针对310P系列优化。验证环境是否就绪可以用一条命令ascend-dmi -i -t能看到设备健康状态、算力温度曲线就说明驱动、固件、CANN三层都通了。到这一步环境准备工作才算真正收尾。3. YOLO模型落地的关键一步ONNX到OM的ATC转换3.1 前置工作导出带动态轴的ONNX从训练框架到昇腾推理中间隔着模型格式的鸿沟。PyTorch的.pt文件不能直接被昇腾加载需要先导出成ONNX再用ATC工具转成昇腾的OM格式。导出ONNX这一步看起来简单但有个关键坑YOLO模型里的NMS非极大值抑制操作导成ONNX时要格外小心。常规做法是导出时把检测头拆开让输出保留为原始特征图把NMS留给后处理在CPU上做。这背后的原因有两个一是NMS操作本身有循环和动态shapeONNX导出时可能会出warning甚至error尤其老版本的torch.onnx.export对这类动态控制流支持不好。二是即使导出成功ATC转换时NMS算子也可能不支持。昇腾的算子库虽然覆盖了常见算子但NMS这类逻辑复杂的算子覆盖情况不稳定跨版本差异很大。我导出的做法是在YOLO的模型类里加一个export模式forward里只保留backboneneckhead去掉NMS然后用固定shape导出比如640x640输入。虽然昇腾支持动态shape但固定shape在ATC转换时能做更多图优化推理延迟更低。import torch def export_onnx(model, pathyolov5s.onnx): model.eval() dummy_input torch.randn(1, 3, 640, 640) torch.onnx.export( model, dummy_input, path, opset_version11, input_names[images], output_names[output], dynamic_axesNone # 固定shape后续ATC转换最稳妥 )3.2 ATC转换命令参数逐个拆解ATC工具是昇腾模型转换的重头戏命令行参数看着多但核心就是那么几个。我先给一个实际可用的转换命令atc --modelyolov5s.onnx \ --framework5 \ --outputyolov5s_om \ --input_shapeimages:1,3,640,640 \ --soc_versionAscend310P3 \ --insert_op_confaipp_yolov5.cfg \ --output_typeFP32 \ --input_formatNCHW各参数的含义我拆开讲--model输入的ONNX模型路径--framework55代表ONNX这是ATC约定的编码0是Caffe1是MindSpore别记错--output输出OM文件的路径前缀--input_shape输入张量的shape跟ONNX导出时的输入对齐--soc_version指定目标芯片型号这个前面说了必须填对--insert_op_conf插入AIPP预处理配置这个很有用后面单独说--output_type输出精度通常FP32就够了转换成功的标志是终端打印出ATC run success并生成了.om文件。如果中途报错最常见的就是算子不支持Operator XX not supported解法有两种一是升级CANN版本到更新算子库二是修改模型结构避开该算子。YOLO系列模型基本没遇到过算子不支持的场景除非你加了很奇怪的模块。3.3 关于AIPP图像预处理到底该放模型里还是放卡上AIPP是昇腾的AI预处理模块可以在硬件层面完成图像缩放、减均值、除方差、颜色通道转换等操作。它的核心价值是把预处理从CPU卸载到硬件上推理pipeline更短。我问一个直击灵魂的问题YOLO部署时图像resize到640x640这个操作放哪里做最合适放CPU上用OpenCV做简单但是占用CPU周期放模型里做加一个resize层浪费算力且效果不好放AIPP做硬件完成CPU零开销显然AIPP是最优解。AIPP的配置文件长这样aipp_op { aipp_mode: static input_format: YUV420SP_U8 src_image_size_w: 1920 src_image_size_h: 1080 crop { crop_size_w: 640 crop_size_h: 640 } resize { src_image_size_w: 1920 src_image_size_h: 1080 } csc_switch: true rbuv_swap_switch: false mean_chn_0: 0 mean_chn_1: 0 mean_chn_2: 0 }这里input_format要根据你的输入源来定。我的输入是视频解码后的YUV420SP数据所以在AIPP里做YUV到RGB的转换。如果你输入的是jpg解码后的RGB图像直接把input_format改成RGB888_U8就行。需要注意用了AIPP之后喂给模型的数据不再需要你在代码里做预处理。如果你代码里既用了AIPP又手动做了resize出来的推理结果会完全错乱这个我踩过惨痛教训。3.4 动态batch和动态分辨率什么时候用什么时候别用ATC支持把模型转成动态shape版本也就是转换时输入shape写-1运行时再指定实际shape。听起来很灵活但代价是性能——动态shape下算子融合和图优化的空间变小推理延迟普遍比固定shape高20%-30%。我的经验是能用固定shape就坚决用固定。YOLO推理服务面对的视频流分辨率一般是固定的1920x1080输入resize到640x640这个链路完全确定动态shape毫无必要。只有当你无法预知输入分辨率时才考虑动态shape方案。如果确实需要动态ATC命令里这样写atc --modelyolov5s.onnx \ --framework5 \ --outputyolov5s_dynamic \ --input_shapeimages:-1,3,-1,-1 \ --dynamic_dims640;960;1280 \ --soc_versionAscend310P3注意dynamic_dims那里分号分隔的是可选的分辨率档位。运行时模型会按最近匹配的原则选一个档位执行做不到真正的任意尺寸推理。4. 推理代码怎么写pyACL方式跑通YOLOv5/v84.1 初始化、资源申请和模型加载转到代码环节。pyACL是昇腾的Python推理接口整体流程可以归纳为初始化-申请设备-加载模型-准备输入输出-执行推理-后处理。先看初始化这段import acl # 初始化 ret acl.init() assert ret 0, facl.init failed: {ret} # 申请设备0是设备ID ret acl.rt.set_device(0) assert ret 0, fset_device failed: {ret} # 创建上下文 context, ret acl.rt.create_context(0) assert ret 0, fcreate_context failed: {ret}这三个步骤是固定的代码结构基本不会变。经验是初始化失败大概率是环境变量没source或者CANN版本和驱动版本不匹配排查优先级最高。模型加载用的是acl.mdl.load_from_file# 加载OM模型 model_id, ret acl.mdl.load_from_file(yolov5s_om.om) assert ret 0, fload model failed: {ret} # 获取模型描述信息 model_desc acl.mdl.create_desc() ret acl.mdl.get_desc(model_desc, model_id)模型描述里包含了输入输出的具体shape、数据类型后面分配内存要用到。建议在加载后打印一下desc里的维度信息确认和ATC转换时的规划一致。4.2 输入输出的数据搬运与内存管理这可能是整个pyACL流程里最容易出错的部分。昇腾的设备内存和主机内存是分开的推理数据必须先搬到设备侧模型输出也要从设备侧搬回来。输入侧的标准流程是创建设备侧内存acl.rt.malloc获取模型输入buffer地址acl.mdl.get_input_data_ptr把图像数据拷贝到设备侧执行模型推理核心代码如下# 创建设备侧内存 dev_ptr, ret acl.rt.malloc(640*640*3, 2) # 这里的2是内存对齐单位固定写2 # 获取模型输入缓存地址 input_ptr acl.mdl.get_input_data_ptr(model_desc, 0) # 把数据拷贝到输入buffer ret acl.rt.memcpy(input_ptr, 640*640*3, dev_ptr, 640*640*3, acl.rt.MEMCPY_DEVICE_TO_DEVICE)这里有个细节很多人会忽略get_input_data_ptr拿到的是模型内部的固定buffer你不需要自己重新malloc直接把数据memcpy到这个ptr上就行。如果你自己malloc了一片新内存再传给推理接口反而可能因为内存对齐告警导致推理失败。输出的处理逻辑类似关键是要知道输出有几个tensor。YOLO模型如果去掉NMS后导出输出通常是一个大tensorshape是[1, 25200, 85]这种格式YOLOv5在640x640输入下。其中25200就是三种特征层预测框数量80x8040x4020x208400乘以3个anchor2520085是4个框坐标1个置信度80个类别概率。这个结构在后处理parse时需要记住。4.3 后处理对齐坐标换算、置信度过滤、NMS拿到模型输出不是终点还得把它变成真正有用的检测框。C代码里大家喜欢用结构化体存储Python里简单numpy数组直接处理。import numpy as np # 假设output是模型输出的numpy数组shape为(25200, 85) boxes output[..., :4] # cx, cy, w, h scores output[..., 4] # 置信度 class_probs output[..., 5:] # 类别概率 # 过滤低置信度框 mask scores 0.5 boxes boxes[mask] scores scores[mask] class_probs class_probs[mask] # 计算最终类别和得分 class_ids class_probs.argmax(axis1) final_scores scores * class_probs.max(axis1)NMS我用的是torchvision.ops.nms或者cv2.dnn.NMSBoxes都可以。如果追求性能建议用C实现后处理或者把NMS放到推理卡的CPU侧做——但这属于后期优化初版先用Python跑通逻辑最重要。有个很隐蔽的坑模型的输出格式取决于导出时怎么写的。如果导出时把检测头拆开分别输出三个特征层各自输出那后处理逻辑就完全是另一套需要分别对三个输出做解码再合并。所以写后处理之前先仔细看一眼ONNX模型的结构或者直接打印输出tensor的shape确认。4.4 实测性能数据与参数调优记录写到这里上一组我的实测数据供你参考。测试环境硬件Atlas 300V 24G模型YOLOv5s输入640x640INT8量化后OM约15MB输入视频流抽帧1920x1080 - AIPP resize到640x640精度FP32输出项目数据单帧模型推理延迟约8-12ms端到端单路延迟含解码前后处理约25-30ms单芯片并发路数1080p视频12-16路连续运行72小时稳定性无异常显存占用稳定整卡功耗约50-70W这个数据对于一台2U服务器来说性价比非常能打。如果换成YOLOv8s推理延迟差不多在10-15ms路数会略降。如果上YOLOv8n或者YOLOv5n这种轻量模型单帧延迟甚至可以压到5ms以内。一个提升吞吐量的小技巧是开batch。比如同一个模型同时喂batch4的数据虽然单batch延迟会从8ms升到15ms左右但吞吐量翻了约2.5倍。这个trade-off对视频流多路场景很划算毕竟视频流天然就是多路并发的。5. 多路并发与生产化配置建议5.1 异步推理与流水线设计初版代码只要能跑通单帧推理距离能上生产还有一大步。视频分析场景中最影响体验的就是并发能力。昇腾提供了异步推理接口核心思想是提交推理-立刻返回-稍后取结果这样在等推理完成的同时CPU可以继续做下一帧的预处理。官方推荐的标准流水线是线程A负责拉流和解码把解码后的帧放入队列线程B负责AIPP预处理和模型推理用异步接口发请求线程C负责后处理和结果上报这个方案跑起来后单路的吞吐优化空间就打开了。我实际跑下来同样的模型异步方案比同步方案端到端延迟低了大概40%。异步接口的关键是acl.mdl.execute_asyncret acl.mdl.execute_async(model_id, input_ptr, output_ptr, batch_num, stream)其中stream需要先创建stream, ret acl.rt.create_stream()注意异步推理的所有内存操作必须在同一个stream上下文中同步时用acl.rt.synchronize_stream。5.2 显存放不下模型副本时怎么办24G显存看起来大但如果你同时加载多个不同模型比如一个YOLO做检测一个ResNet做分类再一个OCR模型做文字识别叠加起来还是挺可观的。我遇到过一种情况模型加载成功了但推理时频繁报device memory not enough排查了半天是显存碎片化问题。解决思路有三个业务上错峰加载不同模型不同时间段使用加载新模型前先卸载旧模型复用一个context不同模型共享同一个device和context减少上下文切换开销减小AIPP缓存如果AIPP设置的图像尺寸过大显存会被预留给大图处理可以动态调整其中复用context是最推荐的也是我实际用到的方案。代码上就是加载多个模型到同一个context推理时按model_id区分调用。5.3 运维侧的几个监控姿势生产环境里除了让功能跑通还要让问题能被及时发现。昇腾提供了npu-smi命令行工具建议写进监控体系里。# 查看所有卡的状态 npu-smi info # 查看指定卡的详细信息和算力使用 npu-smi info -t board -i 0 npu-smi info -t usages -i 0重点关心的指标有三个温度超过85度就要检查风道和散热显存占用持续超过80%要评估是否扩容或优化模型算力使用率如果长期跑不满检查是不是CPU侧的前后处理成了瓶颈我还习惯写一个定时脚本每5分钟把npu-smi的到日志里出问题时可以回溯。5.4 最后的提醒多卡并联和分布式推理如果你有更高的算力需求Atlas 300V是支持多卡并联的。一台机器插4张卡通过昇腾的集合通信库做数据分发。但我要说句实话多卡并联的复杂度上升不是线性的至少是平方级。驱动配置、PCIe带宽、任务调度都要重新考虑。一个更接地气的建议是先单卡跑通把卡的能力吃透再决定要不要上多卡。很多客户场景单卡24G就已经富余了你与其纠结多卡并行不如把单卡的batch调度和异步流水线打磨到极致这带来的收益更大也不折腾人。我个人最近在做的扩展是用Atlas 300V同时跑YOLOv8加一个轻量姿态估计模型一个做检测一个做关键点利用24G大显存把两个模型同时驻留效果意外地好。这种一卡多模型的玩法反而是很多用户没充分挖掘的方向。
延伸阅读

更多相关文章

2026/9/25 9:22:57

Atlas 300V Pro部署YOLOv8全流程实战:从环境配置到推理调优

最近后台和私信里被问得最多的一件事,就是Atlas 300V Pro 24G这块卡到底怎么样,网上炒得火热,有人说是运算加速卡,有人说是智商税,还有人问能不能拿来跑YOLO。说实话,这块卡我前后折腾了小一个月&#xff0…

2026/9/25 10:13:00

正则表达式[1-9]完全指南:字符集、量词与数字匹配实战

正则表达式里的[1-9],恐怕是每个新手都会写、但又未必真的理解的一行小玩意儿。很多人一看“匹配1到9”,随手就写/[1-9]/,结果在"10"里匹配不到、在"123"里又只匹配到一个字符,一脸懵。其实[1-9]是一个字符集…

2026/9/25 10:13:00

微信小程序酒店管理系统三端源码解析与本地跑通实战

简介:这是一套面向高校计算机相关专业毕业设计场景的微信小程序酒店管理系统全套源码,适合正在准备毕设或课程设计的学生、需要快速搭建酒店业务原型的开发者参考。系统由前台管理、后台管理与用户手机端小程序三部分构成,覆盖在线预订、客户…

2026/9/25 10:13:00

MyBatis框架原理与核心特性深度解析:从动态代理到缓存实战

用MyBatis写增删改查几年了,坦白说,很多人用了很久也未必真搞懂这个框架的底层逻辑。它表面上是个“简化JDBC的持久层框架”,但实际运行起来,动态代理、反射、缓存链、类型处理器这些机制全都堆在里头。我刚毕业那会儿用MyBatis&a…

2026/9/25 10:08:00

VMware虚拟机USB直通实战:笔记本摄像头连接与排错指南

1. 为什么要在虚拟机里折腾摄像头把笔记本摄像头直通给 VMware 虚拟机,这个需求听起来小众,实际踩坑的人非常多。我最早碰到这个场景,是要在虚拟机里跑一个视频采集的测试程序,宿主机是 Windows,虚拟机里装的是 Ubuntu…

2026/9/24 20:24:47

GAMP 5 基于风险的计算机化系统验证:软件分类与审计追踪实践

简介:《A Risk-Based Approach to Compliant GxP Computerized Systems》即业内熟知的GAMP 5指南,面向制药企业质量与IT合规人员、验证工程师及计算机化系统管理者,用于解决GxP法规环境下系统合规性难以科学落地的问题。文档以风险管理为主线…

2026/9/23 12:06:55

安全托管MSSP实战:从静态防御到人机协同的攻防运营与应急响应

简介:这份PPT围绕互联网业务安全托管服务展开,面向企业安全负责人、IT运维人员及关注MSSP/MSS选型的读者,重点回应传统安全过度依赖人工、碎片化静态防御难以对抗产业化攻击等痛点。资源共1个pptx文件,包体约30.63MB,以…

2026/9/25 0:02:35

AI元人文:从工具使用到思维重构的深度探索

最近半年我一直在琢磨一件事:AI元人文到底是什么?说白了,就是“用元视角重新审视人与AI的关系”,也在“探索AI如何反向逼着我们发现自己的思考边界”。标题里的“元探索”,在我看就是一层套一层的追问——当你用AI解决…

2026/9/25 0:02:35

Python+CNN车牌识别实战:从数据预处理到模型训练与部署

简介:基于Python与卷积神经网络的车牌识别项目,面向计算机视觉初学者及智能交通开发者,目标是帮助用户掌握从数据预处理、模型构建到实际部署的完整流程。压缩包共25个文件,包含jpg/png图像样本、py训练脚本、md说明文档、dat数据…

2026/9/25 0:02:35

Vim基础操作全攻略:保存退出、模式切换与高频命令实战

1. 项目概述1.1 核心需求解析今天聊聊Vim。写这个题目的原因是:几乎每个后端开发者、运维人员、数据工程师某天都会遇到一个场景——深夜加班,服务器登录界面只有黑底白字,编辑器只有vi/vim,你必须在五分钟内完成一次配置修改并保…

2026/9/22 16:34:32

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/22 20:01:30

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/22 13:25:41

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑