点击上方"蓝色小字"关注我呀

文章翻译自光头哥哥的博客,原文链接:

https://www.pyimagesearch.com/2020/07/27/opencv-grabcut-foreground-segmentation-and-extraction/

本文仅作学习分享,以下为正文。

前言

在本教程中,你将学习如何使用OpenCV和grabCut分割算法来执行前景分割和提取。

在deep learning和Mask R-CNN、U-Net等语义分割网络之前,GrabCut是一种精确分割图像前景和背景的方法。

GrabCut算法的工作原理是:

  • 接收一个输入图像,其中参数1指定我们想分割的图像中对象的位置的边界框,然后参数2是近似分割的腌膜

  • 迭代地执行以下步骤:

步骤1:使用高斯混合模型(GMM)估计前景和背景的颜色分布
步骤2:在像素标签上构造一个马尔可夫随机场。(如前景与背景)
步骤3:应用图切割优化来达到最终的分割

听起来很复杂,是吗?

但幸运的是,OpenCV有一个通过cv2实现的grabCut函数,使应用grabCut轻而易举(前提是你知道函数的参数含义以及如何调整它们)。
但你可能会说:“嘿,阿德里安,GrabCut算法不是老新闻了吗?我们不应该只是使用Mask R-CNN, U-Net,或其他图像分割网络来分割背景和前景吗?”。

如果你以前用过Mask R-CNN或U-Net,你就会知道这些深度神经网络非常强大,但他们生成的掩膜并不总是完美的。实际上,你可以使用GrabCut来清理这些分割掩模(我将在以后的帖子中向你展示如何做到这一点)。

但与此同时,让我们了解一下GrabCut的基本原理。

要学习如何使用OpenCV和GrabCut进行前景分割,请继续阅读。

OpenCV GrabCut:前景分割和提取

在本教程的第一部分中,我们将讨论grabCut函数,及其相关参数。
在这里,我们将学习如何通过:

  • 带有边框的GrabCut初始化

  • 带掩模近似的GrabCut初始化

实现opencv的GrabCut算法,之后,我们将应用GrabCut并回顾我们的成果。

OpenCV 的GrabCut

图1:执行前景分割的方法选择。f列显示GrabCut的结果;与其他方法相比,GrabCut的结果是一个高质量的输出分割。在今天的教程中,我们将应用GrabCut和OpenCV来进行前景和背景的分割和提取。

cv2.grabCut函数有以下参数:

grabCut(img, mask, rect, bgdModel, fgdModel, iterCount, mode) ->  mask, bgdModel, fgdModel 

为了获得对实现的完整理解,让我们回顾一下这些参数:

  • img:输入图像,GrabCut假设它是一个8位的3通道图像(即, BGR信道顺序中的无符号8位整数)。

  • 掩膜:输入/输出掩膜。假设该掩膜是一个单通道图像,数据类型为无符号8位整数。如果你使用边界框初始化(第七个参数mode设为cv2.GC_INIT_WITH_RECT),这个掩膜会自动初始化。否则,GrabCut假设您正在执行掩码初始化(第七个参数设为cv2.GC_INIT_WITH_MASK)。

  • 矩形:包含我们要分割的区域的边框矩形。此参数仅在将模式设置为cv2.GC_INIT_WITH_MASK时使用)。

  • bgModel: GrabCut内部建模背景时使用的临时数组。

  • fgModel: GrabCut在建模前景时使用的临时数组。

  • 迭代计数:GrabCut在对前景和背景建模时执行的迭代次数。迭代次数越多,GrabCut运行的时间越长,理想情况下,结果会更好。

  • 模式:要么cv2.GC_INIT_WITH_RECT或cv2.GC_INIT_WITH_MASK,这分别取决于你是用一个边框还是一个掩码初始化GrabCut。

OpenCV的GrabCut实现返回一个3元组:

  • 掩膜:应用GrabCut后的输出掩模

  • bgModel:用于建模背景的临时数组(可以忽略此值)

  • fgModel:用于建模前景的临时数组(同样,你可以忽略此值)

现在我们已经了解了cv2,grabCut,包括它的参数和返回的值,让我们继续将grabCut应用到一个示例计算机视觉项目中。

