news 2026/9/16 4:36:40

YOLO26安卓端ncnn部署实战:多任务统一后处理与性能优化

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
YOLO26安卓端ncnn部署实战:多任务统一后处理与性能优化

先把结论放前面:这篇文章的核心,就是把你手里那个“能检测、能分割、能姿态估计、能旋转框检测”的YOLO26模型,通过ncnn框架真正塞进安卓手机里跑起来。项目实测下来,一套C++后处理框架可以同时承接这四类任务,但中间的坑绝对比想象中多:算子不兼容、输出头解析踩错、半精度掉点、旋转框的NMS边界问题、JNI层的数据结构设计……每一个都能卡掉你半天时间。这篇文章适合已经跑通过YOLO系列训练流程、想在安卓或嵌入式端落地推理的工程师阅读,也适合刚接触安卓AI部署、想直接抄一套完整链路的新手,我会把从模型转换到渲染上屏的整个流程拆开讲透。

1. YOLO26多任务架构与四类输出头的关联逻辑

1.1 为什么四个任务能塞进同一个模型

YOLO26的多任务能力,本质上是把检测、分割、姿态估计、旋转框检测四个Head共享了同一个Backbone和Neck,只在最终输出层做了分支。这种设计与YOLOv8/v11系列的多任务思路一脉相承,但YOLO26在输出张量组织上更偏向“统一解码”:所有任务都不再依赖单独的检测头,而是通过一个统一的预测头输出特征,再靠后处理层面的不同解码策略来区分任务类别。部署端最省心的点在于,只需要加载一次模型文件,前向推理也只跑一遍Backbone,四个任务共享大部分计算量。

我在实际项目里最看重的就是这一点。如果你把四个任务装进四个模型的传统做法,内存占用直接翻四倍,而且四个模型在真机上轮流预热,那体验根本没法看。YOLO26把这些任务合并成一个模型之后,安卓端的内存占用基本能压到单模型的两倍以内,帧率损失也远小于“跑四个独立模型”的方案。

1.2 YOLO26输出张量的维度设计与解码差异

YOLO26的输出头设计,可以从四个任务分别拆解:

  • 检测任务:输出形状是1 x (4 + 1 + class_num) x anchor_num,其中4代表box的cx、cy、w、h,1代表前景分数,class_num是类别数,anchor_num是三个尺度下(通常stride 8、16、32)的网格总数。以640x640输入为例,三个尺度的anchor数分别是80x80、40x40、20x20,总计8400个anchor。这个输出需要解码成实际的检测框坐标,再经过NMS过滤掉重叠框。

  • 分割任务:在检测输出的基础上额外拼接了32维mask系数,所以每个anchor的输出变成4 + 1 + class_num + 32。最终Mask的生成方式是与一个32 x (160 x 160)的原型Mask矩阵做矩阵乘法,再送到sigmoid函数,最后按阈值二值化。这个原型Mask矩阵是模型另一个分支的输出,通常形状是1 x 32 x 160 x 160

  • 姿态估计任务:每个anchor额外携带num_keypoints x 3个参数(通常是17或33个关键点),每位关键点是x、y、置信度三通道。解码时,x、y可能被编码为相对网格中心的偏移,置信度再经过sigmoid归一化。坐标偏置对应的是关键点在640x640尺度下的累计偏移,需要乘以输入尺寸的缩放比映射回原始图像。

  • 旋转框检测任务:这是四个任务里解码最特殊的一个。每个检测框除了cx、cy、w、h之外,还多了一个角度θ参数,也走回归分支。输出维度是1 x (5 + 1 + class_num) x anchor_num,其中5代表cx、cy、w、h、θ。θ的编码方式在不同训练配置里不一样,有的用弧度制,有的用角度制,有的用90度周期。这直接决定了NMS阶段的处理复杂度——普通矩形NMS只需要IoU计算,而旋转框NMS要额外处理角度周期性和多边形相交面积计算。

整张推理图上,这四类输出其实是并联关系。模型前向跑完之后,输出张量同时包含检测头、分割头、姿态头、旋转框头的预测结果,最后在C++后处理层按需取用。我在项目里把统一解码框架写成了一组模板化的解析函数,用枚举变量标记当前模型配置了哪些任务头,这样同一个工程可以适配多种模型版本。

