填充轮廓但保留包​​含的区域未填充

2024-01-25

我有这个 python 代码,据说可以填充图像的轮廓,但其中包含的孔未填充。这就是我要的:

但这就是我得到的:

我尝试指定轮廓层次结构来填充 cv2,但我无法得到我想要的结果。

这是我尝试过的:


import numpy as np
import cv2

# Load the PNG image
img = cv2.imread('slice.png')

# Convert the image to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Threshold the image to create a binary image
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)

# Find the contours in the binary image
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# Create a blank image with the same dimensions as the original image
filled_img = np.zeros(img.shape[:2], dtype=np.uint8)

# Iterate over the contours and their hierarchies
for i, contour in enumerate(contours):
    # Check if the contour has a parent
    if hierarchy[0][i][3] == -1:
        # If the contour doesn't have a parent, fill it with pixel value 255
        cv2.drawContours(filled_img, [contour], -1, 255, cv2.FILLED)

# Display the result
cv2.imshow('Original Image', img)
cv2.imshow('Filled Regions', filled_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

我尝试修改 'if hierarchy[0][i][3] == -1:' 部分的 -1, 0, 1 值,但它要么填充较小的孔,要么填充整个较大的轮廓,例如我发布的第一张照片。

Update

我还想在较小的层次结构轮廓内部填充白色,如下所示:


问题是cv2.drawContours填充闭合轮廓的整个内部部分,无论是否存在内部轮廓。

我们可以从白色轮廓开始,然后用黑色填充没有父项的轮廓,而不是用白色填充没有父项的轮廓。


假设我们知道内部应该是黑色的,我们可以应用以下阶段:

  • 使用cv2.RETR_EXTERNAL查找轮廓,并用白色填充外部轮廓。
  • 使用 cv2.RETR_TREE 查找轮廓。
  • 迭代轮廓层次结构,并仅用黑色填充没有子轮廓的轮廓(用黑色填充最内部的轮廓)。

代码示例:

import numpy as np
import cv2

# Load the PNG image
img = cv2.imread('slice.png')

# Convert the image to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Threshold the image to create a binary image
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)

# Find the outer contours in the binary image (using cv2.RETR_EXTERNAL)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# Create a blank image with the same dimensions as the original image
filled_img = np.zeros(img.shape[:2], dtype=np.uint8)

# Fill the outer contour with white color
cv2.drawContours(filled_img, contours, -1, 255, cv2.FILLED)

# Find contours with hierarchy, this time use cv2.RETR_TREE
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# Iterate over the contours and their hierarchies
for i, contour in enumerate(contours):
    # Check if the contour has no child
    if hierarchy[0][i][2] < 0:
        # If contour has no child, fill the contour with black color
        cv2.drawContours(filled_img, [contour], -1, 0, cv2.FILLED)

# Display the result
cv2.imshow('Original Image', img)
cv2.imshow('Filled Regions', filled_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Result filled_img:
enter image description here

Note:
如果我们不知道最内部轮廓的颜色,我们可以在黑色背景上绘制白色轮廓,并将结果用作蒙版 - 使用蒙版复制输入图像的原始内容。


Update:

支持没有子项的轮廓:

为了支持有子轮廓和没有子轮廓的轮廓,我们可以填充黑色,仅填充符合这两个条件的轮廓:

  • 轮廓没有子轮廓。
  • 轮廓有一个祖父母轮廓(寻找祖父母而不是父轮廓,因为空轮廓有一个内轮廓,而其父轮廓是外轮廓)。

代码示例:

import numpy as np
import cv2

# Load the PNG image
img = cv2.imread('slice.png')

# Convert the image to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Threshold the image to create a binary image
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)

# Find the outer contours in the binary image (using cv2.RETR_EXTERNAL)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# Create a blank image with the same dimensions as the original image
filled_img = np.zeros(img.shape[:2], dtype=np.uint8)

# Fill the outer contour with white color
cv2.drawContours(filled_img, contours, -1, 255, cv2.FILLED)

