如何使用AI和Python从图像中删除背景?

2021年11月28日04:43:06 发表评论 1,983 次浏览

如何删除图像中的背景?人工智能已经席卷全球。随着越来越多的职业将人工智能与其各自领域相结合,这个概念几乎彻底改变了所有其他领域。下面的文章随后探讨了使用人工智能来去除图像的背景。

Python如何从图像中删除背景?背景去除的想法不是现代的;相反,它自现代技术出现以来就存在于该领域。因此,在计算机视觉领域有许多用于背景去除的技术。尽管如此,经典的计算机视觉技术不断被现代的、基于人工智能的技术所推翻,因为它提出了更多创新的想法,提供了更精确和准确的结果,本文为你介绍相关的具体技术,包括具体的Python删除图像中的背景示例。


经典计算机视觉

经典的计算机视觉依赖于相当广泛的手动工作来构建基于规则的技术来检测和分类图像中的特定像素组。该模型需要被明确告知要检测什么和分类什么,以及图像中存在哪些对象。它包含多种视觉模型技术,如边缘检测器和物体检测器。过滤图像的概念也属于同一保护伞。此外,还包括卷积、霍夫变换和平滑技术。要了解有关计算机视觉经典方法的更多信息,请访问计算机视觉中的经典概念 。

深入探讨手头的问题,经典计算机视觉如何处理从图像中去除背景的想法?最著名的前景提取方法之一,也称为背景去除,是基于分割的颜色阈值。在这个模型中,整个图像被分成多个更小的片段,每个像素值与预先设置的阈值进行比较。阈值通过将像素的强度值降低到单一的纯灰色阴影(通常是纯白色,像素值为 255)来抑制背景信息。你可以在论文中阅读更多相关信息:用于分割自然图像的颜色阈值方法 。

使用经典方法去除背景的处理图像。 来源:https://datacarpentry.org/image-processing/07-thresholding/
使用经典方法去除背景的处理图像。来源:https://datacarpentry.org/image-processing/07-thresholding/

经典方法的另一个很好的例子是我们在博客上为自动驾驶汽车和自动车道检测系统所做的工作 。


现代计算机视觉

现代人工智能和机器学习的曙光彻底改变了计算机视觉领域。与更多依赖复杂编码数学函数和变换的经典计算机视觉不同,现代计算机视觉主要基于人工智能的深度学习技术来执行计算机视觉任务。深度学习是机器学习的一个分支, 涉及主要受人脑功能启发的算法。深度学习模型的算法被称为人工神经网络。你可以在我们应该了解的顶级深度学习算法中找到更多关于神经网络的信息 。

神经网络架构。 资料来源:https://www.extremetech.com/extreme/215170-artificial-neural-networks-are-changed-the-world-what-are-they
神经网络架构。资料来源:https://www.extremetech.com/extreme/215170-artificial-neural-networks-are-changed-the-world-what-are-they

如何删除图像中的背景?深度学习中卷积神经网络的概念极大地影响了日常计算机视觉任务的思考和处理方式。人工神经网络需要大量输入数据用于训练目的,以至于对于深度学习,我们甚至可以颠倒“少即是多”的说法,将数据称为“多即少”。

卷积神经网络将图像作为输入,并通过几个卷积和非线性过程来输出所谓的“特征图”,其中包含有关输入图像的空间信息。然后使用特征图提取类别的输出标签,然后使用损失函数将其与输入图像类别的已知实际标签进行比较。

对训练数据中存在的所有训练样例迭代地完成这个过程,并获得优化的模型。然后使用优化的模型为新图像提取标签。标签可以是二进制的(0 和 1),也可以是两个以上。当只有两个类时,标签是二进制的;例如,我们必须确定图像是否是猫,或者图像是猫还是狗。要了解有关在计算机视觉中使用深度学习的更多信息,请参阅此处博客 。对于计算机视觉中的图像处理和相关方法,请参阅我们使用 OpenCV for Python 的第一步 。