项目结构

在继续之前,使用本教程的“下载”部分获取与这篇博客文章相关的.zip(有需要的可以去原文链接下载)。从这里,让我们检查文件和文件夹的布局,直接在我们的终端与树执行命令:

$ tree --dirsfirst.├── images│   ├── adrian.jpg│   ├── lighthouse.png│   └── lighthouse_mask.png├── grabcut_bbox.py└── grabcut_mask.py1 directory, 5 files

我们今天的项目包括一个文件夹的图像和两个Python脚本:

  • 两个输入的照片和一个手动创建的近似掩模图像

  • grabcut_bbox.py:通过边界框初始化的方式完成GrabCut的脚本

  • grabcut_mask.py:通过蒙版Mask初始化执行GrabCut

通过使用这两个Python脚本,我们将学习如何使用两种方法(边界框初始化和掩码初始化)来执行GrabCut。我们将在下一节中开始使用边界框方法。

初始化边框的GrabCut方法

让我们开始用OpenCV实现GrabCut——我们将首先回顾一下边界框的实现方法。
这里,我们将指定要在图像中分割的对象的边界框。边界框可以通过以下方式生成:

  • 手动检查图像并标记边框的(x, y)坐标

  • 应用Haar级联

  • 利用HOG +线性SVM检测目标

  • 利用基于深度学习的对象检测器,如Faster R-CNN, SSDs, YOLO等。

只要算法生成一个边界框,就可以将它与GrabCut结合使用。

出于今天演示脚本的目的,我们将手动定义边界框(x, y)坐标(即边界框)。而不是应用自动对象检测器。

现在让我们看看GrabCut的边界框初始化方法。
打开一个新文件,命名为grabcut_bbox.py,并插入以下代码:

# import the necessary packagesimport numpy as npimport argparseimport timeimport cv2import os# construct the argument parser and parse the argumentsap = argparse.ArgumentParser()ap.add_argument("-i", "--image", type=str,  default=os.path.sep.join(["images", "adrian.jpg"]),  help="path to input image that we'll apply GrabCut to")ap.add_argument("-c", "--iter", type=int, default=10,  help="# of GrabCut iterations (larger value => slower runtime)")args = vars(ap.parse_args())

我们从选择的导入开始这个脚本,即OpenCV和NumPy(其余都内置在Python中)。

我们的脚本处理两个命令行参数:

  • --image:输入图像的路径。默认情况下,我们将在images/目录中使用adrian.jpg图像。

  • --iter:GrabCut迭代要执行的次数,较小的值会导致更快的总体时间,较大的值会导致较慢的运行时间(但理想情况下更好的分割结果)

让我们加载我们的输入图像,并为相等大小的掩膜分配空间:

# load the input image from disk and then allocate memory for the# output mask generated by GrabCut -- this mask should hae the same# spatial dimensions as the input imageimage = cv2.imread(args["image"])mask = np.zeros(image.shape[:2], dtype="uint8")

在这里,第4行从磁盘加载您的输入—图像,第5行创建一个掩膜(即空图像)具有相同的尺寸。这个掩模将很快被GrabCut算法的结果填充。

接下来,我们将手动定义adrian.jpg图像中人脸的坐标:

# define the bounding box coordinates that approximately define my# face and neck region (i.e., all visible skin)rect = (151, 43, 236, 368)

第3行定义了图像中人脸的边界框坐标。这些(x, y)坐标是手动确定的,方法是鼠标悬停在图像中的像素上,然后我把它们记下来。你可以通过Photoshop或GIMP等免费的图片编辑软件和其他你在网上找到的应用来完成这一任务。
这里需要注意的是,虽然这些face rect坐标是手动确定的,但任何对象检测器都可以完成这项工作。假设我们的第一个示例是一个人脸,您可以选择一个Haar、HOG或基于dll的面检测器来查找边界。

在下一个代码块中,我们将执行GrabCut算法,并对输入进行边界框初始化:

