什么是Mask R-CNN?Mask R-CNN的工作原理,maskrcnn 2024-03-26 05:04:29 0 0 描述 编者按:发展至今,计算机视觉已经产生了不少令人惊叹的应用,但一提到它,人们首先想到的总是人脸检测、物品识别……除去已经发展得很成熟的人脸识别技术,我们难道只能用检测室内物品来练习技巧吗?作为一个极具工程价值的领域,也许大家应当扩张技术应用的广度,把它和现实场景结合起来,真正做一些更接地气的尝试。 本文旨在构建一个自定义Mask R-CNN模型,它可以检测汽车车身的损坏区域(如下图所示)。这背后的应用理念是,购买二手车时,消费者首先会关注车身刮擦情况,有了这个模型,他们足不出户就能大致了解车子情况,避免被坑。而对于日常生活中的小事故,如果用户只需上传图片就能完成车辆破损鉴定,保险公司的索赔效率也会大幅提高。 什么是Mask R-CNN? Mask R-CNN是一个实例分割模型,它能确定图片中各个目标的位置和类别,给出像素级预测。所谓“实例分割”,指的是对场景内的每种兴趣对象进行分割,无论它们是否属于同一类别——比如模型可以从街景视频中识别车辆、人员等单个目标。下图是在COCO数据集上训练好的Mask R-CNN,如图所示,大到每一辆车,小到单根香蕉,它都能用窗口标出目标物品在画面中的像素位置。 不同于Faster R-CNN这样的经典对象检测模型,Mask R-CNN的一个特点是可以给窗口内表示对象轮廓的像素着色。可能有人会觉得这是个鸡肋功能,但它对自动驾驶汽车和机器人控制意义非凡: 着色可以帮助汽车明确道路上各目标的具体像素位置,从而避免发生碰撞; 如果机器人想抓取某个目标物品,它就需要知道位置信息(如亚马逊的无人机)。 如果只是单纯想在COCO上训练Mask R-CNN模型,最简单的方法是调用Tensorflow Object Detection API,具体内容Github都有,此处不再详谈。 Mask R-CNN的工作原理 在构建Mask R-CNN模型之前,我们首先来了解一下它的工作机制。 事实上,Mask R-CNN是Faster R-CNN和FCN的结合,前者负责物体检测(分类标签+窗口),后者负责确定目标轮廓。如下图所示: 它的概念很简单:对于每个目标对象,Faster R-CNN都有两个输出,一是分类标签,二是候选窗口;为了分割目标像素,我们可以在前两个输出的基础上增加第三个输出——指示对象在窗口中像素位置的二进制掩模(mask)。和前两个输出不同,这个新输出需要提取更精细的空间布局,为此,Mask R-CNN在Faster-RCNN上添加一个分支网络:Fully Convolution Networ(FCN)。 FCN是一种流行的语义分割算法,所谓语义分割,就是机器自动从图像中分割出对象区域,并识别其中的内容。该模型首先通过卷积和最大池化层把输入图像压缩到原始大小的1/32,然后在这个细粒度级别进行分类预测。最后,它再用上采样和deconvolution层把图还原成原始大小。 因此简而言之,我们可以说Mask R-CNN结合了两个网络——把Faster R-CNN和FCN纳入同一巨型架构。模型的损失函数计算的是分类、生成窗口、生成掩模的总损失。 此外,Mask R-CNN还做了一些基础改进,使其比FCN更精确,具体可以阅读论文。 构建用于检测汽车漆面情况的Mask R-CNN模型 GitHub:github.com/matterport/Mask_RCNN 这是一个在Python 3、Keras和TensorFlow上实现Mask R-CNN的现成资源。虽然最近TensorFlow目标检测库也更新了和Mask R-CNN相关的资源,但如果想一帆风顺地搭建模型,我们还是推荐这个,用TensorFlow太容易出bug了。 当然,这不是不鼓励大家去勇敢试错,毕竟熟悉了这些错误,我们才能更好地理解整个过程。但这个实现绝对值得收藏。 收集数据 考虑到本文只是演示,这里我们只Google了66张受损车辆图像(50张训练集,16张验证集)。如果想做个大点的数据集,建议把搜索关键词设为“damaged car painting”,用中文容易出现一大堆补漆广告,搜车祸则是大量引擎盖变形图。下面是一些图像样本 注释数据 为了构建Mask R-CNN模型,首先我们要对图像进行注释,标出其中的损坏区域。我们使用的注释工具是VGG Image Annotator — v 1.0.6,它有一个在线版本。除了常规图形,它也允许我们绘制多边形蒙版: 注释完后,记得把它们下载下来,保存为.json格式。这里是注释好的66幅图。 训练模型 完成上述步骤,现在我们就可以训练模型了。首先,把GitHub里的东西复制下来,然后加载我们的图像和注释。 classCustomDataset(utils.Dataset): def load_custom(self, dataset_dir, subset): """Load a subset of the Balloon dataset. dataset_dir: Root directory of the dataset. subset: Subset to load: train or val """ # 添加类别标签,我们只有一个 self.add_class("damage", 1, "damage") # 训练集和验证集 assert subset in ["train", "val"] dataset_dir = os.path.join(dataset_dir, subset) # 我们主要关心每个区域的x和y坐标 annotations1 = json.load(open(os.path.join(dataset_dir, "via_region_data.json"))) annotations = list(annotations1.values()) # don't need the dict keys # 即使没有任何注释工具也会把图像保存在JSON中 # 跳过未注释图像。 annotations = [a for a in annotations if a['regions']] # 添加图像 for a in annotations: # 获取构成每个对象实例轮廓多边形点的x,y坐标 # 它们在shape_attributes里((参见上面的json格式)) polygons = [r['shape_attributes'] for r in a['regions'].values()] # 输入图像大小后,load_mask()才能把多边形转成蒙版 image_path = os.path.join(dataset_dir, a['filename']) image = skimage.io.imread(image_path) height, width = image.shape[:2] self.add_image( "damage", ## 如果只有一类,只需在此处添加名称即可 image_id=a['filename'], # use file name as a unique image id path=image_path, width=width, height=height, polygons=polygons) 整段代码在这里。我们复制了资源里的balloon.py文件,并对它做了修改。需要注意的是,这些代码只适合包含一个类的问题。 此外,你也可以用这个笔记本内容可视化给定图像上的蒙版。 如果要训练,运行以下代码: ## 如果用的是在COCO上预训练的模型 python3 custom.py train --dataset=/path/to/datasetfolder --weights=coco ## 如果是继续训练您之前训练过的模型 python3 custom.py train --dataset=/path/to/datasetfolder --weights=last 注:用一个GPU训练10个epoch需要20-30分钟。 验证模型 至于模型的权重和偏差是不是正确的,大家可以参考这个笔记本 。里面列出了许多设置,可以作为辅助检查工具。 实验结果 如图所示,模型准确标出了漆面损坏位置。当然,这并不是全部,我们在这个示例里只用了66幅图,划痕也比较明显,所以这个模型的应用性非常有限。如果数据集够大,我们完全可以期待一个能检测微小伤痕的模型,当消费者在家里观察汽车3D图时,系统能自动标出一些不显眼的痕迹,避免乘兴而去,败兴而归。 除了检测车辆划痕,你认为Mask R-CNN模型还有什么潜在应用呢? 收藏(0)