语义分割

Python如何从图像中删除背景?现在回到文章最初的问题,如何使用人工智能来实现背景减法?获得该目标的最著名方法称为语义图像分割

语义图像分割背后的概念是图像的每个像素都属于一个特定的类并被赋予该类的标签。此方法用于世界各地使用的多种应用程序。它扩展到但不限于手写识别、虚拟化妆、虚拟试穿、视觉图像搜索和自动驾驶汽车。

该方法的抽象思想是,当每个像素都被赋予一个类标签时,神经网络会在大量示例上进行训练,以了解哪种像素属于特定类,比如说前景类,以及哪个像素属于另一个类,背景一。

在训练像素分类器之后,带有与背景类别对应的标签的结果像素被分配一个灰色阴影(通常是白色)。前景图像保持原样;因此,据说图像的背景已被删除。

用于语义分割模型构建的最新方法是“UNet”和“DeepLab”。两种架构都提出了各种技术来获取语义分割,最大限度地减少计算成本并最大限度地提高准确性。

要了解有关如何将语义分割用于图像和视频的更多信息,请访问2021 年语义分割指南 。

使用 DL 的最先进示例。 来源:https://devblogs.microsoft.com/cse/2018/04/18/deep-learning-image-segmentation-for-ecommerce-catalogue-visual-search/
使用 DL 的最先进示例。来源:https://devblogs.microsoft.com/cse/2018/04/18/deep-learning-image-segmentation-for-ecommerce-catalogue-visual-search/

本文将介绍一种称为MODNet的最先进模型,该模型使用图像抠图(语义分割的一种高级形式)来执行背景减法。


Python删除图像中的背景示例:什么是图像抠图?

Python如何从图像中删除背景?图像抠图是图像分割的高级扩展概念。在图像抠图中,不是仅将像素分配给两个标签;前景 (1) 和背景 (0),我们用 0 到 1 之间的任何值标记每个像素,指的是前景的强度或不透明度。这个介于 0 和 1 之间的值称为 αp。众所周知,图像抠图是一项比图像分割复杂得多的任务;因此使用trimap和stroke等交互方法来输出用户期望的结果。

Trimap的概念本质上引起了对前景的有意义的提取。在trimap的情况下,用户可以手动为图像的像素分配三个标签之一,即前景、背景和未知区域。因此,对于给定的trimap,图像抠图被简化为基于前景和背景像素估计图像未知区域中像素的背景颜色、前景颜色和alpha值。

与trimap方法不同,strokes方法只需要在适当的图像区域指定一些前景和背景涂鸦。在基于笔画的算法中,这些标记的涂鸦被视为输入并用于提取 alpha 值。

除了trimap和stroke方法之外,还有多种不同的图像抠图交互模式,包括蓝屏抠图、自然抠图、基于采样的抠图、基于传播的抠图和基于学习的抠图。要了解有关这些图像抠图交互技术的更多信息,请访问“图像抠图在图像分割中的作用是什么?”。


MOD网

如何删除图像中的背景?首先,我们将抽象地看一下 MODNet 的架构,它本身就是一个复杂的算法,包括交互式和非交互式技术的组合来执行图像抠图。

MODNet的架构

在其主干上,MODNet 建立在以下思想之上:无trimap 抠图作为分割步骤加上基于trimap 的抠图步骤可以实现更好的性能。MODNet 通过将无trimap-free 图像抠图进一步划分为语义估计、细节预测和语义细节融合来扩展这一想法。语义估计输出一个粗糙的前景掩码,而细节预测输出一个精细的前景掩码。语义细节融合融合了前两层的特征。

  1. 语义估计 语义估计的第一步是定位图像中的人/人。这种与原始方法的区别在于,高级特征的提取仅由编码器即低级分支完成。这使得估计更有效,因为它不再由包含解码器和编码器的单独模型完成。
  2. 细节预测 前景肖像周围的区域用高分辨率分支处理,该分支以图像、低级分支输出和来自低级分支的低级特征作为输入。重用低级特征的目的是减少细节预测的计算开销。
  3. Semantic Detail Fusion MODNet 的融合分支是卷积神经网络架构。要了解卷积神经网络,请访问卷积神经网络综合指南 。来自前两个分支的值连接在一起以预测最终的 alpha 遮罩。

