上个月帮一个做智能门禁的客户解决边缘端部署的难题:他们用Jetson Nano 4GB做终端,跑YOLOv8n做人脸和陌生人检测,原生PyTorch推理一帧要400多毫秒,一秒钟只能跑2帧,画面卡成PPT,根本达不到门禁场景25帧的实时要求。客户找了好几波人,要么优化后速度上去了,精度掉得没法用,要么就是TensorRT转换疯狂报错,根本跑不起来。

我抱着试试的心态接了,前前后后在Jetson上踩了快一个月的坑——从环境搭建的版本地狱,到ONNX导出的算子不兼容,再到TensorRT量化的精度崩了,最后把全流程跑通:YOLOv8n 320x320输入,TensorRT FP16量化,单帧推理稳定在31ms,一秒32帧,mAP50只掉了0.8%,完全满足客户的实时要求,客户直接把尾款翻倍打了过来。

今天就把这套针对低算力边缘设备的TensorRT优化YOLOv8全攻略全部分享出来,从环境搭建到模型微调,从ONNX导出到TensorRT转换,再到边缘端部署的极致优化,全是我踩坑踩出来的干货,没有半句虚话。哪怕你用的是树莓派、瑞芯微RK3588这类更低算力的设备,跟着走也能跑通实时推理。

一、先讲清楚:为什么低算力边缘端必须用TensorRT?

很多刚接触边缘部署的朋友,总觉得“我把模型换成nano版本,输入尺寸改小一点,不就能跑了?”,但实际试过就知道,PyTorch是为训练设计的框架,推理时带了大量的冗余操作,哪怕是YOLOv8n,在Jetson Nano这种CPU四核A57、GPU只有128个CUDA核心的低算力设备上,原生推理速度慢到离谱。

而TensorRT是NVIDIA专门为GPU推理做的SDK,核心就是做极致的性能优化,能给低算力设备带来质的飞跃:

  1. 计算图优化:把YOLO里的卷积、激活、归一化等多层算子融合成一个,减少GPU的核函数调用开销,这是速度提升最核心的点
  2. 量化加速:FP32转FP16,推理速度直接翻倍,显存占用减半,精度几乎无损失;进阶INT8量化,速度再翻一倍,适合极致性能要求
  3. 内存复用:自动优化GPU内存的申请与释放,避免边缘设备有限的内存出现频繁颠簸,解决卡顿问题
  4. 硬件适配:针对Jetson这类边缘GPU的架构做了专属优化,能把每一丝算力都榨干

给大家看一下我在Jetson Nano 4GB上的实测数据,同模型同输入尺寸,差距一目了然:

推理方案 单帧推理时间(320x320) FPS 显存占用 mAP50(门禁人脸数据集)
PyTorch原生FP32 426ms 2.3 1.2GB 95.2%
ONNX Runtime FP16 187ms 5.3 860MB 95.1%
TensorRT FP16 31ms 32.2 420MB 94.4%
TensorRT INT8 16ms 62.5 280MB 92.1%

二、第一大坑:环境搭建,版本对齐是唯一的活路

这是90%的人卡在第一步的原因,尤其是Jetson这类arm架构的边缘设备,环境和x86 PC完全不一样,瞎用pip装包,只会陷入“装不上→装上了用不了GPU→版本不兼容报错”的死循环。

我前前后后刷了5次Jetson系统,总结出了零踩坑的环境版本对应表,针对最常用的Jetson Nano、Jetson Xavier NX、Jetson Orin NX全适配,建议直接抄作业,别自己瞎试:

Jetson设备 JetPack版本 CUDA版本 cuDNN版本 TensorRT版本 PyTorch版本 ultralytics版本 Python版本
Jetson Nano 4.6.1 10.2 8.2.1 8.2.1 1.12.0 8.0.228 3.8
Xavier NX 5.1.2 11.4 8.4.1 8.4.1 1.13.0 8.1.0 3.8
Orin NX/Orin Nano 6.0 12.2 8.9.4 8.5.2 2.0.1 8.2.0 3.10

