python 黑白tif提取边界像素坐标_OpenCV GrabCut算法:前景分割和提取
点击上方"蓝色小字"关注我呀
文章翻译自光头哥哥的博客,原文链接:
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掩膜(包括边界框初始化)。左上的:明确的背景。右上的:可能的背景。左下:明确的前景。右下角:可能的前景。
这些值对应为:
明确背景(左上角):cv2.GC_BGD
可能的背景(右上):cv2.GC_PR_BGD
明确的前景(左下):cv2.GC_FGD
可能的前景(右下):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算法:前景分割和提取相关推荐
- OpenCV GrabCut算法前景分割和提取
目录 一.OpenCv Grabcut算法:前景提取与分割(Foreground segmentation and extraction) (一)算法工作原理 (二)opencv函数cv2.grabC ...
- OpenCV GrabCut算法:前景分割和提取
目录 一.OpenCv Grabcut算法:前景提取与分割(Foreground segmentation and extraction) (一)算法工作原理 (二)opencv函数cv2.grabC ...
- Python OpenCV GrabCut进行前景分割和提取
Python OpenCV GrabCut进行前景分割和提取 1. 效果图 1.1 边界框GrabCut效果图 1.2 Mask GrabCut效果图 2. GrabCut原理 2.1 GrabCut ...
- lisp提取长方形坐标_如何利用lisp程序一次性提取CAD中点的坐标(不要点击每个点,太多了麻烦)...
(DEFUN C:TT ( / ss ff ss1 en pt x y) (setvar "cmdecho" 0) (setvar "blipmode" 0) ...
- Python OpenCV学习笔记之:使用Grabcut算法进行图像背景和前景分割
为什么80%的码农都做不了架构师?>>> # -*- coding: utf-8 -*- """ 图像分割 """i ...
- java grabcut,在OpenCV中应用GrabCut算法后获取相同的图像
我使用GrabCut算法来分割我的图像my image,以检测我图像中的柑橘(水果)作为前景并从背景中减去它 . 为此,首先我必须在我的对象(水果)周围选择2个点,用于在我的对象(水果)周围绘制矩形, ...
- lisp提取长方形坐标_用 Python 对图片主体轮廓进行提取、颜色标记、并计算区域面积...
Python + Opencv2 实现轮廓提取,轮廓区域面积计算: 对图像处理时,会遇到这样一个场景:找到图像主体轮廓,这是其一,可能为了凸显轮廓,需要用指定的颜色进行标记:轮廓标记完可能任务还没 ...
- OpenCV python GrabCut算法提取前景背景图片
OpenCV python GrabCut算法提取前景背景图片 处理图片:[lena_color.jpg] 手动mask[mask.jpg] import numpy as np import cv2 ...
- python提取cad坐标_教你一个实用的CAD坐标提取技巧
经常用CASS计算土石方的小伙伴,经常会遇到一个很大的拦路虎:拿到一张甲方提供的dwg图纸,要求用CASS进行土石方计算.顿时感觉无从下手了. 遇到这样的问题,我常常会问焦急的小伙伴三个问题: 已知的 ...
最新文章
- 【Servlet】Request/Response/Cookie/Session中常用方法
- 计算机网络按信号频带占用方式分为,《计算机网络及组网技术》第2阶段测试题....
- mos管防倒灌电路_MOS管自举电路工作原理及升压自举电路结构图
- MySQL高级 - SQL优化 - 子查询优化
- 使用 Spring 2.5 注释驱动的 IoC 功能
- 10个痛点:IT部门如何面对边缘计算
- Ubuntu20+TendaU12驱动离线安装
- python足球数据分析_Python 进行 NBA 比赛数据分析
- Rust_lings
- ADSL自动更换IP的方法
- MyGUI_Orge官网教程_2.快速在工程中使用MyGUI
- 2019unity游戏开发需要学什么?
- ESP8266深度睡眠计时器唤醒
- App在后台被杀死后重启-重进首页方法
- SQL语言_3 模糊查询和聚合函数
- 字符串和转义字符的知识和应用
- 微信企业付款到银行卡(微信转账)(Java完整版)
- 说说Python中切片是什么?
- File.delete()返回false 解决办法--权限
- mysql 事件报错1314_mysql 1314