Python删除图像中的背景示例:MODNet 提供了一种简单、快速且有效的架构,以避免在实时人像抠图中使用绿屏。通过仅查看 RGB 图像,该模型可以在不同场景下预测 alpha 遮罩。尽管有很多优点,但 MODNet 架构的缺点是它不能处理奇怪的服装和强烈的运动模糊,这些都没有被模型没有训练过的训练集覆盖。要广泛研究 MODNet 架构及其实验,请参阅论文,实时人像抠图真的需要绿屏吗?

MODNet 架构。 来源:https://arxiv.org/abs/2011.11961
MODNet 架构。来源:https://arxiv.org/abs/2011.11961

编码时间

与往常一样,你可以自己编写代码,也可以在此处访问 Google Colab 上的完整工作代码 。

Python如何从图像中删除背景?现在我们已经涵盖了从经典计算机视觉和现代计算机视觉之间的差异到 MODNet 的基本架构的背景减除的所有基础知识。我们可以继续运行代码以使用预训练的 MODNet 作为图像的背景去除器。

请注意,该代码是为 Google Colab 开发的,因此如果你想在本地运行,则必须对存储和加载文件的方式进行调整。

模型准备

import os

# clone the repository
%cd /content
if not os.path.exists('MODNet'):
  !git clone https://github.com/ZHKKKe/MODNet
%cd MODNet/

# dowload the pre-trained ckpt for image matting
pretrained_ckpt = 'pretrained/modnet_photographic_portrait_matting.ckpt'
if not os.path.exists(pretrained_ckpt):
  !gdown --id 1mcr7ALciuAsHCpLnrtG_eop5-EYhbCmz \
          -O pretrained/modnet_photographic_portrait_matting.ckpt

'import os' 命令导入操作系统模块,这是标准库的一部分。os 模块提供创建和删除目录、获取内容、更改或识别当前目录等功能。

'%cd' 命令进入其前面提到的路径的目录。if 语句被放置在那里以建议检查代码,以判断 MODNet 目录是否已经存在于当前目录中。如果没有,则从包含该目录的 GitHub 存储库克隆 MODNet 目录。

克隆 MODNet 目录后,我们从目录中导入预训练的模型检查点文件。此处,将进行另一项检查以查找检查点文件是否存在于目录中。如果没有,则下载预训练的模型检查点文件。

上传图片

import shutil
import os
from google.colab import files

# clean and rebuild the image folders
input_folder = 'demo/image_matting/colab/input'
if os.path.exists(input_folder):
  shutil.rmtree(input_folder)
os.makedirs(input_folder)

output_folder = 'demo/image_matting/colab/output'
if os.path.exists(output_folder):
  shutil.rmtree(output_folder)
os.makedirs(output_folder)

# upload images (PNG or JPG)
image_names = list(files.upload().keys())
for image_name in image_names:
  shutil.move(image_name, os.path.join(input_folder, image_name))

Python删除图像中的背景示例解析:现在我们继续下一段代码。我们首先导入必要的模块。'shitil' 模块提供了几个函数来处理对文件及其集合的操作。它提供了复制和删除文件的能力。同理,我们导入colab的os模块和files模块。文件模块将帮助我们将文件从本地机器上传到 google colab。首先,我们通过检查目录中是否已经存在输入和输出文件夹来创建它们。如果是,则删除现有文件夹,并创建具有相同名称的新文件夹。接下来,我们使用 colab 的 files 模块在 google colab 运行时上传我们本地机器上的图像。上传完成后,我们将上传的图片移动到我们之前创建的输入文件夹中。

推理

