如何用YOLOv8实现图像分割

1. 介绍

在之前的文章中,介绍了如何使用 YOLOv8 在不同的编程语言来检测图片中的对象。然而,YOLOv8 还可以把检测到的目标图像分割出来,本篇文章将介绍如何使用YOLOv8做图片分割。
对象检测的结果是所有检测到的对象的边界框。图像分割的结果是所有检测到的对象的蒙版。它是一个黑白图像,其中属于该对象的所有像素都是白色,所有其他像素都是黑色,如下图所示:
请添加图片描述
得到此蒙版(实际上是一个 2D 数组,其中背景像素值为 0,对象像素值为 255)后,可以将其应用于原始图像,仅绘制在蒙版上显示为白色的像素区域。
例如,可以通过这种方式从图像中删除背景:
请添加图片描述
并设置新背景:请添加图片描述
同样,可以对视频中的每个帧运行实例分割,并从整个视频中删除背景。
此外,有了检测到的对象的这些蒙版,可以计算它们的轮廓。
请添加图片描述
计算出的轮廓是一个多边形,它是点坐标的数组。该多边形可用于识别现实世界应用中图像上检测到的对象,比仅使用边界框要更精确。

在本文中,我将分享如何使用YOLOv8实现图像分割。分为3个部分:

  • 首先,我们将使用默认的 Ultralytics API,其中大部分内部工作都高度封装,在这一步我们将使用 YOLOv8 官方的预训练模型,该模型可从COCO 数据集中检测 80 个对象类。
  • 然后介绍如何训练自己的分割模型。
  • 最后,我们将替换掉Ultralytics的库,用更底层的方式来处理图像分割的输入和输出。

2. YOLOv8 图像分割入门

在接下来的部分中,所有代码示例和输出都在 Jupyter Notebook 中运行。
运行以下命令安装 Ultralytics 库:

!pip install ultralytics

导入YOLO包:

from ultralytics import YOLO

然后,加载YOLOv8官方的分割模型

model = YOLO("yolov8m-seg.pt")

下午中将使用以下图片作为示例,图片名为cat_dog.jpg:
请添加图片描述
运行模型并获取图像分割的结果:

results = model.predict("cat_dog.jpg")

分割模型的predict方法与目标检测模型的方法相同,它返回在每个图像的结果数组。可以这样获取结果:

result = results[0]

分割模型还进行对象检测,返回的结果与我们在本系列文章之前介绍的结果内容几乎相同。
同时,它还有一个属性,即检测到的对象掩码的数组,这些掩码被称为mask。

让我们看看检测到了多少个掩码:

masks = result.masks
len(masks)

结果显示为:

2

表示分割了 2 个对象:狗和猫。

现在看看第一个掩码:

mask1 = masks[0]

每个掩码都是一个具有一组属性的对象,我们将使用其中两个属性:

  • data物体的分割掩码,它是一个黑白图像矩阵,其中0个元素是黑色像素,1个元素是白色像素。
  • xy对象的轮廓多边形,它是点的数组。

该data属性是一个 PyTorch 的张量数组,但是利用 NumPy 数组处理它会更方便点。让我们提取掩码和轮廓多边形:

mask = mask1.data[0].numpy()
polygon = mask1.xy[0]

现在来看看这个mask到底是什么,我们使用Pillow Image 处理它。
安装Pillow:

!pip install pillow

从mask创建图像:

from PIL import Image

mask_img = Image.fromarray(mask,"I")
mask_img

显示以下图像:
请添加图片描述
这就是原始图片中狗的蒙版。
现在,让我们使用polygon对象,查看轮廓点数组:

polygon
array([[     280.18,      96.575],
       [      275.4,      101.36],
       [      275.4,      102.31],
       [     274.44,      103.27],
       [     274.44,      105.18],
       [     273.49,      106.14],
       [     273.49,      107.09],
       [     272.53,      108.05],
       [     272.53,      111.87],
       [     271.57,      112.83],
       [     271.57,      117.61],
       [     272.53,      118.57],
       [     272.53,      152.04]
...
       [     302.17,      112.83],
       [     302.17,      110.92],
       [     301.22,      109.96],
       [     301.22,      108.05],
       [     298.35,      105.18],
       [     298.35,      104.22],
       [     297.39,      103.27],
       [     297.39,      102.31],
       [     292.61,      97.531],
       [     291.66,      97.531],
       [      290.7,      96.575]], dtype=float32)

显示了每一个点的坐标[x,y]。该坐标可以直接参与其他需求的计算,比如,可以将其绘制在原始图像上:

from PIL import ImageDraw

img = Image.open("cat_dog.jpg")
draw = ImageDraw.Draw(img)
draw.polygon(polygon,outline=(0,255,0), width=5)

img

此代码加载原始图片,并在其上绘制轮廓polygon。参数outline指定轮廓线条颜色为绿色并设置宽度是5。最后,看到带有狗轮廓的图像:
请添加图片描述
现在,我们对第二个掩码执行相同的操作:

mask2 = masks[1]
mask = mask2.data[0].numpy()
polygon = mask2.xy[0]
mask_img = Image.fromarray(mask,"I")

mask_img

请添加图片描述

draw.polygon(polygon,outline=(0,255,0), width=5)
img

请添加图片描述

到目前为止,我们使用YOLOv8官方的分割模型,但在实践中,可能需要针对具体的问题分割特定的对象。例如,可能需要检测超市货架上的特定产品或通过 X 射线发现脑肿瘤。这些信息在官方的分割模型中并没有训练过。因此,我们需要训练自己的分割模型,创建我们自己的训练数据。

3. 创建自己的训练数据

要训练模型,您需要准备带标注的图片,并将其拆分为训练和验证数据集。训练集将用于训练模型,验证集将用于测试训练的结果,以衡量训练模型的质量。可以将 80% 的图片放入训练集,将 20% 放入验证集。

3.1 创建数据集的步骤

  1. 编码要分割的对象类别。例如,如果您只想检测猫和狗,则可以指定“0”是猫,“1”是狗。
  2. 为数据集创建一个文件夹,并在其中创建两个子文件夹:“images”和“labels”。
  3. 将图片放入“images”子文件夹中。图片越多,训练就越好。
  4. 对于每个图片,在“labels”子文件夹中创建一个标注文本文件。标注文本文件应具有与图片文件相同的名称,并使用“.txt”作为扩展名。在标注文件中,该添加每个对象的记录,格式如下:
{
   object_class_id} {
   polygon}

其中

  • object_class_id是对象类别的标签,例如,如果是猫,则为 0;如果是狗,则为 1。
  • polygon是该对象的边界多边形坐标,格式如下:x1 y1 x2 y2 …

实际上,这是机器学习过程中最耗时的手动工作:测量所有对象的边界多边形坐标并将其添加到标注文件中。
此外,坐标应归一化以适应从 0 到 1 的范围。使用以下方法:

x = x/图像宽度
y = y/图像高度

比如,如果有一个坐标为 (100,100) 的点,并且图像大小为 (612,415),其x和y分别是:

x = 100/612 = 0.163666121
y = 100/415 = 0.240963855

我们要为每个图片上的所有对象设置多边形。例如,如果您有一个具有以下猫和狗多边形的图像:
请添加图片描述
那么你需要为其创建以下标注文件:

1 0.45781 0.23271 0.45 0.24423 0.45 0.24654 0.44844 0.24884 0.44844 0.25345 0.44687 0.25575 0.44687 0.25806 0.44531 0.26036 0.44531 0.26958 0.44375 0.27188 0.44375 0.2834 0.44531 0.28571 0.44531 0.36636 0.44375 0.36866 0.44375 0.38018 0.44219 0.38248 0.44219 0.3894 0.44062 0.3917 0.44062 0.42857 0.43906 0.43087 0.43906 0.45622 0.44062 0.45852 0.44062 0.48157 0.43906 0.48387 0.43906 0.49309 0.4375 0.49539 0.4375 0.50461 0.43594 0.50691 0.43594 0.51843 0.43437 0.52074 0.43437 0.52765 0.43281 0.52995 0.43281 0.54148 0.43125 0.54378 0.43125 0.58295 0.43281 0.58526 0.43281 0.58986 0.43437 0.59217 0.43437 0.59447 0.4375 0.59908 0.4375 0.60139 0.44219 0.6083 0.44219 0.6106 0.44375 0.61291 0.44375 0.61521 0.44531 0.61752 0.44531 0.61982 0.45156 0.62904 0.45156 0.63134 0.46875 0.65669 0.47031 0.65669 0.47344 0.6613 0.47344 0.6636 0.475 0.6659 0.475 0.67512 0.47344 0.67742 0.47344 0.69816 0.475 0.70047 0.475 0.71199 0.47656 0.71429 0.47656 0.7166 0.48437 0.72812 0.4875 0.72812 0.48906 0.72581 0.49062 0.72581 0.49375 0.7212 0.49375 0.7166 0.49844 0.70968 0.49844 0.70738 0.50156 0.70277 0.50312 0.70277 0.50469 0.70047 0.50937 0.70047 0.51406 0.70738 0.51406 0.70968 0.51562 0.71199 0.51562 0.71429 0.51719 0.7166 0.51562 0.7189 0.51562 0.72351 0.51719 0.72581 0.51875 0.72581 0.52031 0.72812 0.52969 0.72812 0.53281 0.72351 0.54531 0.72351 0.54687 0.72581 0.55156 0. 72581 0.55625 0.73273 0.55781 0.73273 0.55937 0.73503 0.56094 0.73273 0.56875 0.73273 0.57031 0.73503 0.575 0.73503 0.57656 0.73273 0.57812 0.73503 0.58281 0.73503 0.58437 0.73733 0.59375 0.73733 0.59531 0.73964 0.6 0.73964 
  • 12
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

guohuang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值