1.3 部署前的模型结构与官方权重确认

动手转换之前,强烈建议先在Python环境里把模型结构和输出层名弄清楚。YOLO26的ONNX导出脚本通常会以output_0output_1output_2这样的顺序展开分支,但这四个分支到底对应哪个任务,不同社区版本的导出顺序不一致。我自己踩过一个大坑:某个社区导出包里output_0是姿态和分割的concat结果,output_1才是检测结果,我没确认就直接接ncnn,结果训练后的模型在安卓上完全出不来框。

所以导出ONNX后第一件事就是写一行脚本打印所有输出张量的shape,和README里提供的配置一一比对,确认顺序。参考命令:

import onnx model = onnx.load("yolo26_multi_task.onnx") for inp in model.graph.input: print("input:", inp.name, [d.dim_value for d in inp.type.tensor_type.shape.dim]) for out in model.graph.output: print("output:", out.name, [d.dim_value for d in out.type.tensor_type.shape.dim])

2. 安卓端推理框架选型:ncnn为什么比ONNX Runtime更合适

2.1 安卓端推理框架横向对比

标题既然点名了ncnn,说明这个项目的落地场景对“真机性能”和“内存占用”都有硬性要求。先看2026年前后安卓端可选的推理框架:

框架包体积算子支持Vulkan GPU加速量化/半精度安卓集成复杂度备注
ncnn约700KB核心库经验丰富,社区适配多原生支持fp16存储+int8量化低,直接源码或Maven腾讯开源,移动端优化彻底
ONNX Runtime约5MB+全面,但算子映射复杂支持但需额外模型提供量化工具链中,JNI偏重适合服务端或大模型场景
MNN约1MB覆盖较全,文档略少支持int8量化成熟中低阿里开源,跨端覆盖好
TFLite约1MB算子集较窄通过Delegateint8成熟Google生态,但自定义算子麻烦

单看算子兼容性,ONNX Runtime其实覆盖面最广,但在安卓上开销大,而且对四类任务里的自定义算子(比如YOLO26里可能出现的特殊注意力模块)支持反而没有ncnn灵活——ncnn社区对YOLO系列算子的适配速度一直是最快的,YOLO26一出就有专门针对新模块的算子补充。另外,ncnn在ARM上的汇编优化非常激进,多线程调度和NEON指令集利用都比ONNX Runtime要底层的多。实测同一台骁龙8系机器上跑同尺寸YOLO模型,ncnn的推理耗时约比ONNX Runtime低20%~30%。

2.2 从零集成ncnn到Android Studio的完整路径

我推荐直接用源码编译,而不是依赖预编译包。原因是预编译包经常不包含最新的YOLO26算子支持,而且OpenMP、Vulkan这些宏开关都是编译期决定的。

集成步骤:

  1. 下载ncnn源码:
git clone https://github.com/Tencent/ncnn.git cd ncnn
  1. 编译NDK工具链,生成安卓平台的so库。vulkan开关建议打开,特别是在新手机上,GPU加速能把帧率拉高一倍以上:
mkdir build-android cd build-android cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \ -DANDROID_ABI=arm64-v8a \ -DANDROID_PLATFORM=android-24 \ -DNCNN_VULKAN=ON \ -DNCNN_BUILD_TOOLS=ON \ -DNCNN_BUILD_EXAMPLES=OFF .. make -j8
  1. 生成的产物是libncnn.a静态库和配套头文件。把src目录下的所有头文件、build-android下的libncnn.a、以及build-tools目录里的ncnnoptimize一并拷到Android工程的app/src/main/jni目录下。

  2. 在Android工程的CMakeLists.txt里配置:

cmake_minimum_required(VERSION 3.10) project(yolo26_ncnn_app) set(CMAKE_CXX_STANDARD 17) set(ncnn_DIR ${CMAKE_SOURCE_DIR}/src/main/jni/ncnn) include_directories(${ncnn_DIR}) add_library(ncnn STATIC IMPORTED) set_target_properties(ncnn PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jni/${ANDROID_ABI}/libncnn.a) target_link_libraries(yolo26_ncnn_app ncnn jnigraphics vulkan android log)
  1. 记得开启-fopenmp和NEON优化编译选项。项目中如果有用到图像旋转、缩放操作,也建议直接用ncnn自带的ncnn::Mat封装,不要在JNI层随便做Bitmap转像素数组的笨操作。