# Find contours with hierarchy, this time use cv2.RETR_TREE
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# Iterate over the contours and their hierarchies
for i, contour in enumerate(contours):
    has_grandparent = False
    has_parent = hierarchy[0][i][3] >= 0
    if has_parent:
        # Check if contour has a grandparent
        parent_idx = hierarchy[0][i][3]
        has_grandparent = hierarchy[0][parent_idx][3] >= 0

    # Check if the contour has no child
    if hierarchy[0][i][2] < 0 and has_grandparent:
        # If contour has no child, fill the contour with black color
        cv2.drawContours(filled_img, [contour], -1, 0, cv2.FILLED)

# Display the result
cv2.imshow('Original Image', img)
cv2.imshow('Filled Regions', filled_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Update:

在较小的层次结构轮廓内部填充白色:

在用黑色填充轮廓之前,我们可以检查指定轮廓内部是否有黑色像素。
仅当它没有孩子、有祖父母并且内部有黑色时才填充黑色。

为了测试内部是否有黑色像素,我们可以在临时图像上绘制轮廓(白色)。
然后检查最小值是否为 0(绘制轮廓为白色的值)。

tmp = np.zeros_like(thresh)
cv2.drawContours(tmp, [contour], -1, 255, cv2.FILLED)
has_innder_black_pixels = (thresh[tmp==255].min() == 0)

代码示例:

import numpy as np
import cv2

# Load the PNG image
img = cv2.imread('slice.png')

# Convert the image to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Threshold the image to create a binary image
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)

# Find the outer contours in the binary image (using cv2.RETR_EXTERNAL)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# Create a blank image with the same dimensions as the original image
filled_img = np.zeros(img.shape[:2], dtype=np.uint8)

# Fill the outer contour with white color
cv2.drawContours(filled_img, contours, -1, 255, cv2.FILLED)

# Find contours with hierarchy, this time use cv2.RETR_TREE
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# Iterate over the contours and their hierarchies
for i, contour in enumerate(contours):
    has_grandparent = False
    has_parent = hierarchy[0][i][3] >= 0
    if has_parent:
        # Check if contour has a grandparent
        parent_idx = hierarchy[0][i][3]
        has_grandparent = hierarchy[0][parent_idx][3] >= 0

    # Draw the contour over temporary image first (for testing if it has black pixels inside).
    tmp = np.zeros_like(thresh)
    cv2.drawContours(tmp, [contour], -1, 255, cv2.FILLED)
    has_innder_black_pixels = (thresh[tmp==255].min() == 0)  # If the minimum value is 0 (value where draw contour is white) then the contour has black pixels inside

    if hierarchy[0][i][2] < 0 and has_grandparent and has_innder_black_pixels:
        # If contour has no child and has a grandparent and it has black inside, fill the contour with black color
        cv2.drawContours(filled_img, [contour], -1, 0, cv2.FILLED)