零踩坑环境搭建步骤

  1. 系统刷机:用NVIDIA官方的SDK Manager,给Jetson刷对应版本的JetPack,必须用官方刷机工具,不要用第三方镜像。刷完之后,CUDA、cuDNN、TensorRT就已经自带了,不用自己手动装,这是避免90%环境问题的核心。
  2. 验证基础环境:刷机完成后,在终端输入以下命令,确认所有组件都正常:
    # 验证CUDA
    nvcc -V
    # 验证TensorRT
    dpkg -l | grep TensorRT
    
    能正常输出版本号,就说明基础环境没问题。
  3. 安装PyTorch:Jetson是arm架构,不能用pip直接装PyTorch官方的x86版本,必须用NVIDIA官方编译好的PyTorch wheel包,对应JetPack版本下载安装,地址在NVIDIA开发者论坛就能找到。
  4. 安装依赖包
    # 安装ultralytics,必须对应上面的版本
    pip install ultralytics==8.0.228
    # 安装ONNX相关依赖
    pip install onnx==1.12.0 onnxruntime-gpu==1.12.1 onnx-simplifier==0.4.10
    # 安装图像处理依赖
    pip install opencv-python==4.8.0.74 numpy==1.23.5
    

踩坑实录

  • 千万别用pip install tensorrt,Jetson自带的TensorRT是和硬件、CUDA深度绑定的,pip装的版本根本不兼容,装上了也调用不了GPU。
  • 别装太高版本的ultralytics,老版本JetPack的CUDA/TensorRT不支持新的YOLOv8算子,会出现转换报错,我用8.0.228版本是兼容性最好的。
  • 一定要用Python 3.8,JetPack 4.6.1自带的Python就是3.8,别自己升级Python版本,不然所有依赖都要重新编译,大概率会失败。

三、前置优化:针对边缘端的YOLOv8模型轻量化微调

很多人直接拿COCO预训练的YOLOv8n模型就去转TensorRT,结果要么速度不够,要么精度不符合场景要求。低算力设备部署,模型本身的轻量化优化,比后期的TensorRT优化更重要,我做了3个核心优化,在不损失业务精度的前提下,给模型“瘦身”,为后续TensorRT优化打下基础。

1. 输入尺寸优化:放弃640,选320/416

YOLO默认的640x640输入,是为了兼顾COCO数据集里的小目标,但大多数边缘端场景,比如门禁、工业检测、车载环视,目标距离摄像头很近,尺寸很大,320x320的输入完全足够识别。

输入尺寸从640降到320,计算量直接降到原来的1/4,推理速度直接翻倍,而针对近距离目标的检测精度,几乎没有损失。我做门禁场景,320输入比640输入,mAP50只掉了0.3%,速度翻了2.3倍。

2. 模型结构裁剪:只保留你需要的

COCO预训练模型有80个类别,而大多数边缘端业务场景,只需要检测1-5个类别,比如门禁只需要检测人脸、陌生人,工业检测只需要检测缺陷,完全可以把多余的检测头、卷积层裁剪掉。

核心裁剪技巧:

  • 导出模型时,只指定你需要的类别,比如classes=[0]只检测人,ultralytics会自动过滤掉其他类别的权重
  • 用ultralytics的prune功能,对模型做结构化剪枝,剪掉权重值接近0的卷积核,模型体积能再减30%
  • 替换激活函数:老版本TensorRT对SiLU激活函数的优化不如ReLU,边缘端可以把SiLU替换成ReLU,速度能再提10%,精度损失极小

3. 场景化微调:把精度补回来

模型裁剪、输入尺寸改小之后,用自己的业务场景数据集做微调,把损失的精度补回来。微调的核心技巧:

  • 冻结骨干网络,只训练检测头,避免破坏预训练权重,收敛速度快,还不容易过拟合
  • 小学习率,lr0=0.001,用余弦退火学习率,训练30-50个epoch就足够
  • 开启小目标增强,针对边缘场景的小目标做Mosaic、MixUp增强,弥补输入尺寸缩小带来的精度损失

最简微调训练命令

yolo detect train \
  data=your_scene.yaml \  # 你的业务数据集配置文件
  model=yolov8n.yaml \    # 用nano版本的配置文件
  pretrained=yolov8n.pt \ # 加载预训练权重
  epochs=50 \
  batch=8 \                # Jetson Nano建议batch=8,不然会OOM
  imgsz=320 \              # 边缘端用320输入
  freeze=10 \              # 冻结前10层骨干网络
  lr0=0.001 \
  cos_lr=True \
  mosaic=1.0

四、核心步骤一:ONNX导出与优化,避开90%的TensorRT转换报错

YOLOv8转TensorRT,90%的报错都出在ONNX导出这一步。ONNX是PyTorch和TensorRT之间的桥梁,ONNX模型导出得不好,要么TensorRT转换直接报错找不到算子,要么转换成功了,速度也慢得离谱。

我踩了无数坑,总结出了边缘端专用的ONNX导出命令,直接复制就能用,几乎不会报错:

yolo export \
  model=runs/detect/train/weights/best.pt \  # 你微调好的模型
  format=onnx \
  imgsz=320 \               # 和训练时的输入尺寸一致,固定尺寸
  opset=11 \                # 重点!opset用11,老版本TensorRT兼容性最好
  simplify=True \           # 必须开!简化计算图,去掉冗余算子
  dynamic=False \           # 重点!边缘端必须关动态轴,固定尺寸优化更极致
  batch=1 \                 # 边缘端单帧推理,batch=1就够
  device=0                  # 用GPU导出,确保算子兼容

必须重点讲的3个坑,90%的人都踩过

  1. dynamic=True动态轴的坑:很多人导出时开了动态轴,想适配不同的输入尺寸,结果在边缘端,TensorRT对动态轴的优化极差,推理速度比固定尺寸慢了50%以上,还容易出现显存溢出。边缘端场景输入尺寸都是固定的,绝对不要开动态轴
  2. opset版本太高的坑:很多人直接用默认的opset=17,结果老版本TensorRT根本不支持里面的新算子,转换时疯狂报错Unsupported ONNX operator。opset=11是兼容性最好的版本,YOLOv8的所有核心算子都支持,老版本TensorRT也能完美转换。
  3. 不开simplify的坑:不开onnx-simplifier的话,ONNX模型里会有大量的Shape、Gather等冗余算子,TensorRT转换时要么报错,要么没法做算子融合,速度上不去。simplify=True必须开,能把计算图简化到极致,为TensorRT优化打下最好的基础。

导出后验证ONNX模型

导出完成后,一定要先验证ONNX模型的精度,避免转换过程中出现精度损失:

yolo val model=best.onnx data=your_scene.yaml imgsz=320

如果验证出来的mAP和PyTorch模型相差不超过1%,就说明ONNX导出没问题,可以进行下一步的TensorRT转换。

五、核心步骤二:TensorRT模型转换,FP16是必做,INT8是进阶

ONNX模型没问题之后,就可以转换成TensorRT的engine模型了,这一步是速度提升的核心。我分两种方案讲:新手必做的FP16量化,和进阶的INT8量化,覆盖不同的性能需求。

重点提醒:绝对不能跨架构转换

很多人图省事,在自己的x86电脑上转好engine文件,拷贝到Jetson上用,结果直接报错,根本运行不了。TensorRT的engine文件是和硬件架构、CUDA版本、TensorRT版本深度绑定的,x86的engine不能在arm架构的Jetson上用,必须在目标边缘设备上本地转换。

方案一:FP16量化转换(新手必选,零精度损失)

FP16量化是边缘端部署的首选,能在几乎不损失精度的前提下,把推理速度翻倍,显存占用减半,转换成功率100%,几乎不会报错。

我给大家写了一个一键转换的Python脚本,直接在Jetson上运行就行:

import tensorrt as trt
import os

def onnx2tensorrt(onnx_file_path, engine_file_path, fp16_mode=True):
    # 创建TensorRT日志器,WARNING级别只打印重要信息,DEBUG可以看详细报错
    TRT_LOGGER = trt.Logger(trt.Logger.WARNING)
    # 创建构建器、网络、配置
    builder = trt.Builder(TRT_LOGGER)
    network = builder.create_network(1 << int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH))
    parser = trt.OnnxParser(network, TRT_LOGGER)
    
    # 解析ONNX模型
    print("开始解析ONNX模型...")
    with open(onnx_file_path, "rb") as f:
        if not parser.parse(f.read()):
            # 打印解析错误
            for error in range(parser.num_errors):
                print(f"ONNX解析错误:{parser.get_error(error)}")
            return None
    print("ONNX模型解析成功!")
    
    # 配置构建参数
    config = builder.create_builder_config()
    # 设置工作空间大小,Jetson Nano建议4GB,不要超过设备的显存大小
    config.set_memory_pool_limit(trt.MemoryPoolType.WORKSPACE, 1 << 32)  # 4GB
    
    # 开启FP16量化
    if fp16_mode and builder.platform_has_fast_fp16:
        config.set_flag(trt.BuilderFlag.FP16)
        print("已开启FP16量化模式")
    
    # 构建engine
    print("开始构建TensorRT Engine,Jetson Nano上可能需要5-10分钟,请耐心等待...")
    serialized_engine = builder.build_serialized_network(network, config)
    if serialized_engine is None:
        print("Engine构建失败!")
        return None
    
    # 保存engine文件
    with open(engine_file_path, "wb") as f:
        f.write(serialized_engine)
    print(f"Engine构建成功!已保存到:{engine_file_path}")
    return engine_file_path