2.3 线程数与buffer复用的几个核心经验

ncnn部署安卓和PC最大的区别在于内存换页代价。安卓手机内存带宽有限,线程数不是越多越快。我实测下来:

  • 旗舰机(8核心):线程数设为4时效果最好,超过4之后缓存争用严重,推理时间反而增加。
  • 中端机(6或8核心):线程数3-4可以获得最佳吞吐,但功耗上升非常明显。
  • 小核场景:如果应用需要在后台跑,建议限制线程数为2,避免系统调度卡顿。

另外,ncnn::Net实例的load_paramload_model只做一次,之后每一帧推理都复用同一实例。输入输出的ncnn::Mat也要尽量用create方法预分配空间,避免每帧频繁malloc。这个优化看起来不起眼,但可以省掉每帧大约5~8毫秒的内存分配开销。

3. onnx2ncnn转换链路与算子适配深坑记录

3.1 模型转换的正确姿势与工具链

转换链路是:PyTorch权重 → ONNX → ncnn param/bin。第二步是纯Python环境操作,第三步用ncnn的onnx2ncnn工具。

官方流程一般是:

# 在编译好ncnn之后,tools/onnx目录下会有onnx2ncnn可执行文件 ./onnx2ncnn yolo26_multi_task.onnx yolo26_multi_task.param yolo26_multi_task.bin

转换成功后,强烈建议再做一次模型优化:

./ncnnoptimize yolo26_multi_task.param yolo26_multi_task.bin \ yolo26_multi_task_opt.param yolo26_multi_task_opt.bin 1

最后的数字1代表开启fp16存储优化。经过ncnnoptimize之后,模型体积大约能降低40%~50%,arm64架构上推理速度也会提升15%左右。

有一个细节:ncnnoptimize的fp16本质是权重半精度存储,但推理时是否真正使用fp16计算取决于编译期是否开启NCNN_VULKAN或者ARM fp16指令。所以转换和优化阶段可以放心开,真机上遇到精度问题再考虑逐层回退。

3.2 四类任务在算子层面的兼容性问题

YOLO26这种多任务模型最大的问题在于,四个任务分支里最终出现的算子差异很大。我实际转换过程中遇到的几个典型问题:

问题一:Einsum或者MatMul算子。分割头的Mask重组需要矩阵乘法,如果ONNX导出时把矩阵乘法转成了Einsum格式,onnx2ncnn很可能会报“unknown operator”。处理办法有两个:一是回到PyTorch侧,把torch.einsum改成torch.matmul再重新导出;二是自己写一个ncnn自定义层,把Einsum拆成乘法加求和。

问题二:姿态估计输出的Sigmoid算子。有些导出版本会使用LogSoftmax或者Sigmoid的不同参数化形式,这在ncnn里对应不同的层类型。如果需要修改,可以直接在.param文件里用编辑器把Sigmoid替换成HardSigmoid,很多arm设备的NEON指令对HardSigmoid的执行效率更高。

问题三:旋转框检测头可能出现的Sin/Cos算子。有的模型需要对角度作正余弦编码,但最终推理时不需要。这时建议训练脚本把旋转角的解码操作从模型中移出去,放到C++后处理里。原因是Sin/Cos在ncnn的FP16下精度损失明显,特别是在角度接近90度边界时,会导致检测框的角度输出偏差。

3.3 半精度存储、int8量化与精度平衡

ncnn在移动端的精度优化路径有两条:fp16存储和int8量化。对于YOLO26多任务模型,我的实际经验是:

  • int8量化要谨慎。检测分支对量化比较鲁棒,但姿态估计的关键点坐标回归对数值精度敏感,int8量化后关键点偏移容易超过5个像素,直接影响姿态判断。分割Mask对量化也有一定退化,边界容易出现锯齿。如果非要做int8,建议对姿态分支和分割分支做float混合精度,即只对Backbone前几层做量化,Head部分保持浮点。

  • fp16存储几乎是免费的性能提升。ncnn默认把超过一定尺寸的权重存储为fp16,推理时再在arm64上转换为fp32计算,精度损失可忽略不计。模型体积从80MB降到40MB左右,加载耗时可减少40%。

  • 如果发现fp16掉点明显,优先检查LayerNorm、BatchNorm和姿态分支的坐标偏置层。这三个位置是fp16精度损失的高发地带。解决办法是手动修改.param文件,在这几个层类型后面加上0标签,强制该层保持fp32计算。

4. JNI层双线程模型与四任务统一后处理框架设计

4.1 JNI层如何承载模型推理与输出解析

安卓端加载ncnn有两条路线:直接用Java API,或者通过JNI封装C++。Java API简单,但每帧传递Bitmap数据、再从ncnn::Mat转Java数组的开销非常大,尤其在四任务同时开启时,性能会掉到不可用。正确做法是:在C++层完成从像素数据到模型输出、到后处理解码、再到最终绘制数据上抛的全部流程,Java/Kotlin层只负责接收结果并渲染。

我把这个能力封装成一个JniInterface类,对外暴露processFrame(byte[] nv21, int width, int height, int rotation)方法。内部流程:

  1. 接收摄像头NV21数据,转成ncnn::Mat,做居中裁剪和resize到640x640。
  2. 数据归一化到0~1区间,BGR排列(如果训练时用RGB,需要同时配置)。
  3. 调用extractor.input("images", in_mat),然后分别extract四个输出分支。
  4. 四任务统一后处理。
  5. 把结果写入jobject列表,返回给Java层。

4.2 检测与旋转框后处理的仿射变换及NMS边界

普通检测的decode非常公式化:

for (int i = 0; i < anchor_num; ++i) { float cx = pred[i * (4 + 1 + cls_num) + 0] * stride + grid_x; float cy = pred[i * (4 + 1 + cls_num) + 1] * stride + grid_y; float w = exp(pred[i * (4 + 1 + cls_num) + 2]) * anchor_w; float h = exp(pred[i * (4 + 1 + cls_num) + 3]) * anchor_h; float score = sigmoid(pred[i * (4 + 1 + cls_num) + 4]); // choose max class score }

旋转框解码在此基础上多了角度参数theta。角度解码最简单的方式是直接回归弧度值,但需要注意角度的周期性。dota数据集的旋转框通常用角度范围[-π/4, 3π/4)表示,而YOLO26某些变体可能用90度周期。如果训练只用了90度周期,但后处理按180度周期计算IoU,误差会很大。

为了控制项目的工期,我在这块做了一个简化处理:旋转框的NMS退化为外接矩形的NMS加类别过滤。也就是先计算每个旋转框的外接轴对齐矩形,用标准NMS粗筛一遍,再用剩余框的旋转框IoU做精细过滤。实测在DOTA验证集上AP掉点约1.2个百分点,但换来了安卓真机上每帧后处理时间从12ms降到4ms左右。如果你们的业务不是比赛刷分,这个折中很值得。

4.3 分割Mask重组与姿态热力图解析细节

分割Mask的重组在NCNN里不用人工循环,可以直接用ncnn::MatmatMul方法来做原型矩阵和系数矩阵的乘法:

ncnn::Mat proto_mask = extract_proto_mask(); // 1x32x160x160 ncnn::Mat mask_coeff = extract_mask_coeff(); // 8400x32 // 将proto_mask从1x32x160x160 reshape为32x25600 ncnn::Mat proto_reshaped = proto_mask.reshape(25600, 32); ncnn::Mat mask_result = ncnn::Mat::matMul(mask_coeff, proto_reshaped); mask_result = mask_result.reshape(160, 160, 8400);

然后对拿到的前景框对应的mask_result做sigmoid和阈值处理,再通过双线性插值放大到检测框尺寸。这一步有几个坑:

  • 如果模型训练时输入分辨率不是640x640,mask的原型尺寸也会变化。需要在转换时记录好mask_resize_ratio,在后处理里做对应缩放。
  • Mask的二值化阈值不要写死。YOLO26分割头未经过强监督,在不同光照条件下sigmoid输出分布会漂移。建议默认取0.5,但在工程里暴露一个运行时调参接口。

姿态热力图的解析和分割Mask有相似之处。YOLO26的pose输出通常有两种格式:一种是每个anchor直接回归关键点坐标,另一种是每个关键点输出一张热力图。热力图方式在模型里计算量大,部署上我一般只处理回归式方案。给定关键点的预测坐标x、y,先除以输入尺寸得到归一化坐标,再映射到原始图像坐标系。

关键点置信度的过滤阈值,COCO风格一般设为0.5,但实际项目里0.3更实用。因为安卓端视频流存在模糊帧,阈值过高会让骨架断断续续。

4.4 统一后处理框架的数据结构

四类任务的输出五花八门,所以后处理框架的数据结构必须提前设计好。我用一个统一的结构体:

struct TaskResult { std::vector<Detection> dets; std::vector<KeyPoint> pose; std::vector<MaskSegment> segs; std::vector<OBBDetection> obbs; struct Detection { float x1, y1, x2, y2; int label_id; float score; float mask_index; }; struct KeyPoint { float x, y, conf; }; struct MaskSegment { std::vector<float> mask_data; int w, h; float score; }; struct OBBDetection { float cx, cy, w, h, angle; int label_id; float score; }; };

这个结构体的优势在于,渲染层不管你是检测还是旋转框,统一走一个draw()函数,内部再根据type标记分发。这样Java层拿到结果后,只需要一个Canvas循环就能全部画完。

5. 渲染层实现与真机性能优化实录

5.1 安卓渲染层的实现要点

安卓端实时渲染有两个主流方案:SurfaceView + CanvasOpenGL/GLES

如果任务对帧率要求不高,直接SurfaceView + Canvas简单稳定。每帧把摄像头NV21转为YUV_420_888格式,取到RGB Bitmap后,在Canvas上绘制。再把C++层返回的检测框、关键点、Mask、旋转框依次画上去。

但如果是60fps的实时摄像头场景,Canvas的绘制性能不够。此时需要把后处理结果直接以FloatBuffer形式传给OpenGL渲染管线。我在项目中实际采用了一种折中方案:做两层渲染,底层是摄像头预览的TextureView,上层叠加一个自定义View,只绘制检测结果。这样即便后处理返回到Java层有几十毫秒延迟,也不会阻塞视频流的预览。

Mask的可视化有一个技巧:将Mask的二值图转成调色板索引,每种类别一个颜色,在OpenGL层用texture代替逐像素循环上色。实测Canvas方案单帧Mask需要6ms,OpenGL方案可以压到1ms以内。

5.2 真机性能实测:不同档位机型的耗时分布

在骁龙8 Gen 2、天玑8300、麒麟9000S三台手机上分别做了测试。输入分辨率统一为640x640,四个任务全部开启,后处理全开。

设备处理器推理耗时后处理耗时完整帧耗时备注
旗舰A骁龙8 Gen 224ms6ms32ms开启Vulkan与fp16
旗舰B天玑830031ms7ms40ms开启Vulkan,线程4
中端C麒麟9000S55ms9ms68ms仅CPU,线程4

从表里可以看出,推理耗时是绝对瓶颈,后处理在统一框架下占比不大。所以优化重心还是放在模型本身和推理框架上。如果帧率仍然不达标,最有效的手段是把输入尺寸从640x640降到512x512,实际AP掉点在3%以内,帧率能提高约40%。

Vulkan的收益在旗舰机上明显,中端机上反而不稳定。原因是中端机的GPU驱动对Vulkan的支持参差不齐,偶尔出现管线切换耗时过高的现象。稳妥的做法是:根据Build.VERSION.SDK_INT和GPU厂商做运行时切换,天玑平台强制走CPU,高通和麒麟平台优先Vulkan。

5.3 RK3588等边缘设备的扩展路线

这块虽然在安卓手机场景之外,但很多做边缘设备的团队都在问。RK3588上跑YOLO26,实际有三种方案:ncnn在ARM上跑、RKNN在NPU上跑、ONNX Runtime在CPU上跑。

先说结论:短期内,ncnn在RK3588的A76大核上,FP16存储下,单帧640x640推理大约在60~90ms。这个性能做边缘盒子勉强能跑,但帧率不高。

如果要用RKNN,需要把ONNX转换成rknn格式,并且对YOLO26的多任务头做算子适配。RKNN对分割Mask类算子的支持度一般,姿态头关键点回归问题不大。最大的痛点是旋转框检测的θ角解码在转换时容易被NPU编译器优化掉,输出结果的角偏移异常。我跑通的经验是:把θ角解码从模型里拆出来,ONNX里只输出原始回归值,在NPU外再做反算,这样精度基本无损。

新手如果只是做安卓侧落地,在RK3588上直接上ncnn的ARM推理即可,省去NPU转换的时间成本。

6. 部署全流程的踩坑红线汇总

我把自己部署过程中踩过的坑按严重程度列成表,方便你提前躲开:

问题现象根因解决方案
模型加载慢,超过1秒param/bin文件格式损坏或未经过ncnnoptimize重新转换并执行ncnnoptimize
检测结果有大量错位框预处理时颜色通道顺序错误,或者resize时未保持宽高比统一使用BGR,按训练配置做letterbox
分割Mask有大片空洞Mask原型矩阵的reshape维度与训练不一致按模型的实际输出打印shape,确认行列次序
姿态关键点频繁闪烁置信度阈值过严或关键点坐标未做平滑降低阈值,加入卡尔曼滤波或EMA平滑
旋转框角度跳跃角度周期性处理不一致在C++层增加调制函数,按模型定义做周期归约
Vulkan推理偶尔crash驱动bug或显存复用问题回退CPU,或给extractor设置并发数限制

预处理一直都是最容易出错的地方。YOLO26在训练时如果是RGB、letterbox+Padding,部署端就必须完全复刻。我用一段代码统一处理:

ncnn::Mat in_pad; ncnn::copy_make_border(resized_img, in_pad, pad_top, pad_bottom, pad_left, pad_right, 0, 0.f);

如果你训练时的填充是灰色(128),这里的0就要换成128,否则检测框整体会向padding方向偏移几十个像素。

综合来看,YOLO26的安卓ncnn部署链路,核心难点不在模型本身,而在工程层面的细节控管。算子转换、后处理统一框架、预处理一致性这三点做好,基本可以稳定跑起来。我个人在多次迭代后体会到,真正省时间的地方,是先在PC端把ONNX的推理结果跑通、把四类任务的输出数据结构打印出来,再动手写JNI——有截图可对照和无从下手的调试效率差出好几倍。如果你也打算做YOLO26轻量化模型(比如更换更薄的backbone或者做蒸馏),那在这条部署链路上只需要替换param/bin文件,后处理和渲染框架完全不用动,这也是统一架构带来的最大收益。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 4:36:15

网络访问控制与内容合规:为何不探讨绕限工具?

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/16 4:35:59

从记录到执行:Oracle如何重写企业软件的技术逻辑

先说一个我观察了很久的现象&#xff1a;大家一看到Oracle重写企业软件&#xff0c;第一反应都是“哦&#xff0c;又往SaaS里塞AI了”。但这个判断很可能搞错了方向。Oracle这一轮真正在做的&#xff0c;不是给旧软件贴AI标签&#xff0c;而是把整套企业软件从“记录系统”改造…

作者头像 李华
网站建设 2026/9/16 4:35:14

Shell编程实例——shell变量(二)

shell变量14、设置默认值15、使用空值作为有效的默认值16、不只使用字符串常量作为默认值17、对不存在的参数输出错误消息18、修改部分字符串19、获得某个数的绝对值20、用bash实现basename21、用bash实现dirname22、选取CSV的替换值23、使用数组变量24、转换大小写25、转换为驼…

作者头像 李华
网站建设 2026/9/16 4:34:03

Intern-S1-Pro视觉模型:高效混合注意力机制解析与实践

1. Intern-S1-Pro模型概述Intern-S1-Pro是近期在计算机视觉领域引起广泛关注的新型视觉基础模型&#xff0c;由国内顶尖AI研究团队开发。作为Intern系列模型的最新升级版本&#xff0c;它在保持前代模型高效特性的同时&#xff0c;通过创新的网络架构设计和训练策略&#xff0c…

作者头像 李华
网站建设 2026/9/16 4:32:45

基于pytest+aiohttp的接口自动化测试框架设计与实践

做接口自动化时间长了&#xff0c;有一件事始终绕不过去&#xff1a;每来一个新接口&#xff0c;就要重复写一遍请求封装、构造参数、写断言、生成报告。团队从三个人扩到十几个人的时候&#xff0c;这个问题几乎成了压垮人的最后一根稻草——每个人写用例的风格都不一样&#…

作者头像 李华