目标检测之Mask R-CNN(Pytorch):小白动手实现项目

这篇博客是关于如何在Pytorch中实现Mask R-CNN,用于行人检测和分割。作者首先介绍了项目背景、环境配置和所需基础知识,接着详细讲解了Mask R-CNN的原理,包括R-CNN系列的发展。然后,博主逐步指导如何安装依赖、下载数据集、编写数据集类、定义模型,以及训练和测试模型。博客还包括训练和测试过程中遇到的问题以及解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

引言

  • 首先声明本项目的运行环境。操作系统为Windows,编写环境为Anaconda3 + Jupyter Notebook。Pytorch版本为 torch 1.7.1+cu110 、torchvision版本为 0.8.2+cu110,cuda版本为cu100,显卡为Nvidia 2060。
  • 我是目标检测领域的小白,刚刚完成了Pytorch的相关入门学习任务,所以我认为学习本篇博客的基础要求是:熟练的python技巧、初步接触Pytorch、了解基本tensor运算以及卷积网络的知识。
  • 本篇博客的代码部分并非全部原创,对领域小白来说自己搭建框架,寻找合适的模型和数据集都比较困难,因此我参照Pytorch官方文档来进行学习。我会尽力针对每一句代码书写自己的理解,写博客的目的是帮助自己整理思路同时也能给志同道合的初学者们一点点经验建议。
  • 本博客参照的Pytorch官方文档为:Mask R-CNN项目官方文档
  • 简单叙述一下本项目的主要内容:PennFudanPed是一个搜集行人步态信息的数据集,我们想要通过训练模型实现检测图像中的人物,不仅仅局限于边界框检测,我们想要针对每个检测人物生成掩码图片,进而分割图像。我们采用 Mask R-CNN模型来完成这一工作。
    项目含义示意图(真实掩码可能没有这么清晰准确)

Mask R-CNN原理简述

  • 目标检测领域的深度学习算法可以分为两类,一阶段算法代表为YOLO,二阶段算法代表为R-CNN。阐述一下二阶段算法和一阶段算法的区别,二阶段算法首先生成候选区域(提议区域),然后针对候选区域进行筛选和预测。一阶段算法并没有单独的步骤用来生成候选区域,而是将候选区域的生成、筛选与预测同步进行。
  • R-CNN 中文名字是区域提议卷积网络,其发展大体经历了R-CNN、Fast R-CNN、Faster R-CNN到Mask R-CNN的过程。每一种新模型都是在旧模型的基础上优化改善而得。总体来说优化的目的都是在于,提高模型的计算速度,以及优化模型的计算精读。
  • R-CNN大体经过了以下步骤:1.通过选择性搜索算法得到大量提议区域。2.针对每一个提议区域使用卷积网络提取特征,计算特征图。3.针对每一个特征图训练SVM实现类别预测。4.针对每一个特征图训练边框回归,实现边框坐标偏移量预测。
  • Fast R-CNN针对于R-CNN中存在的大量卷积计算进行了优化。Fast R-CNN首先针对全图进行卷积网络特征提取,然后同样使用选择性搜索算法生成大量提议区域,使用RoIPooling算法针对每一个提议区域从全图特征中挑选特征值,并调整维度。标签值与偏移量的预测与R-CNN相同。
  • Faster R-CNN针对提议区域的生成方式进行了修改。Faster R-CNN采用RPN网络的方式生成提议区域,接受全图特征图作为输入,筛选提议区域,极大减少了提议区域的生成数量。
  • Mask R-CNN为了实现像素级别的分类进行了优化。使用RoIAlign代替RoIPooling,将多尺寸提议区域进行特征对齐,原RoIPooling算法无法支持高精度的像素级别的图像分类。除了标签值和边界框偏移量的预测以外,单独开设一个分支通过全卷积网络实现像素级别分类。
    在这里插入图片描述

代码、注释及详细解释

1.安装COCOAPI(pycocotools)

  • Linux操作系统下COCOAPI的安装十分简单,具体方法百度即可。因此大部分的深度学习模型与平台也都部署在Linux系统下。
  • Windows操作系统的设计目的就是为了让更多的计算机非专业人士能够更简单直接地操作计算机,而针对于计算机从业人员来说,Linux系统有其独特地优势是我们绕不开地话题。
  • 言归正传COCOAPI在Windows系统下安装需要进行一些特殊操作。具体内容请见CSDN博客在 Windows 下安装 COCO API(pycocotools)

2.下载PennFudan数据集

3.初步查看数据集图片

  • 注意第一点的是,本博客中所有路径都需要更改成自己的路径。具体方法只需要建立对应文件夹,存放好数据集和图片即可。本文均采用绝对路径,有关绝对路径与相对路径的区别请自行学习。
  • Image.open()读取的图片有多种模式,每种模式有不同的作用并且拥有相对应可调用的函数,这里也不做赘述,感兴趣的可以自行查阅。下面代码中读取的mask默认为“L”模式,需要转换为“P”模式才可以调用调色板函数putpalette()。
  • 我们对掩码图片进行一下了解。普通图片的矩阵元素是一个RGB数值,当然有三个通道。而掩码图片的矩阵元素是0,1,2,3…的类别序号。掩码矩阵可以理解为像素级别的分类结果,如果掩码图片上实体只有一个那么就是二色掩码图,矩阵元素只有0(背景)、1(实体);下图所示的掩码图片实体不唯一,那么就是多色掩码图。掩码图片可能有三个通道也可能只有一个通道,具体情况请.shape分析一下。
from PIL import Image

# 读取待训练图片00001
Image.open(r'C:\Users\HP\Anaconda3\envs\pytorch\data\PennFudanPed\PNGImages\FudanPed00001.png')