# allocate memory for two arrays that the GrabCut algorithm internally# uses when segmenting the foreground from the backgroundfgModel = np.zeros((1, 65), dtype="float")bgModel = np.zeros((1, 65), dtype="float")# apply GrabCut using the the bounding box segmentation methodstart = time.time()(mask, bgModel, fgModel) = cv2.grabCut(image, mask, rect, bgModel,fgModel, iterCount=args["iter"], mode=cv2.GC_INIT_WITH_RECT)end = time.time()print("[INFO] applying GrabCut took {:.2f} seconds".format(end - start))

在执行GrabCut计算之前,我们需要两个空数组,以便GrabCut在从背景分割前景时使用(fgModel和bgModel)。第3行和第4行使用NumPy的zeros方法生成两个数组。
从那里,第7行应用GrabCut(在操作之前/之后收集时间戳),经过的时间通过第9行打印出来。

GrabCut返回我们填充的掩码以及两个我们可以忽略的数组。如果您需要查看包括输入参数和返回值在内的GrabCut方法参数,请参阅上面的“OpenCV中的GrabCut”一节。

让我们继续对掩膜进行后期处理:

# the output mask has for possible output values, marking each pixel# in the mask as (1) definite background, (2) definite foreground,# (3) probable background, and (4) probable foregroundvalues = (  ("Definite Background", cv2.GC_BGD),  ("Probable Background", cv2.GC_PR_BGD),  ("Definite Foreground", cv2.GC_FGD),  ("Probable Foreground", cv2.GC_PR_FGD),)# loop over the possible GrabCut mask valuesfor (name, value) in values:  # construct a mask that for the current value  print("[INFO] showing mask for '{}'".format(name))  valueMask = (mask == value).astype("uint8") * 255  # display the mask so we can visualize it  cv2.imshow(name, valueMask)  cv2.waitKey(0)

第4-9行定义了输出的GrabCut掩膜中可能的值,包括我们确定的/可能的背景和前景。
然后我们继续对这些值进行循环,以便我们可以可视化每个值。在循环中(第11-17行),我们(1)为当前值构造一个掩码,并(2)显示它,直到按下任何键为止。

在我们确定的/可能的背景和前景已经显示后,我们的代码将开始生成一个outputMask和一个输出图像:

# we'll set all definite background and probable background pixels# to 0 while definite foreground and probable foreground pixels are# set to 1outputMask = np.where((mask == cv2.GC_BGD) | (mask == cv2.GC_PR_BGD), 0, 1)# scale the mask from the range [0, 1] to [0, 255]outputMask = (outputMask * 255).astype("uint8")# apply a bitwise AND to the image using our mask generated by# GrabCut to generate our final output imageoutput = cv2.bitwise_and(image, image, mask=outputMask)

在这里,我们显示了两幅图像:

  • GrabCut输出掩膜

  • 输出图像(背景被掩盖)

为了生成我们的GrabCut outputMask,第4行找到所有确定的背景或可能的背景像素,并将它们设置为0 ,所有其他像素应该标记为1(即:,前景)。请注意,我们是如何利用NumPy的where函数来处理每个掩码并相应地将值设置为0和1的。然后,第6行将outputMask从范围[0,1]扩展到[0,255]。

然后,我们通过bitwise_and操作生成隐藏背景的输出图像,并将outputMask作为mask参数传递(第9行)。

此时,我们有:

  • 为grabCut函数准备的输入,包括我们的输入图像、掩模、矩形坐标以及fgModel和bgModel零数组。注意,rect坐标是手动确定的。

  • 执行GrabCut算法。

  • 生成并可视化我们确定的/可能的背景和前景腌膜。

  • 生成我们的(1)GrabCut输出掩膜(outputMask)和(2)带有背景掩膜的输出图像(output)。

让我们继续并显示我们的最终结果:

# show the input image followed by the mask and output generated by# GrabCut and bitwise maskingcv2.imshow("Input", image)cv2.imshow("GrabCut Mask", outputMask)cv2.imshow("GrabCut Output", output)cv2.waitKey(0)

最后,我们在单独的窗口中显示以下内容:

  • image:原图

  • outputMask:GrabCut 生成的mask

  • 输出:我们努力工作的结果:只有前景的原始图像(即背景已经用GrabCut的方法掩盖了)

现在已经实现了带有边框初始化的GrabCut,让我们继续将其应用到输入图像中。