!python -m demo.image_matting.colab.inference \
        --input-path demo/image_matting/colab/input \
        --output-path demo/image_matting/colab/output \
        --ckpt-path ./pretrained/modnet_photographic_portrait_matting.ckpt

运行上面的命令,因为它使用预训练的 MODNet 模型来推断输入图像上的 alpha 遮罩。上面的命令使用我们在步骤 1 中下载的检查点模型文件对上传的图像执行抠图操作。

可视化

import numpy as np
from PIL import Image

def combined_display(image, matte):
  # calculate display resolution
  w, h = image.width, image.height
  rw, rh = 800, int(h * 800 / (3 * w))
  
  # obtain predicted foreground
  image = np.asarray(image)
  if len(image.shape) == 2:
    image = image[:, :, None]
  if image.shape[2] == 1:
    image = np.repeat(image, 3, axis=2)
  elif image.shape[2] == 4:
    image = image[:, :, 0:3]
  matte = np.repeat(np.asarray(matte)[:, :, None], 3, axis=2) / 255
  foreground = image * matte + np.full(image.shape, 255) * (1 - matte)
  
  # combine image, foreground, and alpha into one line
  combined = np.concatenate((image, foreground, matte * 255), axis=1)
  combined = Image.fromarray(np.uint8(combined)).resize((rw, rh))
  return combined

# visualize all images
image_names = os.listdir(input_folder)
for image_name in image_names:
  matte_name = image_name.split('.')[0] + '.png'
  image = Image.open(os.path.join(input_folder, image_name))
  matte = Image.open(os.path.join(output_folder, matte_name))
  display(combined_display(image, matte))
  print(image_name, '\n')

如何删除图像中的背景?现在我们继续可视化去除背景的新图像。我们还将查看从输入图像中提取的 alpha 遮罩。

首先,我们导入必要的模块。NumPy 是一个支持大型多维数组和矩阵的库,以及用于对这些数组进行操作的大量高级数学函数集合。要了解有关可以使用 NumPy 执行哪些操作的更多信息,请阅读此处的文档 。Python 图像库 (PIL) 是一个添加对打开、操作和保存多种不同图像文件格式的支持的库。

Python删除图像中的背景示例解析:我们从函数“combined_display”开始。首先,计算要显示的图像的分辨率。因此,我们通过执行某些图像操作来提取预测的前景图像,即去除背景的图像,包括将图像重新整形为 3 通道 (RGB) 图像,然后将图像连接成单个图像,以便三个图像(原始图像、前景图像和遮罩图像)显示在一个图像中。我们获得如下所示的输出。

原始、处理和蒙版图像
原始、处理和蒙版图像

保存结果

zip_filename = 'matte.zip'
if os.path.exists(zip_filename):
  os.remove(zip_filename)

os.system(f"zip -r -j {zip_filename} {output_folder}/*")
files.download(zip_filename)

最后,你可以使用 OS 模块将预测的 alpha 格式保存到 zip 文件中到你的本地运行时/机器。


结论

Python如何从图像中删除背景?现代的、基于深度学习的计算机视觉以其应用风靡全球。背景去除有许多经典技术,但最近人工智能已经证明自己可以提供更好、更有效的方法来完成任务。一种这样的方法称为语义分割,我们通过查看图像的每个像素并将其分配为前景或背景两类之一来训练输入和输出图像。

因此,许多研究人员和开发人员致力于创建改进且更高效的模型和架​​构来执行每项任务。背景去除器的情况也是如此,也称为前景提取器。这种架构的一个例子是MODNet,它使用使用trimap交互技术的图像抠图的概念,其中图像像素分为三类,即:前景、背景和未知区域。根据前景的不透明度为未知区域计算不同的 alpha 值。

使用预训练的 MODNet 模型很简单,你可以从官方公共 GitHub 存储库中导入预训练的模型并输入要从中删除背景的图像。它输出去除背景的图像。

谢谢阅读!

木子山

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: