1. 磐创AI首页
  2. Medium

使用5行代码的实时图像分割

计算机视觉应用中的图像分割

计算机视觉是计算机看到并分析它们所看到的东西的能力。图像分割是计算机视觉的一个方面,它处理将计算机可视化的对象的内容分割成不同的类别,以便更好地分析。图像分割过程的一个很好的例子是图像中对象的前景-背景分离,这是一种将对象与其背景分离的技术,用于分析对象及其背景。图像分割能够实现前景和背景的分离,在解决医学图像分析、背景编辑、自动驾驶汽车视觉和卫星图像分析等计算机视觉问题方面具有不可估量的价值。

PixelLib库是一个库,它允许使用几行python代码轻松集成图像和视频中的对象分割。它支持许多令人惊叹的功能,例如:

对实时图像分割应用的需求

Pytorch后端PixelLib:计算机视觉中最大的挑战之一是保持实时应用的准确性和速度性能之间的空间。在计算机视觉领域,存在这样的两难境地:计算机视觉解决方案要么更准确、更慢,要么更不准确、更快。上一版本的PixelLib使用TensorFlow深度学习库作为后端,使用Mask R-CNN进行实例分割。MASK R-CNN是一个很好的架构,但未能在实时应用的准确性和速度性能之间取得平衡。我非常兴奋地宣布,PixelLib现在提供了对pytorch后端的支持,可以使用😊分割架构更快、更准确地分割和提取图像和视频中的对象。用Alexander Kirillov等人的PointRend对象分割结构代替Mask R-CNN进行对象的实例分割。PointRend是实现对象分割的优秀神经网络。它生成准确的分割掩码,并以较高的推理速度运行,满足了日益增长的对精确和实时计算机视觉应用的需求。Alexander Kirillov et al

多操作系统支持

注意:本文基于使用pytorch和PointRend执行实例分割。如果您想了解如何使用TensorFlow和Mask R-CNN执行实例分割,请阅读下面的文章;

下载Python

PixelLib pytorch版本支持python 3.7及以上版本。下载兼容的python版本。

安装PixelLib及其依赖项

安装Pytorch

PixelLib Pytorch版本支持这些版本的pytorch(1.6.0、1.7.1、1.8.0和1.9.0)。

注意:Pytorch 1.7.0不受支持,请不要使用低于1.6.0的任何pytorch版本。安装兼容的Pytorch版本。

安装Pycotools

  • PIP3安装pycotools

安装PixelLib

  • PIP3安装像素库

如果已安装,请使用以下命令升级到最新版本:

  • PIP3安装Pixellibâuro“升级

图像分割

PixelLib使用5行python代码,使用PointRend模型对图像和视频进行对象分割。下载PointRend模型。这是图像分割的代码。PointRend model

line 1âuro“4:PixelLib包已导入,我们还从模块Pixellib.torchbackend.instance(从pytorch support导入实例分段类)导入了instanceSegaging类。我们创建了类的一个实例,并最终加载了我们下载的PointRend模型。

第5行:我们调用了函数SegmentImage来对图像中的对象进行分割,并向该函数添加了以下参数:

  • IMAGE_PATH:这是要分割的图像的路径。
  • show_bbox:这是一个可选参数,用于显示带有边界框的分割结果。
  • OUTPUT_IMAGE_NAME:这是保存的分割图像的名称。

用于分割的样本图像

ins.segmentImage("image.jpg",output_image_name="output.jpg")

分割后的图像

The checkpoint state_dict contains keys that are not used by the model: proposal_generator.anchor_generator.cell_anchors.{0, 1, 2, 3, 4}

获取细分结果

results, output = ins.segmentImage("image.jpg", show_bboxes=True, output_image_name="result.jpg")
print(results)

分割结果返回具有与图像中分割的对象相关联的许多值的字典。打印的结果将采用以下格式:

