基于EagleEye DAMO-YOLO TinyNAS的智能垃圾分类系统

每天早上,小区里的垃圾桶旁总能看到这样的场景:一位阿姨拿着垃圾袋,对着几个不同颜色的垃圾桶犹豫不决,嘴里念叨着“这个塑料瓶是可回收的,那这个沾了油的餐巾纸算什么?” 这不仅是她一个人的困惑,更是城市垃圾分类推广中普遍存在的痛点。人工分拣效率低、成本高,而且分类标准复杂,普通人很难完全掌握。

有没有一种方法,能让垃圾桶自己“看懂”垃圾,自动完成分类呢?这就是我们今天要聊的智能垃圾分类系统。它不需要复杂的传感器阵列,也不用昂贵的工业相机,只需要一个普通的摄像头和一套聪明的算法,就能实时识别垃圾类型,指导投放或者自动分拣。

这个系统的核心,就是我们今天的主角——EagleEye DAMO-YOLO TinyNAS。听起来名字有点长,但你可以把它理解为一个“视力”极好、反应极快的“AI大脑”。它专门负责从摄像头画面中快速、准确地找出各种垃圾,并告诉你是哪一类。下面,我就带你看看,我们是如何用这个“大脑”,一步步搭建起一个实用的智能垃圾分类系统的。

1. 为什么选择EagleEye DAMO-YOLO TinyNAS?

在开始动手之前,我们得先搞清楚,为什么在众多目标检测模型里,偏偏选中了它。这就像盖房子选地基,选对了事半功倍。

首先,垃圾分类是个典型的“边缘计算”场景。什么意思呢?就是我们的“AI大脑”需要装在垃圾桶、分拣设备或者社区监控摄像头里,这些地方通常没有强大的电脑服务器,只有算力有限的嵌入式设备或普通工控机。所以,我们的模型必须足够“轻”,跑起来要快,不能卡顿。

EagleEye DAMO-YOLO TinyNAS在这方面表现突出。它名字里的“TinyNAS”就透露了关键信息——神经架构搜索。简单说,它不是人工设计好的固定网络结构,而是让AI自己在一个庞大的“结构库”里,根据我们设定的目标(比如:速度要快、精度要高、模型要小),自动搜索出最优的网络骨架。这就好比不是给你一件均码的衣服,而是根据你的身材数据,量身定制一套最合身的。因此,它天生就比很多通用模型更适合在资源受限的设备上运行。

其次,垃圾分类需要较高的识别精度。瓶子、纸张、电池、厨余垃圾,形态各异,有时还互相遮挡或者装在袋子里。DAMO-YOLO系列模型在精度和速度的平衡上做得很好,它采用了一些新技术,比如高效的RepGFPN特征金字塔AlignedOTA标签分配策略,让模型在保持轻快的同时,“看”得更准。我们实测下来,在自建的垃圾数据集上,它的平均识别精度能轻松超过85%,这对于实际应用来说已经非常可靠了。

最后,是部署的便利性。这个框架对部署非常友好,支持导出成 ONNXTensorRT 格式。ONNX就像一个通用的模型“翻译器”,能让模型在各种不同的硬件和推理引擎上运行;而TensorRT则是英伟达GPU上的“加速器”,能极大提升推理速度。这意味着我们可以先在性能好的电脑上训练和调试模型,然后轻松地把它“移植”到各种边缘设备上,无论是用CPU还是GPU。

所以,总结下来就是:轻快、精准、易部署。这三点正好切中了智能垃圾分类落地应用的命门。

2. 打造系统的“眼睛”:数据采集与处理

AI模型就像个孩子,教它认识世界,首先得给它看足够多、足够好的“图画”。对于垃圾分类系统,我们需要准备一个高质量的垃圾图片数据集。

2.1 数据从哪里来?