# 执行转换
if __name__ == "__main__":
    ONNX_FILE = "best.onnx"
    ENGINE_FILE = "yolov8n_fp16.engine"
    onnx2tensorrt(ONNX_FILE, ENGINE_FILE, fp16_mode=True)

方案二:INT8量化转换(进阶,极致性能)

如果FP16的速度还满足不了你的需求,比如要在树莓派这类更低算力的设备上跑,可以尝试INT8量化,能把推理速度再翻一倍,但是会有一定的精度损失,需要用校准集来控制精度。

INT8量化的核心是校准集:必须用和你的业务场景完全一致的图片做校准,比如你做门禁,就用门禁场景的100-500张图片做校准集,不能用COCO的通用图片,不然精度会直接崩掉。

核心转换步骤和FP16基本一致,只需要添加强制INT8模式和校准器,代码比较长,我放在了我的GitHub仓库里,需要的朋友可以去拿。

踩坑实录

  • Jetson Nano构建Engine的时候,一定要关闭其他占用GPU内存的程序,不然会出现内存不足,构建失败。
  • 工作空间大小不要设得超过设备的显存,Jetson的内存是CPU和GPU共享的,设得太大会导致系统卡死。
  • INT8量化如果精度掉得太多,先检查校准集是不是和业务场景匹配,再增加校准集的图片数量,一般200-500张就足够了。

六、核心步骤三:边缘端部署推理,Python简单上手,C++极致性能

Engine文件构建完成后,就可以在边缘端部署推理了。我分两种方案讲:Python部署,上手简单,适合快速验证;C++部署,性能极致,适合量产落地。

方案一:Python部署(快速验证,新手友好)

Python部署代码简单,不用编译,直接就能跑,适合快速验证模型效果。我写了一个完整的推理脚本,包含预处理、推理、后处理全流程,直接复制就能用:

import tensorrt as trt
import pycuda.driver as cuda
import pycuda.autoinit
import cv2
import numpy as np
import time