{'boxes':  array([[ 579,  462, 1105,  704],
[ 1, 486, 321, 734],
[ 321, 371, 423, 742],
[ 436, 369, 565, 788],
[ 191, 397, 270, 532],
[1138, 357, 1197, 482],
[ 877, 382, 969, 477],),

上面打印的结果中的值包括:

{'boxes': array([[5.790e+02, 4.620e+02, 1.105e+03, 7.050e+02],[1.000e+00, 4.870e+02, 3.220e+02, 7.340e+02],[1.142e+03, 3.640e+02, 1.161e+03, 4.060e+02]], dtype=float32),

长方体:这些是分割的对象的边界框坐标。我没有显示所有的框-欧元™坐标,这是因为列表太长了。

'class_ids': array([ 2,  2,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  2, 24, 24,2,  2,2,  0,  0,  0,  0,  0,  0], dtype=int64),

CLASS_ID:这些是分段的对象的类ID。

'class_names': ['car', 'car', 'person', 'person', 'person', 'person', 'person', 'car', 'person', 'person', 'person', 'person', 'car', 'backpack', 'backpack', 'car', 'car', 'car', 'person', 'person', 'person', 'person', 'person', 'person'],

CLASS_NAMES:这些是分段的对象的类名。

'object_counts': Counter({'person': 15, 'car': 7, 'backpack': 2}),

OBJECT_COUNTS:这些是图像中分割的每个类的计数。我使用Python内置计数器来清点对象。在本例中,图像中分割了15个人、7辆汽车和2个背包。

'scores': array([100., 100., 100., 100.,  99.,  99.,  98.,  98.,  97.,  96.,  95.,95.,  95.,  95.,  94.,  94.,  93.,  91.,  90.,  88.,  82.,  72.,69.,  66.], dtype=float32),

分数:这些是每个分割对象的置信度分数。

'masks': array([[[False, False, False, ..., False, False, False],

遮罩:这些是分段的每个对象的遮罩值。我没有显示所有的掩码值,这是因为列表太长了。

注意:返回的掩码的默认值为Bolean。可以使用新参数MASK_POINTS_VALUES获取掩码-欧元™坐标。

ins.segmentImage("sample.jpg", show_bboxes=True, mask_points_values=True,  output_image_name="output.jpg")

将MASK_POINTS_VALUES参数添加到SegmentImage函数并设置为True,新的掩码值将为:

[[array([[295, 497]])
array([[422, 114],
[421, 115],
[417, 115],
...,
[436, 115],
[433, 115],
[432, 114]])]]

EXTECTED_OBJECTS:如果我们提取对象,这是提取的对象值的容器值。它是空的,因为我们没有提取任何东西。我们将在本文后面讨论如何提取这些分割对象。

results, output = ins.segmentImage("image.jpg", show_bboxes=True, output_image_name="result.jpg")

访问由分段结果呈现的值

边界框坐标值

results["boxes"]

类IDs值

results["class_ids"]

类名称值

results["class_names"]

对象计数值

results["object_counts"]

掩码值

results["masks"]

检测阈值

PixelLib使得确定对象分割的检测阈值成为可能。

ins.load_model("pointrend_resnet50.pkl", confidence = 0.3)

置信度:这是LOAD_MODEL函数中引入的一个新参数,它被设置为0.3以将检测阈值设置为30%。我为检测阈值设置的默认值是0.5,可以使用置信度参数增加或减少该值。

速度纪录

PixelLib使实时对象分割成为可能,并增加了调整推理速度以适应实时预测的能力。使用4 GB容量的NVIDIA GPU处理单张图像的默认推理速度约为0.26秒。

速度调整:

PixelLib支持速度调整,有快速和快速两种速度调整模式;

1个快速模式

ins.load_model("pointrend_resnet50.pkl", detection_speed = "fast")

在LOAD_MODEL函数中,我们添加了参数DETACTION_SPEED,并将该值设置为FAST。快速模式处理单个图像达到0.20秒。

用于快速模式检测的完整代码

2个快速模式

ins.load_model("pointrend_resnet50.pkl", detection_speed = "fast")

在LOAD_MODEL函数中,我们添加了参数DETACTION_SPEED,并将该值设置为RAPID。快速模式处理单个图像达到0.15秒。

用于快速模式检测的完整代码

点渲染模型

有两种类型的PointRend模型用于对象分割,它们是resnet50变体和resnet101变体。整篇文章都使用resnet50变体,因为它速度更快,准确性也更好。resnet101变体更准确,但它比resnet50变体慢。根据Detectron2上模型的官方报告,resnet50变体在COCO上获得了38.3个地图,resnet101变体在COCO上获得了40.1个MAP。official reports

Resnet101的速度记录:分段的默认速度为0.5秒,快速模式为0.3秒,而快速模式为0.25秒。

Resnet101变体的代码

ins.load_model("pointrend_resnet101.pkl", network_backbone = "resnet101")

使用resnet101模型执行推理的代码是相同的,只是我们在load_model函数中加载了PointRend resnet101模型。从此处下载resnet101型号。我们还添加了一个额外的参数NETWORK_BRONSPONE,并将该值设置为resnet101。here

注意:如果您想要获得高推理速度和良好的准确性,请使用PointRend resnet50变量,但如果您更关心准确性,请使用PointRend resnet101变量。所有这些推断报告都基于使用4 GB容量的NVIDIA GPU。

图像分割中的自定义目标检测

使用的PointRend模型是支持80类对象的预先训练的COCO模型。Pixellib支持自定义对象检测,支持过滤检测,保证了目标对象的分割。我们可以从支持的80类对象中进行选择,以匹配我们的目标。以下是支持的80类对象:

person, bicycle, car, motorcycle, airplane,

我们想过滤我们的样本图像的检测,以检测图像中的唯一人。

target_classes = ins.select_target_classes(person = True)

调用函数SELECT_TARGET_CLASSES来选择要分割的目标对象。函数SegmentImage获得了一个新的参数SECTION_TARGET_CLASSES来从目标类中进行选择,并基于这些参数过滤进行检测。

太棒了!PixelLib仅检测图像中存在的人。

用于自定义对象检测的完整代码

图像中的对象提取

PixelLib使提取和分析图像中分割的对象成为可能。

用于对象提取的代码

图像分割的代码是相同的,只是我们在SegmentImage函数中添加了额外的参数来执行对象提取。

ins.segmentImage("image.jpg", extract_segmented_objects = True, save_extracted_objects = True, output_image_name="output.jpg")

  • EXTRACT_SECADED_OBJECTS:这是处理分段对象提取的参数。使用以下命令访问提取的对象值:

results, output = ins.segmentImage("image.jpg", show_bboxes=True, output_image_name="result.jpg")

  • SAVE_EXTECTED_OBJECTS:这是将每个提取的对象保存为图像的参数。每个分段的对象将保存为SECADERED_OBJECT_INDEX,例如SECATENDED_OBJECT_1。对象将根据其提取顺序进行保存。

segmented_object_1.jpg
segmented_object_2.jpg
segmented_object_3.jpg
segmented_object_4.jpg
segmented_object_5.jpg
segmented_object_6.jpg

注意:图像中的所有对象都已提取,我选择仅显示其中的两个对象。

从包围盒坐标中提取

默认提取方法从掩码-欧元™坐标提取对象。提取只给我们关于对象本身的信息,而不包括其邻近的环境。考虑一个问题,其中我们想要分析对象及其在图像中所处的区域。PixelLib能够通过使用其边界框(欧元™坐标)提取分割的对象及其在图像中的远程位置来解决这个问题。

用于提取的修改代码

ins.segmentImage("image.jpg", extract_segmented_objects = True, extract_from_box = True, save_extracted_objects = True, output_image_name="output.jpg")

我们引入了一个新的参数Extract_from_box来提取从包围盒坐标分割的对象。每个提取的对象都将保存为Object_Extract_index,例如OBJECT_EXTRACT_1。对象将根据它们的提取顺序保存。

object_extract1.jpg
object_extract2.jpg
object_extract3.jpg
object_extract4.jpg
object_extract5.jpg
object_extract6.jpg

使用边界框坐标提取对象的完整代码

图像分割输出可视化。

PixelLib使根据图像的分辨率调节图像的可视化成为可能。

ins.segmentImage("sample.jpg", show_bboxes=True, output_image_name= "output.jpg")


可视化效果是不可见的,因为文本大小和方框厚度都太薄了。我们可以调整文本大小、粗细和方框粗细来调整可视化效果。

为更好地可视化而进行的修改

ins.segmentImage(“sample.jpg�, show_bboxes=True, text_size=5, text_thickness=3, box_thickness=8, output_image_name=�output.jpg�)

SegmentImage函数接受调整文本和边界框厚度的新参数。

  • TEXT_SIZE:默认文字大小为0.6,中等分辨率的图片也可以。对于高分辨率的图像来说,它会太小。
  • Text_Thickness:默认文本厚度为1,我将其增加到4以匹配图像分辨率。
  • box_thickness:默认的长方体厚度为2,我将其更改为10以匹配图像分辨率。

以更好的可视化效果输出图像

注:请根据您的图像分辨率调整参数。如果您的图像分辨率较低,我为分辨率为5760×3840的示例图像使用的值可能太大。如果您的图像分辨率非常高,您可以将参数值增加到我在此示例代码中设置的值之外。TEXT_™和BOX_THICTH参数-TEXT TEXTH的值必须是整数,并且不能用浮点数表示它们的值。text_size值可以用整数和浮点数表示。

批量图像分割

PixelLib可以对同一文件夹中的一批图像执行预测。

批量分割代码

ins.segmentBatch("inputfolder",  show_bboxes=True, output_folder_name = "outputfolder")

批处理分割的代码与单图像分割非常相似,只是我们将SegmentImage函数替换为SegmentBatch函数。我们在SegmentBatch中添加了以下参数:

  • Folder_PATH:这是包含我们要分割的图像的文件夹。
  • OUTPUT_Folder_NAME:这是我们将保存所有分割图像的文件夹的名称。

文件夹结构示例

--input_folder
--test1.jpg
--test2.jpg
--test3.jpg

--output_folder
--test1.jpg
--test2.jpg
--test3.jpg

批量图像分割中的目标提取代码

ins.segmentBatch("inputfolder", show_bboxes=True, extract_segmented_objects=True, save_extracted_objects=True, output_folder_name="outputfolder")

在SegmentBatch函数中,我们添加了EXTRACT_SECADED_OBJECTS来提取分段的对象,并添加了SAVE_EXTECTED_Objects来保存提取的对象。输入文件夹中每个图像的提取对象将保存在名称为imageName_Extracts的单独文件夹中,例如,如果图像名称为test1.jpg,这意味着提取的对象将保存在名为test1_Extracts的文件夹中。

注意:提取对象的文件夹是在图像的同一输入文件夹中创建的。文件夹结构示例

--input_folder
--test1.jpg
--test1_extracts

从包围盒坐标中提取物体的代码

ins.segmentBatch("inputfolder", show_bboxes=True, extract_segmented_objects=True, extract_from_box=True,save_extracted_objects=True, output_folder_name="outputfolder")

在SegmentBatch函数中,我们添加了EXTRACT_FROM_BOX来从边界框中提取对象-™坐标和SAVE_EXTECTED_OBJECTS来保存提取的对象。

注意:从边界框(欧元™坐标)提取的对象的文件夹也是在图像的同一输入文件夹中创建的。文件夹结构示例

--input_folder
--test1.jpg
--test1_extracts

批量图像分割中的自定义对象分割代码

target_classes = ins.select_target_classes(person = True)
ins.segmentBatch("inputfolder", show_bboxes=True, segment_target_classes = target_classes, output_folder_name="outputfolder")

我们调用函数SELECT_TARGET_CLASSES来选择要分割的目标对象。函数SegmentBatch获得了一个新参数SEGMENT_TARGET_CLASS以从目标类中进行选择,并基于这些参数过滤检测。

批量图像分割中的快速模式检测代码

ins.load_model(“pointrend_resnet50.pkl�, detection_speed = "fast")

在LOAD_MODEL函数中,我们添加了参数DETACTION_SPEED,并将该值设置为FAST。快速模式处理单个图像达到0.20秒。

批量图像分割中的快速模式检测代码

ins.load_model(“pointrend_resnet50.pkl�, detection_speed = "rapid")

我们将推理的检测速度设置为快速模式。

在LOAD_MODEL函数中,我们添加了参数DETACTION_SPEED,并将该值设置为RAPID。快速模式处理单个图像达到0.15秒。

注:PixelLib支持的所有功能的批量图像分割代码实现与单幅图像分割相同,只不过SegmentImage函数被替换为SegmentBatch。

视频和摄像机源中的对象分割

PixelLib使得在实时摄像机视频源和视频文件中执行实时对象分割成为可能。

视频分割

用于视频分割的代码

line 1âuro“4:PixelLib包已导入,我们还从模块Pixellib.torchbackend.instance(从pytorch support导入实例分段类)导入了instanceSegaging类。我们创建了类的一个实例,并最终加载了PointRend模型。如果模型尚未下载,请从此处下载。here

第5行:我们调用函数process_video对视频中的对象进行分割,函数中增加了如下参数:

  • VIDEO_PATH:这是要分割的视频的路径。
  • show_bbox:这是一个可选参数,用于在结果中显示带有边界框的分割对象。
  • FRAMES_PER_Second:这是设置保存的视频的每秒帧数的参数。
  • OUTPUT_VIDEO_NAME:输出分段视频的名称。

ins.process_video("sample_video.mp4", show_bboxes=True, frames_per_second=3, output_video_name="output_video.mp4")

用于视频中的对象提取的代码

ins.process_video(“sample_video.mp4�, show_bboxes=True,  extract_segmented_objectsframes_per_second=5, output_video_name=�output_video.mp4")

process_video函数有新的参数EXTRACT_SECATED_OBJECTS和SAVE_EXTECTED_OBJECTS,分别用于提取和保存分段对象。

视频中边界框坐标的提取

用于提取的修改代码

ins.process_video(“sample.mp4�, show_bboxes=True, extract_segmented_objects=True, extract_from_box=True,save_extracted_objects=True, frames_per_second=5, output_video_name=�output_video.mp4")

  • 函数中添加了EXTRACT_FROM_BOX以提取从其边界框坐标分割的对象。

视频中的自定义对象分割

PixelLib可以自定义视频中的对象分割,以过滤未使用的检测和分割目标类。

视频中的自定义检测代码

target_classes = ins.select_target_classes(person = True, bicycle =True)

调用函数SELECT_TARGET_CLASSES来选择要分割的目标对象。函数PROCESS_VIDEO获得了一个新参数SECTION_TARGET_CLASS以从目标类中选择,并基于它们过滤检测。

视频分割中的快速模式检测编码

ins.load_model(“pointrend_resnet50.pkl�, detection_speed = "fast")

我们将视频处理的检测速度设置为快速模式。

视频分割中的快速模式检测代码

ins.load_model(“pointrend_resnet50.pkl�, detection_speed = "rapid")

我们将视频处理的检测速度设置为快速模式。

实时摄像机视频源中的对象分割

PixelLib为实时摄像机视频源的实时分割提供了出色的支持。

实时摄像机视频源的分割代码

import cv2 capture = cv2.VideoCapture(0)

我们导入了cv2并包含了捕获Cameraâuro™帧的代码。

segment_video.process_camera(capture,  show_bboxes = True, frames_per_second= 5, check_fps=True, show_frames= True,frame_name= "frame", output_video_name="output_video.mp4")

在执行分割的代码中,我们替换了要捕获的视频™的文件路径,也就是说,我们正在处理摄像机捕获的帧流。我们添加了额外的参数,以显示摄像机-Euro™的帧:

  • SHOW_FRAMES:这是处理分割的Camera-uro™帧的显示的参数。
  • FRAME_NAME:这是为所显示的摄像机™的帧指定的名称。
  • check_fps:这是在摄像机视频源处理结束时每秒打印帧数的参数。
  • show_bbox:这是一个可选参数,用于显示带有边界框的分段对象。
  • FRAMES_PER_Second:这是为保存的视频文件设置每秒帧数的参数。在这种情况下,它被设置为5,即保存的视频文件将具有每秒5帧。
  • OUTPUT_VIDEO_NAME:这是保存的分段视频的名称。

实时摄像机视频源处理的速度调整

默认速度模式为4fps。快速模式达到6fps,快速模式达到9fps。这些报告基于使用4 GB容量的NVIDIA GPU

摄像机视频源中的快速模式检测代码

ins.load_model(“pointrend_resnet50.pkl�, detection_speed = "fast")

我们将处理实时摄像机视频的检测速度设置为快速模式,推理速度将为6fps。

用于快速模式检测的代码

ins.load_model(“pointrend_resnet50.pkl�, detection_speed = "rapid")

我们将处理实时摄像机视频的检测速度设置为快速模式,推理速度将为9fps。

实时摄像机视频源中的自定义对象分割代码

target_classes = segment_video.select_target_classes(person=True)

调用函数SELECT_TARGET_CLASSES来选择要分割的目标对象。函数PROCESS_CAMERA获得了一个新参数SECTION_TARGET_CLASS以从目标类中进行选择,并基于这些参数过滤检测。

实时摄像机视频源中的对象提取代码

segment_video.process_camera(capture,  show_bboxes = True, frames_per_second= 5, extract_segmented_objects=True, save_extracted_objects=True,show_frames= True,frame_name= "frame", output_video_name="output_video.mp4")

process_Camera函数具有新的参数Extract_Segated_Objects和save_Extracted_Objects,分别用于提取和保存分割的对象。

  • 函数中添加了EXTRACT_FROM_BOX以提取从其边界框坐标分割的对象。

用于从实时摄像机视频源中的长方体坐标提取对象的代码

segment_video.process_camera(capture,  show_bboxes = True, frames_per_second= 5, extract_segmented_objects=True, extract_from_box=True,save_extracted_objects=True, show_frames= True,frame_name= "frame", output_video_name="output_video.mp4")

  • 函数中添加了EXTRACT_FROM_BOX以提取从其边界框坐标分割的对象。

我们在本文中详细讨论了如何使用PixelLib Pytorch版本准确、快速地分割和提取图像和实时摄像机视频源中的对象。我们还描述了使用PointRend网络体系结构添加到PixelLib的升级,它使库能够满足不断增长的需求,以平衡计算机视觉中的精度和速度性能。

注意:PixelLib pytorch版本不支持自定义训练,使用PointRend的自定义训练即将发布。

通过以下方式联系我:

电子邮件:olafenwaayoola@gmail.comolafenwaayoola@gmail.com

LinkedIn:Ayoola OlafenwaAyoola Olafenwa

推特:@AyoolaOlafenwa@AyoolaOlafenwa

看看这些关于如何利用PixelLib在图像和视频中进行语义分割、实例分割、对象提取和背景编辑的文章。

原创文章,作者:fendouai,如若转载,请注明出处:https://panchuang.net/2021/09/26/%e4%bd%bf%e7%94%a85%e8%a1%8c%e4%bb%a3%e7%a0%81%e7%9a%84%e5%ae%9e%e6%97%b6%e5%9b%be%e5%83%8f%e5%88%86%e5%89%b2/

联系我们

400-800-8888

在线咨询:点击这里给我发消息

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息