# Display the result
cv2.imshow('Original Image', img)
cv2.imshow('Filled Regions', filled_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

填充轮廓但保留包​​含的区域未填充 的相关文章

随机推荐

  • 查询对象 mongoose 的嵌套数组

    我想在嵌套对象中查找带有 Alexa 的名称 操场 https mongoplayground net p rqYQtf0liaX https mongoplayground net p rqYQtf0liaX item journal i
  • 类型“Object”上不存在属性“json”

    我正在尝试使用 Angular 2 HttpClient 通过 REST 获取数据 我正在关注这里的角度教程https angular io tutorial toh pt6 https angular io tutorial toh pt
  • Woocommerce REST API - 添加自定义路由

    我有一家 Woocommerce 商店 我正在使用 Woocommerce REST API 在另一个网站上列出产品等 它工作正常 不过 我缺少一些功能 我想知道是否可以通过自定义调用来扩展 API 通过阅读 Woocommerce 的源代
  • 如何自动增加詹金斯构建号?

    如何自动增加 jenkins 内部版本号或使用 shell 脚本 现在我正在使用配置选项执行相同的操作 并手动增加 我想自动完成 您所要求的 即在多个作业之间保持内部版本号相同 很简单不可能的在詹金斯 这是通过设计完成的 正如 Jenkin
  • 过滤多列 Pandas

    我有一个将 pandas 数据框作为输入的方法 def dfColumnFilter df columnFilter columnName Returns a filtered DataFrame Keyword arguments df
  • 如何从 python 程序发送信号?

    我有这段代码可以监听 USR1 信号 import signal import os import time def receive signal signum stack print Received signum signal sign
  • 用于同步数组访问的最快 x86 汇编代码? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 同步访问内存中数组的最快 x86 汇
  • PHP 中具有不透明度的径向渐变

    我需要创建一个具有不透明度的 PNG 径向渐变 我浏览过 GDLib 但看不到生成径向渐变的方法 有谁知道使用 GDlib 或任何其他 PHP 图形库的方法吗 我想最坏的情况我可以使用 GDLib 逐像素生成它 但是如何开始对此进行数学计算
  • SQLAlchemy 模型 Django 喜欢保存方法吗?

    我正在一个项目中使用 sqlalchemy 不过 我更习惯Django的ORM 我想知道在 sqlalchemy ORM 中是否有类似于 Django 模型的 save 方法 我可以重写该方法以在 提交 保存 时自动实施操作 您可以使用一些
  • 无法获取 SoftwareComponentInternal - Maven 发布插件项目 gradle 的未知属性“release”

    我有一个包含多个模块的 Android 项目 我想将它们发布到自托管 Maven 存储库 我之前将发布代码存在于各个模块中 并且一切正常 我现在正在尝试将发布代码移至项目中build gradle这样我就可以重用该代码 我的各个模块内的代码
  • 在 pandas 中组合两个时间序列

    如果这明显记录在某处 我深表歉意 但我很难发现它 我有两个带有一些重叠日期 索引的 TimeSeries 我想合并它们 我假设我必须指定从两个系列中的哪一个获取重叠日期的值 为了说明我有 s1 2008 09 15 100 2008 10
  • 数据 URI 的用途是什么?

    为什么资源有时会嵌入到数据 URI 中 而不是使用链接到服务器上作为文件存储的资源的常规 URI 1 减少服务器请求 数据 URI 可用于通过减少获取资源所需的 HTTP 请求数量来减少服务器负载并提高客户端性能 例如 这个 HTML im
  • 注册媒体维基需要管理员批准吗?

    我维护的一个 wiki 受到了垃圾邮件机器人的严重打击 我们没有很多用户 而且我不想让合法用户背负验证码 有没有一种简单的方法可以让管理员确认注册 我浏览了手册 但无法弄清楚如何操作 您可以创建一个新用户权限 例如 批准 允许管理员分配该权
  • 如何在流上重用过滤器和映射的应用程序?

    我有一组从共享类型继承的域对象 即GroupRecord extends Record RequestRecord extends Record 子类型具有特定的属性 即GroupRecord getCumulativeTime Reque
  • 如何在 Android 中的 Activity 上强制执行自定义权限?

    我在android中创建了一个自定义权限
  • Python wand:具有透明度的合成图像

    我正在尝试用 Wand 合成两个图像 计划是将图像 B 放在 A 的右侧 并使 B 的透明度为 60 使用 IM 可以这样完成 composite blend 60 geometry 1000 0 b jpg a jpg new jpg 但
  • json对象访问

    我知道这很简单 但我坚持不下去 我有 json 变量 数据如下 var jsonText user Gender M Minage 19 Maxage 30 MaritalStatusId 0 user maritialtype Does
  • Google 应用程序引擎网站的多个域 - 每个域的分析

    好的 基本上我正在为我工 作的公司测试一种新的营销理念 购买 10 个左右的域名 其中包含与业务相关的关键搜索词 例如 carservice com carmot com hondaservice com 并将它们全部链接到一个网站 托管在
  • 训练 tesseract 后,tessdata 文件夹中应包含哪些文件?

    我使用 tesseract 作为我的 ANPR 应用程序的 OCR 引擎 我已经用车牌字体训练了 tesseract 3 01v 但我需要知道 tessdata 文件夹中应包含哪些文件 我应该使用安装 tesseract 3 01v 的同一
  • 填充轮廓但保留包​​含的区域未填充

    我有这个 python 代码 据说可以填充图像的轮廓 但其中包含的孔未填充 这就是我要的 但这就是我得到的 我尝试指定轮廓层次结构来填充 cv2 但我无法得到我想要的结果 这是我尝试过的 import numpy as np import