完全从零开始拍摄数万张垃圾图片不太现实。我们的数据来源主要有三个:

  1. 公开数据集:网络上可以找到一些开源的垃圾识别数据集,比如“TrashNet”或者国内一些竞赛数据集。它们是很好的起点,能提供一批基础样本。
  2. 网络爬取:在遵守版权和伦理的前提下,可以从电商平台(商品图)、生活分享社区等获取各类垃圾的干净背景图片。
  3. 实地拍摄:这是最关键的一步。我们需要拿着手机或相机,去小区垃圾桶、垃圾站等真实场景拍摄。要特别注意拍摄不同角度、不同光照(白天、夜晚)、不同状态(完整、破损、被挤压)的垃圾,以及它们堆叠、装在袋子里等复杂情况。这部分数据最能提升模型在真实环境下的表现。

我们最终定义的类别包括:可回收物厨余垃圾有害垃圾其他垃圾四大类。为了更精细,我们在可回收物下又细分了塑料瓶易拉罐纸张玻璃等子类。

2.2 给数据“做标记”

拍好的图片,需要告诉模型“哪里有什么东西”。这个过程叫标注。我们使用LabelImg、CVAT这类标注工具,在每张图片上把垃圾框出来,并打上正确的标签。

这里有个小技巧:对于被遮挡只露出一部分的垃圾,或者多个同类小物体(如一堆瓶盖),我们也会尽量框出。标注的质量直接决定模型学习的上限,一定要仔细。

2.3 让数据“更多样”

我们手头的数据量可能有限,而且场景比较单一。这时就需要“数据增强”——通过一些技术手段,人工创造更多的训练样本。这能有效防止模型“死记硬背”,提升它的泛化能力。

我们主要用了以下几种增强方法,并直接写在模型的配置里:

# 在DAMO-YOLO的配置文件(例如 damoyolo_tinynasL20_T.py)中,找到 data_aug 部分进行修改
train_dataset = dict(
    type='MosaicDataset',
    ...
    pipeline=[
        dict(type='LoadImageFromFile', to_float32=True),
        dict(type='LoadAnnotations', with_bbox=True),
        # 随机翻转,让模型认识左右对称的物体
        dict(type='RandomFlip', flip_ratio=0.5),
        # 随机调整亮度、对比度、饱和度,模拟不同光照
        dict(type='PhotoMetricDistortion',
             brightness_delta=32,
             contrast_range=(0.5, 1.5),
             saturation_range=(0.5, 1.5),
             hue_delta=18),
        # Mosaic增强:将四张图片拼成一张,增加小物体样本和复杂背景
        dict(type='Mosaic', img_scale=(640, 640), pad_val=114.0),
        # RandomAffine:随机旋转、缩放、平移,模拟不同视角
        dict(type='RandomAffine',
             max_rotate_degree=10.0,
             max_translate_ratio=0.1,
             scaling_ratio_range=(0.5, 1.5),
             border=(-320, -320)),
        dict(type='Resize', img_scale=(640, 640), keep_ratio=True),
        dict(type='Pad', pad_to_square=True, pad_val=(114, 114, 114)),
        dict(type='FilterAnnotations', min_gt_bbox_wh=(1, 1)),
        dict(type='DefaultFormatBundle'),
        dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels'])
    ]
)

经过采集、标注和增强,我们得到了一个包含上万张图片的数据集,并按8:1:1的比例划分为训练集、验证集和测试集。系统的“眼睛”算是初步准备好了。

3. 训练系统的“大脑”:模型训练与调优

有了数据,接下来就是训练模型,也就是教我们这个“AI大脑”认识各种垃圾。

3.1 环境搭建与模型准备

首先,我们需要一个适合的训练环境。推荐使用带有NVIDIA GPU的服务器或云平台。我们以在Linux系统下为例:

# 1. 克隆DAMO-YOLO仓库
git clone https://github.com/tinyvision/DAMO-YOLO.git
cd DAMO-YOLO

# 2. 创建并激活Python虚拟环境(推荐)
conda create -n damo-yolo python=3.8 -y
conda activate damo-yolo

# 3. 安装PyTorch(请根据你的CUDA版本选择)
# 例如,对于CUDA 11.3
pip install torch==1.12.1+cu113 torchvision==0.13.1+cu113 --extra-index-url https://download.pytorch.org/whl/cu113

# 4. 安装其他依赖
pip install -r requirements.txt

# 5. 将当前目录加入Python路径
export PYTHONPATH=`pwd`:$PYTHONPATH

然后,我们需要准备模型配置文件。DAMO-YOLO提供了多种尺寸的预训练模型(Tiny, Small, Medium等)。考虑到边缘设备的算力,我们选择DAMO-YOLO-T(Tiny)版本,它在速度和精度上取得了很好的平衡。我们基于其配置文件进行修改,主要是调整类别数。

# 复制一份 Tiny 模型的配置文件
cp configs/damoyolo_tinynasL20_T.py configs/damoyolo_trash_T.py

# 然后修改 configs/damoyolo_trash_T.py 中的关键参数
model = dict(
    type='DAMOYOLO',
    backbone=...,
    neck=...,
    head=dict(
        type='ZeroHead',
        num_classes=10,  # 修改为你的垃圾类别总数,例如我们分了10个子类
        ...
    )
)

# 修改数据集配置,指向我们自己的数据
data = dict(
    samples_per_gpu=16, # 根据你的GPU内存调整
    workers_per_gpu=4,
    train=dict(
        _delete_=True, # 覆盖继承的设置
        type='MosaicDataset',
        dataset=dict(
            type='CocoDataset',
            ann_file='data/trash/annotations/train.json', # 你的训练集标注文件路径
            img_prefix='data/trash/train/', # 你的训练集图片路径
            ...
        ),
        ...
    ),
    val=dict(
        ann_file='data/trash/annotations/val.json',
        img_prefix='data/trash/val/',
        ...
    ),
    test=dict(
        ann_file='data/trash/annotations/test.json',
        img_prefix='data/trash/test/',
        ...
    )
)

3.2 开始训练

配置好后,就可以开始训练了。我们使用预训练模型权重进行微调,这比从零开始训练快得多,效果也更好。

# 单GPU训练
python tools/train.py -f configs/damoyolo_trash_T.py -d 1 -b 16 --ckpt ./path/to/pretrained/damoyolo_tinynasL20_T.pth

# 多GPU分布式训练(例如4张卡)
python -m torch.distributed.launch --nproc_per_node=4 --master_port 29500 tools/train.py -f configs/damoyolo_trash_T.py -b 16 --ckpt ./path/to/pretrained/damoyolo_tinynasL20_T.pth

训练过程中,我们可以通过TensorBoard等工具监控损失下降和精度变化。通常训练几十个epoch后,模型在验证集上的精度就会趋于稳定。

3.3 模型评估与测试

训练完成后,我们需要看看这个“大脑”学得怎么样。

# 在测试集上评估模型性能
python tools/eval.py -f configs/damoyolo_trash_T.py --ckpt ./work_dirs/damoyolo_trash_T/epoch_300.pth

评估会输出平均精度(mAP)等指标。更重要的是,我们要进行可视化测试,看看模型在真实图片上的表现。

# 使用训练好的模型对单张图片进行推理
python tools/demo.py image \
  -f configs/damoyolo_trash_T.py \
  --engine ./work_dirs/damoyolo_trash_T/epoch_300.pth \
  --path ./test_image.jpg \
  --conf 0.5 \ # 置信度阈值,高于此值的检测框才显示
  --infer_size 640 640 \
  --device cuda \
  --output ./result.jpg

打开result.jpg,你就能看到模型框出的垃圾和对应的类别标签了。多测试一些复杂场景的图片,比如光线暗的、垃圾堆叠的,确保模型的鲁棒性。

4. 让系统“跑起来”:终端部署与应用

模型训练好了,精度也不错,接下来就要把它放到实际的终端设备里去运行。这是从实验走向应用的关键一步。

4.1 模型转换与优化

为了在终端设备上获得最快的运行速度,我们需要将PyTorch模型转换成更高效的格式。这里我们选择转换为ONNXTensorRT

# 1. 转换为ONNX格式(通用性好)
python tools/converter.py \
  -f configs/damoyolo_trash_T.py \
  -c ./work_dirs/damoyolo_trash_T/epoch_300.pth \
  --batch_size 1 \
  --img_size 640 640 \
  --opset 11

# 2. 转换为TensorRT引擎(NVIDIA GPU设备上速度最快)
# 首先确保已安装TensorRT
python tools/converter.py \
  -f configs/damoyolo_trash_T.py \
  -c ./work_dirs/damoyolo_trash_T/epoch_300.pth \
  --batch_size 1 \
  --img_size 640 640 \
  --trt \
  --end2end # 将后处理(NMS)也打包进引擎,进一步加速

转换后会生成 .onnx.trt 文件。TensorRT引擎在相同硬件上,推理速度通常比直接运行PyTorch模型快数倍。

4.2 终端应用开发

现在,我们可以在终端设备(如Jetson Nano、树莓派+AI加速棒、或者x86工控机)上编写简单的应用代码了。下面是一个使用ONNX Runtime在CPU上进行视频流推理的简化示例:

import cv2
import onnxruntime as ort
import numpy as np
import time

class TrashDetector:
    def __init__(self, onnx_path, class_names):
        # 初始化ONNX Runtime推理会话
        self.session = ort.InferenceSession(onnx_path)
        self.input_name = self.session.get_inputs()[0].name
        self.output_name = self.session.get_outputs()[0].name
        self.class_names = class_names
        self.conf_threshold = 0.5
        self.nms_threshold = 0.5

    def preprocess(self, image):
        """将输入图像预处理为模型需要的格式"""
        # 调整大小到640x640
        img = cv2.resize(image, (640, 640))
        # 转换颜色通道 BGR -> RGB
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        # 归一化并转换维度为 NCHW
        img = img.astype(np.float32) / 255.0
        img = np.transpose(img, (2, 0, 1))
        img = np.expand_dims(img, axis=0) # 增加批次维度
        return img

    def postprocess(self, outputs, original_shape):
        """解析模型输出,得到边界框和类别"""
        # outputs 是模型原始输出,这里需要根据DAMO-YOLO的输出格式进行解析
        # 假设输出是 [1, 8400, 10+5] 格式,其中10是类别数,5是(x, y, w, h, conf)
        predictions = outputs[0] # [8400, 15]
        boxes = []
        scores = []
        class_ids = []

        for pred in predictions:
            # 获取类别置信度
            class_scores = pred[5:15]
            class_id = np.argmax(class_scores)
            confidence = pred[4] * class_scores[class_id]

            if confidence > self.conf_threshold:
                # 解析边界框坐标 (cx, cy, w, h) -> (x1, y1, x2, y2)
                cx, cy, w, h = pred[:4]
                x1 = int((cx - w/2) * original_shape[1])
                y1 = int((cy - h/2) * original_shape[0])
                x2 = int((cx + w/2) * original_shape[1])
                y2 = int((cy + h/2) * original_shape[0])
                boxes.append([x1, y1, x2, y2])
                scores.append(float(confidence))
                class_ids.append(class_id)

        # 应用非极大值抑制(NMS)去除重叠框
        indices = cv2.dnn.NMSBoxes(boxes, scores, self.conf_threshold, self.nms_threshold)
        results = []
        if len(indices) > 0:
            for i in indices.flatten():
                results.append({
                    'box': boxes[i],
                    'score': scores[i],
                    'class_id': class_ids[i],
                    'class_name': self.class_names[class_ids[i]]
                })
        return results

    def detect(self, image):
        """主检测函数"""
        original_shape = image.shape[:2]
        input_tensor = self.preprocess(image)
        # 运行推理
        outputs = self.session.run([self.output_name], {self.input_name: input_tensor})
        # 后处理
        detections = self.postprocess(outputs, original_shape)
        return detections

# 使用示例
if __name__ == "__main__":
    # 类别名称,需与训练时一致
    CLASS_NAMES = ['plastic_bottle', 'can', 'paper', 'glass', 'food_waste', 'battery', 'other', ...]

    detector = TrashDetector('damoyolo_trash_T.onnx', CLASS_NAMES)

    # 打开摄像头
    cap = cv2.VideoCapture(0)
    print("开始智能垃圾分类检测... (按'q'退出)")

    while True:
        ret, frame = cap.read()
        if not ret:
            break

        start_time = time.time()
        detections = detector.detect(frame)
        inference_time = (time.time() - start_time) * 1000 # 毫秒

        # 在图像上绘制结果
        for det in detections:
            x1, y1, x2, y2 = det['box']
            label = f"{det['class_name']}: {det['score']:.2f}"
            # 根据类别画不同颜色的框
            if 'recyclable' in det['class_name']:
                color = (0, 255, 0) # 绿色-可回收
            elif 'food' in det['class_name']:
                color = (0, 165, 255) # 橙色-厨余
            elif 'hazardous' in det['class_name']:
                color = (0, 0, 255) # 红色-有害
            else:
                color = (128, 128, 128) # 灰色-其他

            cv2.rectangle(frame, (x1, y1), (x2, y2), color, 2)
            cv2.putText(frame, label, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)

        # 显示推理速度
        cv2.putText(frame, f"FPS: {1000/inference_time:.1f}", (10, 30),
                    cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 255), 2)

        cv2.imshow('Smart Trash Sorting', frame)

        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    cap.release()
    cv2.destroyAllWindows()

这段代码创建了一个简单的检测类,可以实时处理摄像头视频流,识别出垃圾并标注出来。在实际部署中,你可以将它集成到智能垃圾桶的控制器里,当检测到“塑料瓶”时,就控制机械臂将其拨入可回收物箱,或者通过语音/灯光提示用户正确投放。

4.3 部署形态与优化建议

根据不同的场景,这个系统可以有多种部署形态:

  • 社区智能垃圾桶:在垃圾桶投放口内部安装一个小型摄像头和边缘计算盒子(如Jetson Nano)。居民扔垃圾时,系统快速识别并亮起对应分类的指示灯,或通过语音提示。
  • 垃圾中转站分拣线:在传送带上方安装工业相机和工控机。系统识别传送带上的垃圾,控制高压气嘴或机械臂将其吹入或夹取到对应的收集箱中。
  • 移动巡检车:安装在环卫车上,自动识别街道上错误投放的垃圾,并生成报告。

在部署时,还有几个优化点可以考虑:

  • 模型量化:将模型从FP32精度转换为INT8精度,可以进一步减少模型大小和提升推理速度,对精度影响很小。
  • 使用TensorRT:在NVIDIA设备上,务必使用转换后的TensorRT引擎,能获得最佳性能。
  • 流水线处理:如果处理速度跟不上摄像头帧率,可以采用多线程,让图像采集、预处理、推理、后处理并行进行。

5. 总结

走完这一整套流程,从数据准备、模型训练到终端部署,一个基于EagleEye DAMO-YOLO TinyNAS的智能垃圾分类系统就初具雏形了。回过头看,这套方案的核心优势在于它的实用性可落地性

TinyNAS技术让模型天生就适合在资源紧张的边缘设备上运行,保证了系统的实时响应。DAMO-YOLO框架本身优秀的精度,又确保了识别的准确性。从我们的实践来看,在中等算力的边缘设备上,达到每秒20帧以上的处理速度并不难,这完全能满足实时提示或自动分拣的需求。

当然,实际部署中总会遇到新问题,比如新的垃圾品类、极端的光照条件、或者非常规的包装。这时,你可以把新遇到的数据收集起来,用我们前面讲的方法,对模型进行增量训练,让它持续学习,越用越聪明。

技术最终要服务于生活。这样一套系统,如果能帮助减少垃圾分类的错误率,提升回收效率,哪怕只是让清晨扔垃圾的阿姨不再犹豫,我觉得就是很有价值的尝试。如果你对环保科技感兴趣,或者正面临类似的视觉检测需求,不妨从这个小项目开始动手试试。从一行代码、一张图片开始,看着AI逐渐理解我们的世界,并帮我们把它变得更好,这个过程本身就充满了乐趣。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