class YOLOv8_TRT:
    def __init__(self, engine_path, imgsz=320, conf_thres=0.4, iou_thres=0.45):
        self.imgsz = imgsz
        self.conf_thres = conf_thres
        self.iou_thres = iou_thres
        self.class_names = ["person"]  # 替换成你的类别名称
        # 加载TensorRT Engine
        self.TRT_LOGGER = trt.Logger(trt.Logger.WARNING)
        with open(engine_path, "rb") as f:
            self.engine = trt.Runtime(self.TRT_LOGGER).deserialize_cuda_engine(f.read())
        self.context = self.engine.create_execution_context()
        # 分配GPU和主机内存
        self.inputs, self.outputs, self.bindings, self.stream = self.allocate_buffers()
    
    def allocate_buffers(self):
        inputs = []
        outputs = []
        bindings = []
        stream = cuda.Stream()
        for binding in self.engine:
            size = trt.volume(self.engine.get_binding_shape(binding)) * self.engine.max_batch_size
            dtype = trt.nptype(self.engine.get_binding_dtype(binding))
            # 分配锁页内存和GPU内存
            host_mem = cuda.pagelocked_empty(size, dtype)
            device_mem = cuda.mem_alloc(host_mem.nbytes)
            bindings.append(int(device_mem))
            # 区分输入输出
            if self.engine.binding_is_input(binding):
                inputs.append({"host": host_mem, "device": device_mem})
            else:
                outputs.append({"host": host_mem, "device": device_mem})
        return inputs, outputs, bindings, stream
    
    def preprocess(self, img):
        # 图像预处理:resize、归一化、CHW格式转换
        h, w = img.shape[:2]
        # 等比例缩放,避免变形
        scale = min(self.imgsz / w, self.imgsz / h)
        new_w, new_h = int(w * scale), int(h * scale)
        img_resized = cv2.resize(img, (new_w, new_h))
        # 填充到正方形
        pad_w, pad_h = self.imgsz - new_w, self.imgsz - new_h
        img_padded = cv2.copyMakeBorder(img_resized, 0, pad_h, 0, pad_w, cv2.BORDER_CONSTANT, value=(114, 114, 114))
        # 转换格式
        img_rgb = cv2.cvtColor(img_padded, cv2.COLOR_BGR2RGB)
        img_normalized = img_rgb / 255.0
        img_transposed = img_normalized.transpose(2, 0, 1).astype(np.float32)
        img_contiguous = np.ascontiguousarray(img_transposed)
        return img_contiguous, scale, pad_w, pad_h
    
    def postprocess(self, output, scale, pad_w, pad_h):
        # 后处理:reshape、置信度过滤、NMS、坐标还原
        output = output.reshape(-1, 4 + 1 + len(self.class_names))
        # 过滤低置信度框
        output = output[output[:, 4] > self.conf_thres]
        if len(output) == 0:
            return []
        # 计算类别置信度
        class_conf = output[:, 5:] * output[:, 4:5]
        class_id = np.argmax(class_conf, axis=1)
        class_conf = np.max(class_conf, axis=1)
        # 转换bbox格式,还原到原图坐标
        boxes = output[:, :4].copy()
        # 中心点xy、宽高 → 左上角xy、右下角xy
        boxes[:, 0] = (boxes[:, 0] - boxes[:, 2] / 2 - pad_w / 2) / scale
        boxes[:, 1] = (boxes[:, 1] - boxes[:, 3] / 2 - pad_h / 2) / scale
        boxes[:, 2] = (boxes[:, 0] + boxes[:, 2] - pad_w / 2) / scale
        boxes[:, 3] = (boxes[:, 1] + boxes[:, 3] - pad_h / 2) / scale
        # NMS非极大值抑制
        indices = cv2.dnn.NMSBoxes(boxes.tolist(), class_conf.tolist(), self.conf_thres, self.iou_thres)
        # 整理结果
        results = []
        if len(indices) > 0:
            for i in indices.flatten():
                results.append({
                    "bbox": boxes[i].astype(int).tolist(),
                    "class_id": int(class_id[i]),
                    "class_name": self.class_names[int(class_id[i])],
                    "confidence": float(class_conf[i])
                })
        return results
    
    def infer(self, img):
        # 完整推理流程
        img_processed, scale, pad_w, pad_h = self.preprocess(img)
        # 拷贝输入到GPU
        np.copyto(self.inputs[0]["host"], img_processed.flatten())
        cuda.memcpy_htod_async(self.inputs[0]["device"], self.inputs[0]["host"], self.stream)
        # 执行推理
        self.context.execute_async_v2(bindings=self.bindings, stream_handle=self.stream.handle)
        # 拷贝输出到主机
        for output in self.outputs:
            cuda.memcpy_dtoh_async(output["host"], output["device"], self.stream)
        self.stream.synchronize()
        # 后处理
        output = self.outputs[0]["host"]
        results = self.postprocess(output, scale, pad_w, pad_h)
        return results

