如何从 OpenCV 中已标记的图像中获取区域属性?

2023-12-07

我使用 OpenCV 中的分水岭算法来标记图像(类似于本教程:https://docs.opencv.org/3.4/d3/db4/tutorial_py_watershed.html)这样最后我获得了一个标签数组,其中每个区域都有一个与其标签相对应的整数值。现在,我想获取每个区域的边界框和面积的坐标。

我知道这很容易完成skimage.measure.regionprops()但出于执行速度的考虑,我希望在不导入skimage的情况下实现这一点,最好直接使用OpenCV。

我尝试过使用cv2.connectedComponentsWithStats()但它似乎只有在图像是二进制的情况下才起作用,而不是在标签已经定义的情况下才起作用。

我尝试对标记图像进行二值化,然后用connectedComponentsWithStats()如下(请注意,本例中背景的标签为 1,我想将其删除):

segmented = cv2.watershed(image.astype('uint8'), markers)

segmented_bin = segmented.copy()
segmented_bin[segmented < 2] = 0
segmented_bin[segmented > 1] = 255
num_labels, label_image, stats, centroids = cv2.connectedComponentsWithStats(segmented_bin.astype('uint8'), 4, cv2.CV_32S)

但这种方法合并了未被背景分隔的区域,这不是预期的效果。

本质上我想知道是否有类似的功能connectedComponentsWithStats()处理已经标记的图像?


由于(如果我没记错的话)每个标签代表一个连续区域,因此我们可以迭代所有非背景标签。

for i in range(2, marker_count + 1):

对于每个标签,我们可以使用以下命令创建相应的二进制掩码(具有该标签的像素变为 255,其他所有像素变为 0)numpy.where.

    mask = np.where(segmented==i, np.uint8(255), np.uint8(0))

Since cv2.boundingRect也可以处理单通道图像,我们可以用它直接从掩模确定边界框。

    x,y,w,h = cv2.boundingRect(mask)

标签的面积只是具有给定标签的像素的计数(即掩模中的所有非零像素)。我们可以简单地使用cv2.countNonZero为了那个原因。由于我们已经知道边界框,因此我们可以通过仅处理相应的 ROI 来节省一些工作。

    area = cv2.countNonZero(mask[y:y+h,x:x+w])

我们就完成了。

    print "Label %d at (%d, %d) size (%d x %d) area %d pixels" % (i,x,y,w,h,area)

控制台输出

Label 2 at (41, 14) size (47 x 49) area 1747 pixels
Label 3 at (111, 30) size (48 x 47) area 1719 pixels
Label 4 at (71, 51) size (56 x 48) area 1716 pixels
Label 5 at (152, 61) size (48 x 47) area 1676 pixels
Label 6 at (25, 75) size (47 x 48) area 1719 pixels
Label 7 at (109, 76) size (49 x 49) area 1748 pixels
Label 8 at (192, 82) size (49 x 48) area 1774 pixels
Label 9 at (64, 97) size (48 x 49) area 1695 pixels
Label 10 at (1, 114) size (47 x 48) area 1720 pixels
Label 11 at (139, 114) size (52 x 48) area 1727 pixels
Label 12 at (97, 132) size (48 x 48) area 1745 pixels
Label 13 at (181, 133) size (48 x 47) area 1667 pixels
Label 14 at (41, 140) size (47 x 48) area 1733 pixels
Label 15 at (129, 167) size (45 x 47) area 1666 pixels
Label 16 at (5, 169) size (50 x 48) area 1713 pixels
Label 17 at (72, 176) size (46 x 48) area 1745 pixels
Label 18 at (171, 177) size (50 x 49) area 1772 pixels
Label 19 at (35, 205) size (46 x 47) area 1702 pixels
Label 20 at (106, 207) size (55 x 49) area 1909 pixels
Label 21 at (155, 219) size (43 x 47) area 1537 pixels
Label 22 at (65, 237) size (51 x 48) area 1713 pixels
Label 23 at (25, 251) size (50 x 49) area 1818 pixels
Label 24 at (108, 264) size (48 x 47) area 1730 pixels
Label 25 at (155, 264) size (46 x 47) area 1711 pixels

Images

  • Input
    Input image
  • Colored labels
    Colored labels
  • Labeled bounding boxes
    Labeled bounding boxes

完整的脚本

import numpy as np
import cv2

# START of original watershed example
# from https://docs.opencv.org/3.4/d3/db4/tutorial_py_watershed.html

img = cv2.imread('water_coins.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

# noise removal
kernel = np.ones((3,3),np.uint8)
opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 2)
# sure background area
sure_bg = cv2.dilate(opening,kernel,iterations=3)
# Finding sure foreground area
dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,5)
ret, sure_fg = cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0)
# Finding unknown region
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg,sure_fg)