边框抓取结果:

图2:GrabCut边界初始化方法要求提供边界坐标作为算法的输入。在这里,我手动找到了边界框的坐标;但是,您可以应用任何类型的对象检测器来获取(x, y)坐标。无论哪种方式,您都可以使用OpenCV应用GrabCut来执行前景分割和提取。

在左侧,您可以看到原始的输入图像,而在右侧,您可以看到在face/neck区域周围绘制了一个边界框的相同面孔(该边界框对应于grabcut_bbox.py脚本中的rect变量)。

我们的目标是使用GrabCut和OpenCV从上面的图像中自动分割面部和颈部区域。

接下来,你可以看到我们输出的明确和可能的背景和前景分段:

图3:使用OpenCV显示的各种GrabCut掩膜(包括边界框初始化)。左上的:明确的背景。右上的:可能的背景。左下:明确的前景。右下角:可能的前景。

这些值对应为:

  1. 明确背景(左上角):cv2.GC_BGD

  2. 可能的背景(右上):cv2.GC_PR_BGD

  3. 明确的前景(左下):cv2.GC_FGD

  4. 可能的前景(右下):cv2.GC_PR_FGD

最后,我们有GrabCut自身的输出:

图4:左:我的原始输入图像。右:通过边界框初始化抓取掩模。下图:我们的输出图像,前景通过GrabCut掩蔽从背景中分割出来。利用OpenCV生成每一幅图像,并应用GrabCut进行前景分割和提取。

左边是原始的输入图像。
右边是GrabCut生成的输出mask,下面是将mask应用到输入图像的输出-注意我的脸部和颈部区域是如何通过GrabCut清晰地分割和提取的。

初始化掩膜的grabCut方法

之前,我们学习了如何使用边界框来初始化OpenCV的GrabCut ,但实际上还有第二个方法来初始化GrabCut。

使用腌膜,我们可以提供图像中物体的近似分割。然后,GrabCut可以迭代地应用图切割来改进分割,并从图像中提取前景。

这些掩膜可以通过以下方式生成:

  • 在Photoshop、GIMP等图片编辑软件中手动创建。

  • 应用阈值、边缘检测、轮廓滤波等基本图像处理操作。

  • 利用基于深度学习的分割网络(如Mask R-CNN和U-Net)

如何生成腌膜与GrabCut无关。只要你有一个近似图像中物体分割的掩膜,你可以使用GrabCut来进一步改进分割。

让我们看看基于初始化掩膜的GrabCut方法如何工作。

在你的项目目录结构中打开grabcut_mask.py文件,插入以下代码:

# import the necessary packagesimport numpy as npimport argparseimport timeimport cv2import os# construct the argument parser and parse the argumentsap = argparse.ArgumentParser()ap.add_argument("-i", "--image", type=str,default=os.path.sep.join(["images", "lighthouse.png"]),help="path to input image that we'll apply GrabCut to")ap.add_argument("-mask", "--mask", type=str,default=os.path.sep.join(["images", "lighthouse_mask.png"]), help="path to input mask")ap.add_argument("-c", "--iter", type=int, default=10,help="# of GrabCut iterations (larger value => slower runtime)")args = vars(ap.parse_args())

同样,我们最值得注意的导入是OpenCV和NumPy。

我们的脚本处理三个命令行参数:

  • --image:输入图像的路径。这一次,默认情况下,我们将使用images/目录中可用的lighthou. png照片。

  • --mask:输入近似掩模的路径与输入图像相关联。同样,您可以用本节顶部列出的许多方法创建这个掩膜,但是为了本示例的目的,我手工创建了这个掩膜。

  • --iter:要执行的GrabCut迭代的数量,较小的值导致更快的总体时间,较大的值导致更慢的运行时间(但理想情况下更好的分割结果)

现在我们的导入和命令行参数已经完成了,让我们继续加载我们的输入——image和输入——mask。

# load the input image and associated mask from diskimage = cv2.imread(args["image"])mask = cv2.imread(args["mask"], cv2.IMREAD_GRAYSCALE)# apply a bitwise mask to show what the rough, approximate mask would give usroughOutput = cv2.bitwise_and(image, image, mask=mask)# show the rough, approximated outputcv2.imshow("Rough Output", roughOutput)cv2.waitKey(0)

在开始第二个GrabCut方法之前,我们需要从磁盘加载我们的输入——image和——mask(第2和3行)。

请注意,我们的粗糙掩膜是为了这个例子而手工生成的(使用Photoshop/GIMP)。然而,在未来的文章中,我们将向你展示如何通过深度学习腌膜R-CNN自动生成掩膜。

第5行对使用蒙版的图像按位和操作,得到我们的前景分割的粗略近似。随后的第7和8行显示近似值,直到按下任何键。

在这里,我们将在腌膜数组中设置可能/确定的前景值:

# any mask values greater than zero should be set to probable# foregroundmask[mask > 0] = cv2.GC_PR_FGDmask[mask == 0] = cv2.GC_BGD

掩膜中任何大于零的像素值被设置为可能的前景(第3行);所有其他像素值设置为明确的背景(第4行)。

我们现在准备应用带有掩膜初始化的GrabCut:

# allocate memory for two arrays that the GrabCut algorithm internally# uses when segmenting the foreground from the backgroundfgModel = np.zeros((1, 65), dtype="float")bgModel = np.zeros((1, 65), dtype="float")# apply GrabCut using the the mask segmentation methodstart = time.time()(mask, bgModel, fgModel) = cv2.grabCut(image, mask, None, bgModel,fgModel, iterCount=args["iter"], mode=cv2.GC_INIT_WITH_MASK)end = time.time()print("[INFO] applying GrabCut took {:.2f} seconds".format(end - start))

同样,我们为GrabCut的前景和后景模型分配内存(第3行和第4行)。
然后我们使用近似掩模分割对图像执行GrabCut(第7行)。注意rect参数是如何设置为None的(这个方法不需要它),不像这篇博客文章中描述的第一个基于边框的方法。
接下来,我们将对结果进行后期处理:

# the output mask has for possible output values, marking each pixel# in the mask as (1) definite background, (2) definite foreground,# (3) probable background, and (4) probable foregroundvalues = (  ("Definite Background", cv2.GC_BGD),  ("Probable Background", cv2.GC_PR_BGD),  ("Definite Foreground", cv2.GC_FGD),  ("Probable Foreground", cv2.GC_PR_FGD),)# loop over the possible GrabCut mask valuesfor (name, value) in values:  # construct a mask that for the current value  print("[INFO] showing mask for '{}'".format(name))  valueMask = (mask == value).astype("uint8") * 255  # display the mask so we can visualize it  cv2.imshow(name, valueMask)  cv2.waitKey(0)

这段程序看起来应该特别熟悉。实际上,它与我们第一次GrabCut方法代码演练中的块是相同的。
同样,我们定义明确的/可能的前景和背景值(第5-8行),并显示每个产生的valueMask图像(第11-17行)。
接下来,我们将准备我们的GrabCut腌膜并输出去除背景的图像:

# set all definite background and probable background pixels to 0# while definite foreground and probable foreground pixels are set# to 1, then scale teh mask from the range [0, 1] to [0, 255]outputMask = np.where((mask == cv2.GC_BGD) | (mask == cv2.GC_PR_BGD), 0, 1)outputMask = (outputMask * 255).astype("uint8")# apply a bitwise AND to the image using our mask generated by# GrabCut to generate our final output imageoutput = cv2.bitwise_and(image, image, mask=outputMask)

同样,第4行中的代码现在应该很熟悉了(它们与前面的脚本相同)。
在这里,我们找到所有确定背景或可能背景的像素,并将它们设为0;所有其他像素标记为1(即。,前景)。然后我们将掩码缩放到范围[0,255]。
然后我们使用outputMask对输入图像应用一个按位AND操作,导致背景被删除(屏蔽掉)。
最后我们将结果显示在屏幕上:

# show the input image followed by the mask and output generated by# GrabCut and bitwise maskingcv2.imshow("Input", image)cv2.imshow("GrabCut Mask", outputMask)cv2.imshow("GrabCut Output", output)cv2.waitKey(0)

同样,在结束我们的脚本时,我们显示了输入图像、GrabCut outputMask以及应用掩膜后GrabCut的输出。
现在已经实现了GrabCut蒙版初始化,让我们用自己的示例图像来测试它。

基于腌膜的grabcut算法测试

我们现在准备使用OpenCV和GrabCut通过蒙版初始化来分割图像。
首先使用本教程的“下载”部分下载源代码和示例图像。
然后打开终端,执行以下命令:

$ python grabcut_mask.py[INFO] applying GrabCut took 0.56 seconds[INFO] showing mask for 'Definite Background'[INFO] showing mask for 'Probable Background'[INFO] showing mask for 'Definite Foreground'[INFO] showing mask for 'Probable Foreground'

图5:左:灯塔的原始照片。右:通过掩模初始化应用GrabCut的输出。

在左边,您可以看到我们的原始输入图像。在右边你可以看到通过腌膜初始化应用GrabCut的输出。
右边的图像显示了与灯塔相关的腌膜。为了这篇博文/例子,我在Photoshop中手工创建了这个掩膜mask;然而,任何能够产生一个掩模的算法都可以在这里使用(例如,通过阈值、边缘检测、轮廓的基本图像处理;深度上优于分割;注意到掩膜分割不是很“干净”——我们可以很容易地看到背景的蓝色天空“泄露”到掩膜中。

图6:使用OpenCV显示的各种GrabCut掩膜(掩膜初始化)。左上的:明确的背景。右上的:可能的背景。左下:明确的前景。右下角:可能的前景。

这些值分别对应于:

  • 明确背景(左上角):cv2.GC_BGD

  • 可能的背景(右上):cv2.GC_PR_BGD

  • 明确的前景(左下):cv2.GC_FGD

  • 可能的前景(右下):cv2.GC_PR_FGD

最后,我们有基于腌膜初始化的grabCut分割结果:

图7:左:我们的原始输入图像灯塔。右:通过蒙版初始化抓取蒙版。下图:我们输出的图像,前景通过GrabCut掩蔽从背景中分割出来。利用OpenCV生成每一幅图像,并应用GrabCut进行前

作为参考,左边显示了我们的输入图像。
右边是我们通过GrabCut生成的输出掩膜,下面是我们将GrabCut生成的掩膜应用到原始输入图像的输出。
注意,我们已经清理了分割——天空的蓝色背景被移除,而灯塔作为前景。
唯一的问题是聚光灯在灯塔上的位置已经被标记为背景:

图8:正如你所看到的,带有掩模初始化的GrabCut的结果并不完美。我建议你使用明确的背景掩膜值结果,而不是两个明确/可能的前景掩膜,在这个特定的情况下。你需要使用你的OpenCV/NumPy知识来反转特定的背景掩膜图像。从那里,你的GrabCut蒙版初始化方法将产生一个更好的前景分割。

这里的问题是,光线停留在灯塔的区域多多少少是透明的,导致蓝色天空的背景通过,从而导致GrabCut标记这个区域作为背景。

你可以通过更新你的掩膜使用明确的背景来解决这个问题。当从磁盘加载您的掩码时。我将把这个作为练习留给读者来实现。

为什么GrabCut很好,但不是完美的?

GrabCut是我最喜欢的计算机视觉算法之一,但它并不完美。
此外,基于深度学习的分割网络,如Faster R-CNN和U-Net,可以自动生成从背景中分割物体(前景)的掩膜——这是否意味着GrabCut在深度学习时代是没意义的?
事实上,并非如此。

虽然Faster R-CNN和U-Net是超级强大的方法,但它们会导致生成的掩膜混乱粗糙。我们可以用GrabCut来帮助清理这些掩膜得到更好的结果。我将在以后的博客文章中向您展示如何做到这一点。

THE  END

今天就到这里啦。点击下方箭头就可以来评论区交流啦。

python 黑白tif提取边界像素坐标_OpenCV GrabCut算法:前景分割和提取相关推荐

  1. OpenCV GrabCut算法前景分割和提取

    目录 一.OpenCv Grabcut算法:前景提取与分割(Foreground segmentation and extraction) (一)算法工作原理 (二)opencv函数cv2.grabC ...

  2. OpenCV GrabCut算法:前景分割和提取

    目录 一.OpenCv Grabcut算法:前景提取与分割(Foreground segmentation and extraction) (一)算法工作原理 (二)opencv函数cv2.grabC ...

  3. Python OpenCV GrabCut进行前景分割和提取

    Python OpenCV GrabCut进行前景分割和提取 1. 效果图 1.1 边界框GrabCut效果图 1.2 Mask GrabCut效果图 2. GrabCut原理 2.1 GrabCut ...

  4. lisp提取长方形坐标_如何利用lisp程序一次性提取CAD中点的坐标(不要点击每个点,太多了麻烦)...

    (DEFUN C:TT ( / ss ff ss1 en pt x y) (setvar "cmdecho" 0) (setvar "blipmode" 0) ...

  5. Python OpenCV学习笔记之:使用Grabcut算法进行图像背景和前景分割

    为什么80%的码农都做不了架构师?>>>    # -*- coding: utf-8 -*- """ 图像分割 """i ...

  6. java grabcut,在OpenCV中应用GrabCut算法后获取相同的图像

    我使用GrabCut算法来分割我的图像my image,以检测我图像中的柑橘(水果)作为前景并从背景中减去它 . 为此,首先我必须在我的对象(水果)周围选择2个点,用于在我的对象(水果)周围绘制矩形, ...

  7. lisp提取长方形坐标_用 Python 对图片主体轮廓进行提取、颜色标记、并计算区域面积...

    Python +  Opencv2  实现轮廓提取,轮廓区域面积计算: 对图像处理时,会遇到这样一个场景:找到图像主体轮廓,这是其一,可能为了凸显轮廓,需要用指定的颜色进行标记:轮廓标记完可能任务还没 ...

  8. OpenCV python GrabCut算法提取前景背景图片

    OpenCV python GrabCut算法提取前景背景图片 处理图片:[lena_color.jpg] 手动mask[mask.jpg] import numpy as np import cv2 ...

  9. python提取cad坐标_教你一个实用的CAD坐标提取技巧

    经常用CASS计算土石方的小伙伴,经常会遇到一个很大的拦路虎:拿到一张甲方提供的dwg图纸,要求用CASS进行土石方计算.顿时感觉无从下手了. 遇到这样的问题,我常常会问焦急的小伙伴三个问题: 已知的 ...

最新文章

  1. 【Servlet】Request/Response/Cookie/Session中常用方法
  2. 计算机网络按信号频带占用方式分为,《计算机网络及组网技术》第2阶段测试题....
  3. mos管防倒灌电路_MOS管自举电路工作原理及升压自举电路结构图
  4. MySQL高级 - SQL优化 - 子查询优化
  5. 使用 Spring 2.5 注释驱动的 IoC 功能
  6. 10个痛点:IT部门如何面对边缘计算
  7. Ubuntu20+TendaU12驱动离线安装
  8. python足球数据分析_Python 进行 NBA 比赛数据分析
  9. Rust_lings
  10. ADSL自动更换IP的方法
  11. MyGUI_Orge官网教程_2.快速在工程中使用MyGUI
  12. 2019unity游戏开发需要学什么?
  13. ESP8266深度睡眠计时器唤醒
  14. App在后台被杀死后重启-重进首页方法
  15. SQL语言_3 模糊查询和聚合函数
  16. 字符串和转义字符的知识和应用
  17. 微信企业付款到银行卡(微信转账)(Java完整版)
  18. 说说Python中切片是什么?
  19. File.delete()返回false 解决办法--权限
  20. mysql 事件报错1314_mysql 1314

热门文章

  1. IDEA下用freemarker热更新的问题
  2. ALTER PROFILE DEFAULT LIMIT PASS_LIFE_TIME UNLIMITED
  3. Python简介及安装
  4. 嵌入式软件工程师笔试题(含答案)
  5. Ibatis调用Oracle存储过程,以及返回Cursor结果集的问题
  6. 虚拟化部署之灵活应用Hyper-V快照
  7. Java 实现 SSH 协议的客户端登录认证方式
  8. 接口级故障的应对方法
  9. 在 Spring Boot 中,如何干掉 if else
  10. 避免35岁现象,我给技术人的建议永远是架构师!