Faster RCNN算法项目 Python项目 面向打包垃圾的目标检测算法 基于城市场景的垃圾检测算法,首先收集城市垃圾样本集, 再利用 LabelImg工具对城市垃圾样本集进行垃圾标注,并对城市垃圾样本集中的图片进行归一化处理;而后将转化后的样本图片集输入至 Faster RCNN 算法中,建立目标分类模型,并利用 PASCAL VOC2007 数据集的图片对所建立的目标分类模型进行验证,直至统计目标分类准确率不低于 90%,最后对含有城市场景的视频进行图片解码,利用建立的 Faster- RCNN垃圾分类检测模型对解码后的图片进行分类检测,从而实现实时对城市垃圾管理进行监控。

蹲在电脑前啃着能量棒的时候,突然想到个有意思的事——城市里那些被随意丢弃的饮料瓶和塑料袋,要是能让摄像头自动发现它们该多酷。于是翻出吃灰的显卡,准备用Faster RCNN搞个能实时监控街边垃圾的玩意儿。

搞数据才是真功夫

从垃圾分类站搞来2000张街拍照片,打开LabelImg标注工具直接傻眼:这界面怎么跟我爷爷用的收音机一样复古?硬着头皮给每个塑料瓶画框,手抖画歪的框还得按W键撤回重来。这时候突然发现个偷懒技巧:

import os
for i, filename in enumerate(os.listdir('trash_dataset')):
    os.rename(f'trash_dataset/{filename}', f'trash_dataset/trash_{i:04d}.jpg')

这招让原本乱七八糟的"微信图片2023xxxx.jpg"瞬间变整齐队列。处理图片尺寸时发现有些照片路灯反光太强,顺手加了个归一化处理:

from torchvision import transforms
preprocess = transforms.Compose([
    transforms.Resize((800, 600)),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], 
                         std=[0.229, 0.224, 0.225])
])

这里用ImageNet的均值和标准差不是为了装专业,主要是显卡显存告急时能蹭预训练模型的优势。

模型训练就像熬汤

Faster RCNN算法项目 Python项目 面向打包垃圾的目标检测算法 基于城市场景的垃圾检测算法,首先收集城市垃圾样本集, 再利用 LabelImg工具对城市垃圾样本集进行垃圾标注,并对城市垃圾样本集中的图片进行归一化处理;而后将转化后的样本图片集输入至 Faster RCNN 算法中,建立目标分类模型,并利用 PASCAL VOC2007 数据集的图片对所建立的目标分类模型进行验证,直至统计目标分类准确率不低于 90%,最后对含有城市场景的视频进行图片解码,利用建立的 Faster- RCNN垃圾分类检测模型对解码后的图片进行分类检测,从而实现实时对城市垃圾管理进行监控。

在PyTorch里调出Faster RCNN时,发现原版代码的类别数设置简直反人类:

# 修改头文件时手滑的惨案现场
num_classes = 6 + 1  # 原来写死的21改成自己的5类垃圾+背景
roi_pooler = torchvision.ops.MultiScaleRoIAlign(...)

加载预训练权重时遇到shape不匹配,差点把咖啡洒在键盘上。突然想起某位大佬说过:"遇到参数不对就删最后几层",果断把box_predictor层的参数重置,模型居然真的跑起来了!

验证阶段拿PASCAL VOC2007做测试,准确率卡在89.7%死活上不去。这时候祭出炼丹师祖传秘方——把学习率调到1e-5,再加个早停机制:

# 来自玄学调参的神秘代码
scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(
    optimizer, mode='max', patience=3, factor=0.5)
if val_map > best_map:
    torch.save(model.state_dict(), 'trash_detector.pth')

三天后在第七次训练时,验证集准确率突然飙到91.2%,比看到外卖提前送达还激动。

让摄像头动起来

最后要把模型塞进视频流里,发现OpenCV读视频帧的速度比蜗牛还慢。灵机一动把每5帧处理1次,中间帧直接用线性插值大法:

# 量子波动速读版视频处理
cap = cv2.VideoCapture('street.mp4')
frame_queue = []
while cap.isOpened():
    ret, frame = cap.read()
    if len(frame_queue) == 5:
        process_batch(frame_queue)  # 丢给模型批量处理
        frame_queue.clear()
    frame_queue.append(preprocess(frame))

现在看着屏幕上实时跳出的垃圾标记框,突然觉得之前标注时手抽筋的苦没白吃。虽然偶尔会把路人的双肩包误判成垃圾袋,但至少证明这堆代码真的能跑起来——下次该试试把误检的包包训练成新类别?

Logo

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

更多推荐