# Marker labelling
marker_count, markers = cv2.connectedComponents(sure_fg)
# Add one to all labels so that sure background is not 0, but 1
markers = markers+1
# Now, mark the region of unknown with zero
markers[unknown==255] = 0

segmented = cv2.watershed(img,markers)

# END of original watershed example

output = np.zeros_like(img)
output2 = img.copy()

# Iterate over all non-background labels
for i in range(2, marker_count + 1):
    mask = np.where(segmented==i, np.uint8(255), np.uint8(0))
    x,y,w,h = cv2.boundingRect(mask)
    area = cv2.countNonZero(mask[y:y+h,x:x+w])
    print "Label %d at (%d, %d) size (%d x %d) area %d pixels" % (i,x,y,w,h,area)

    # Visualize
    color = np.uint8(np.random.random_integers(0, 255, 3)).tolist()
    output[mask!=0] = color
    cv2.rectangle(output2, (x,y), (x+w,y+h), color, 1)
    cv2.putText(output2,'%d'%i,(x+w/4, y+h/2), cv2.FONT_HERSHEY_SIMPLEX, 0.4, color, 1, cv2.LINE_AA)

cv2.imwrite('wshseg_colors.png', output)
cv2.imwrite('wshseg_boxes.png', output2)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何从 OpenCV 中已标记的图像中获取区域属性? 的相关文章

  • 从 torch.autograd.gradcheck 导入 zero_gradients

    我想复制代码here https github com LTS4 DeepFool blob master Python deepfool py 并且我在 Google Colab 中运行时收到以下错误 ImportError 无法导入名称
  • DynamodB:如何更新排序键?

    该表有两个键 filename 分区键 和eventTime 排序键 我要更新eventTime对于某些filename Tried put item and update item 发送相同的filename与新的eventTime但这些
  • Python 不考虑 distutils.cfg

    我已经尝试了给出的所有内容 并且所有教程都指向相同的方向 即使用 mingw 作为 python 而不是 Visual C 中的编译器 我确实有 Visual C 和 mingw 当我想使用 pip 安装时 问题开始出现 它总是给Unabl
  • 如何找到多个 pandas 数据框中一对列与任意顺序对的交集?

    我有多个 pandas 数据框 为了简单起见 假设我有三个 gt gt df1 col1 col2 id1 A B id2 C D id3 B A id4 E F gt gt df2 col1 col2 id1 B A id2 D C id
  • 会话数据库表清理

    该表是否需要清除或者由 Django 自动处理 Django 不提供自动清除功能 然而 有一个方便的命令可以帮助您手动完成此操作 Django 文档 清除会话存储 https docs djangoproject com en dev to
  • 为什么opencv videowriter这么慢?

    你好 stackoverflow 社区 我有一个棘手的问题 我需要你的帮助来了解这里发生了什么 我的程序从视频采集卡 Blackmagic 捕获帧 到目前为止 它工作得很好 同时我用 opencv cv imshow 显示捕获的图像 它也工
  • 了解 Python 2.7 中的缩进错误

    在编写 python 代码时 我往往会遇到很多缩进错误 有时 当我删除并重写该行时 错误就会消失 有人可以为菜鸟提供 python 中 IndentationErrors 的高级解释吗 以下是我在玩 CheckIO 时收到的最近 inden
  • 无法通过 Android 应用程序访问我的笔记本电脑的本地主机

    因此 我在发布此内容之前做了一项研究 我发现的解决方案不起作用 更准确地说 连接到我的笔记本电脑的 IPv4192 168 XXX XXX 没用 连接到10 0 2 2 加上端口 不起作用 我需要测试使用 Django Rest 框架构建的
  • 如何从 python 脚本执行 7zip 命令

    我试图了解如何使用 os system 模块来执行 7zip 命令 现在我不想用 Popen 或 subprocess 让事情变得复杂 我已经安装了 7zip 并将 7zip exe 复制到我的用户文件夹中 我只想提取我的测试文件 inst
  • multiprocessing.Queue 中的 ctx 参数

    我正在尝试使用 multiprocessing Queue 模块中的队列 实施 https docs python org 3 4 library multiprocessing html exchang objects Between p
  • Flymake的临时文件可以在系统临时目录下创建吗?

    我目前正在使用以下代码在 emacs 中连接 Flymake 和 Pyflakes defun flymake create temp in system tempdir filename prefix make temp file or
  • 哪种方式最适合Python工厂注册?

    这是一个关于这些方法中哪一种被认为是最有效的问题 Pythonic 我不是在寻找个人意见 而是在寻找惯用的观点 我的背景不是Python 所以这会对我有帮助 我正在开发一个可扩展的 Python 3 项目 这个想法类似于工厂模式 只不过它是
  • Python:导入模块一次然后与多个文件共享

    我有如下文件 file1 py file2 py file3 py 假设这三个都使用 lib7 py lib8 py lib9 py 目前 这三个文件中的每一个都有以下行 import lib7 import lib8 import lib
  • Python脚本从字母和两个字母组合生成单词

    我正在编写一个简短的脚本 它允许我使用我设置的参数生成所有可能的字母组合 例如 b a 参数 单词 5 个字母 第三 第五个字母 b a 第一个字母 ph sd nn mm 或 gh 第二 第四个字母 任意元音 aeiouy 和 rc 换句
  • 如何创建增量加载网页

    我正在编写一个处理大量数据的页面 它会永远持续到我的结果页面加载 几乎无限 因为返回的数据太大了 因此 我需要实现一个增量加载页面 例如 url 中的页面 http docs python org http docs python org
  • 类返回语句不打印任何输出

    我正在学习课程 但遇到了问题return语句 它是语句吗 我希望如此 程序什么也没有打印出来 它只是结束而不做任何事情 class className def createName self name self name name def
  • 如何将两列 pandas Dataframe 移动并堆叠为一列?

    我有一个下面提到的数据框 ETHNIC SEX USUBJID 0 HISPANIC OR LATINO F 16 1 HISPANIC OR LATINO M 8 2 HISPANIC OR LATINO Total 24 3 NOT H
  • AWS 将 MQTT 消息存储到 DynamoDB

    我构建了一个定期发送 MQTT 消息的 python 脚本 这是发送到后端的 JSON 字符串 Id 1234 Ut 1488395951 Temp 22 86 Rh 48 24 在后端 我想将 MQTT 消息存储到 DynamoDB 表中
  • PyQt5按钮lambda变量变成布尔值[重复]

    这个问题在这里已经有答案了 当我运行下面的代码时 它显示如下 为什么 x 不是 x 而是变成布尔值 这种情况仅发生在传递到用 lambda 调用的函数中的第一个参数上 错误的 y home me model some file from P
  • 超过两个点的Python相对导入

    是否可以使用路径中包含两个以上点的模块引用 就像这个例子一样 Project structure sound init py codecs init py echo init py nix init py way1 py way2 py w

随机推荐