# 读取对应图片的掩码图片
mask = Image.open(r'C:\Users\HP\Anaconda3\envs\pytorch\data\PennFudanPed\PedMasks\FudanPed00001_mask.png')

# 读取的mask默认为“L”模式,需要转换为“P”模式调用调色板函数
mask = mask.convert("P")

# 针对“P”类图片调用调色板函数
# 看来掩码图片存的不是RGB数值,而是类别index
mask.putpalette([
    0, 0, 0, # 0号像素为黑色
    255, 0, 0, # 1号像素为红色
    255, 255, 0, # 2号像素为黄色
    255, 153, 0, # 3号像素为黄色
])

mask

在这里插入图片描述

4.编写针对PennFudan的数据集类

  • 我们知道深度学习的训练函数,一般是接受DataLoader的实例作为输入,而DataLoader则需要接受自定义的数据集类实例作为输入。因此本章节就用来完成数据集接口的编写。
  • PennFudanDataset类一共有三个函数,四个属性。首先介绍四个属性,self.root是根路径,后面跟上训练集或测试集的文件夹便可以得到最终路径,无论是训练集还是测试集,都需要变形参数self.transforms,也都有普通图片self.img和掩码图片self.masks。
  • 三个函数中重点在于__getitem__()函数。该函数的功能是根据图片编号,获得对应的图片信息。该函数需要返回两个变量:
    在这里插入图片描述
import os
import torch
import numpy as np
import torch.utils.data
from PIL import Image
 
 
class PennFudanDataset(torch.utils.data.Dataset):
    def __init__(self, root, transforms=None):
        self.root = root # 数据集的根路径
        self.transforms = transforms # 数据集的预处理变形参数
        
        # 路径组合后返回该路径下的排序过的文件名(排序是为了对齐)
        self.imgs = list(sorted(os.listdir(os.path.join(root, "PNGImages")))) # self.imgs 是一个全部待训练图片文件名的有序列表
        self.masks = list(sorted(os.listdir(os.path.join(root, "PedMasks")))) # self.masks 是一个全部掩码图片文件名的有序列表
 
    # 根据idx对应读取待训练图片以及掩码图片
    def __getitem__(self, idx):
        # 根据idx针对img与mask组合路径
        img_path = os.path.join(self.root, "PNGImages", self.imgs[idx])
        mask_path = os.path.join(self.root, "PedMasks", self.masks[idx])
        
        # 根据路径读取三色图片并转为RGB格式
        img = Image.open(img_path).convert("RGB")
        
        # 根据路径读取掩码图片默认“L”格式
        mask = Image.open(mask_path)
        # 将mask转为numpy格式,h*w的矩阵,每个元素是一个颜色id
        mask = np.array(mask)
        
        # 获取mask中的id组成列表,obj_ids=[0,1,2]
        obj_ids = np.unique(mask)
        # 列表中第一个元素代表背景,不属于我们的目标检测范围,obj_ids=[1,2]
        obj_ids = obj_ids[1:]
 
        # obj_ids[:,None,None]:[[[1]],[[2]]],masks(2,536,559)
        # 为每一种类别序号都生成一个布尔矩阵,标注每个元素是否属于该颜色
        masks = mask == obj_ids[:, None, None]
 
        # 为每个目标计算边界框,存入boxes
        num_objs = len(obj_ids) # 目标个数N
        boxes = [] # 边界框四个坐标的列表,维度(N,4)
        for i in range(num_objs):
            pos = np.where(masks[i]) # pos为mask[i]值为True的地方,也就是属于该颜色类别的id组成的列表
            xmin = np
### 如何实现 Mask R-CNN 模型 #### 使用 Detectron 库进行快速复现 为了方便研究人员和开发者,Facebook AI Research 提供了一个名为Detectron的开源库,该库包含了Mask R-CNN以及其他多种计算机视觉模型的实现[^3]。 安装依赖项并克隆仓库: ```bash git clone https://github.com/facebookresearch/Detectron.git cd detectron pip install -r requirements.txt python setup.py build develop ``` 配置环境变量以便于调用CUDA和其他必要的工具包。接着可以根据官方文档准备数据集,通常是以COCO格式存储的对象检测与实例分割标注文件。 #### 利用 PyTorch 实现 Mask R-CNN 对于希望通过PyTorch框架自行构建Mask R-CNN的情况,下面给出了一种简化版的方式来进行模型搭建: 导入所需模块: ```python import torch from torchvision import models, transforms from PIL import Image import numpy as np ``` 加载预训练权重并初始化网络结构: ```python model = models.detection.maskrcnn_resnet50_fpn(pretrained=True) model.eval() ``` 设置输入图片转换规则: ```python transform = transforms.Compose([ transforms.ToTensor(), ]) ``` 读取测试图像并执行前向传播获取预测结果: ```python image_path = "path_to_your_image.jpg" input_image = Image.open(image_path).convert('RGB') tensor_input = transform(input_image)[None,...] with torch.no_grad(): prediction = model(tensor_input) boxes = prediction[0]['boxes'].cpu().numpy() # 边界框坐标 labels = prediction[0]['labels'].cpu().numpy() # 类别标签 scores = prediction[0]['scores'].cpu().numpy() # 置信度分数 masks = prediction[0]['masks'].mul(255).byte().cpu().numpy() # 掩码矩阵 ``` 上述代码片段展示了如何利用torchvision中的`models.detection.maskrcnn_resnet50_fpn()`函数轻松创建一个带有ResNet-50骨干网和支持FPN特征金字塔网络的Mask R-CNN实例,并对其进行基本操作以完成一次简单的推断过程[^4]。
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值