# 测试推理
if __name__ == "__main__":
    # 初始化模型
    model = YOLOv8_TRT("yolov8n_fp16.engine", imgsz=320, conf_thres=0.4)
    # 读取测试图片
    img = cv2.imread("test.jpg")
    # 测试100次,计算平均推理时间
    total_time = 0
    for i in range(100):
        start = time.time()
        results = model.infer(img)
        end = time.time()
        total_time += (end - start)
    avg_time = total_time / 100 * 1000
    print(f"平均单帧推理时间:{avg_time:.2f}ms,FPS:{1000/avg_time:.1f}")
    # 可视化结果
    for res in results:
        x1, y1, x2, y2 = res["bbox"]
        cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
        cv2.putText(img, f"{res['class_name']} {res['confidence']:.2f}", (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
    cv2.imwrite("result.jpg", img)

方案二:C++部署(量产落地,极致性能)

Python部署虽然简单,但是在低算力边缘设备上,Python的GIL锁会带来一定的性能损耗,预处理和后处理的速度会比C++慢很多。量产落地一定要用C++部署,能把性能榨到极致。

C++部署的核心逻辑和Python完全一致,分为:Engine加载、内存分配、预处理、推理、后处理,完整的工程代码我放在了GitHub仓库里,这里给大家讲核心的优化点:

  1. 预处理GPU加速:用CUDA核函数做resize、归一化、格式转换,不要用OpenCV在CPU上做预处理,Jetson的CPU很弱,GPU加速预处理能省10ms以上的时间。
  2. TensorRT插件化NMS:把后处理的NMS放到TensorRT里用插件实现,不用在CPU上做NMS,减少CPU-GPU的数据拷贝,又能省5ms以上的时间。
  3. 多线程流水线:用3个线程分别做视频流读取、推理、后处理可视化,流水线并行,解决RTSP流的延迟问题,做到真正的低延迟实时推理。
  4. 内存复用:全程复用GPU和主机内存,不要每次推理都申请释放内存,避免边缘设备的内存颠簸,解决卡顿问题。

七、极致优化技巧:把低算力设备的性能榨干

上面的基础流程跑通之后,还能通过这些优化技巧,再提升20%-50%的推理速度,完全榨干低算力设备的每一丝性能:

  1. 跳帧推理:监控视频流一般是25帧/秒,人的动作不会在1帧里发生巨大变化,每2帧做一次推理,中间的帧用跟踪器预测目标位置,速度直接翻倍,对检测精度的影响几乎可以忽略不计。
  2. ROI区域检测:边缘端场景大多有固定的检测区域,比如门禁只检测门口的区域,工业检测只检测传送带的区域,只对ROI区域做推理,不用处理整张图,速度能再提30%以上。
  3. 关闭不必要的系统服务:Jetson系统默认会开很多没用的服务,比如桌面、蓝牙、打印服务,把这些服务关掉,能释放更多的CPU和内存给推理用,速度能提升10%左右。
  4. Jetson性能模式拉满:用sudo nvpmodel -m 0把Jetson开到最大性能模式,sudo jetson_clocks锁定CPU和GPU频率,避免自动降频导致的推理速度波动。

八、终极避坑指南:这些坑我踩了一个月,你别再踩了

  1. 版本对齐的坑:这是最核心的坑,JetPack、CUDA、TensorRT、PyTorch、ultralytics的版本必须严格对应,Jetson上绝对不要自己手动装CUDA/TensorRT,用JetPack自带的版本,能避开90%的问题。
  2. 跨架构转换的坑:绝对不要在x86电脑上转Engine文件放到Jetson上用,必须在目标边缘设备上本地转换,不然根本运行不了。
  3. 动态轴的坑:边缘端固定输入尺寸,绝对不要开动态轴,不然TensorRT优化不到极致,速度慢一半,还容易显存溢出。
  4. opset版本的坑:ONNX导出时opset用11,不要用太高的版本,老版本TensorRT不支持新算子,会出现转换报错。
  5. 内存溢出的坑:Jetson Nano只有4GB共享内存,batch size不要设太大,固定输入尺寸,关闭不必要的程序,不然很容易OOM。
  6. 量化精度的坑:新手先从FP16开始,不要上来就INT8,INT8量化必须用和业务场景一致的校准集,不然精度会直接崩掉。

写在最后

这套方案我给客户的门禁设备用了快3个月,运行极其稳定,Jetson Nano上32帧实时推理,连续开机72小时没有出现卡顿、崩溃,误检率和漏检率完全满足业务要求。

很多人觉得边缘端AI部署是大厂的专利,需要高深的底层知识,其实不是的。只要你找对了方法,避开了那些坑,用TensorRT把YOLOv8优化到极致,哪怕是Jetson Nano、树莓派这类低算力设备,也能跑实时的AI推理。

对于我们程序员来说,技术的价值从来不是炫技,而是在有限的硬件条件下,解决实际的业务问题。你可以用这套方案做智能门禁、工业检测、车载环视、安防监控,只要有想法,就能在边缘端落地。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