为了账号安全,请及时绑定邮箱和手机立即绑定

查找多个连接对象的每个质心

查找多个连接对象的每个质心

MYYA 2023-03-16 10:56:28
我是 python 编码的超级新手,需要一些帮助。我能够分割生物组织内的每个细胞轮廓(超酷!),现在我正尝试使用以下方法找到组织内每个细胞的质心:我正在使用这段代码:img = cv2.imread('/Users/kate/Desktop/SegmenterTest/SegmentedCells/Seg1.png')image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)thresh = cv2.threshold(image, 60, 255, cv2.THRESH_BINARY)[1]cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)cnts = imutils.grab_contours(cnts)# loop over the contoursfor c in cnts:    # compute the center of the contour    M = cv2.moments(c)    cX = int(M["m10"] / M["m00"])    cY = int(M["m01"] / M["m00"])    # draw the contour and center of the shape on the image    cv2.drawContours(image, [c], -1, (0, 255, 0), 2)    cv2.circle(image, (cX, cY), 7, (255, 255, 255), -1)    cv2.putText(image, "center", (cX - 20, cY - 20),        cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)    # show the image    cv2.imshow("Image", image)    cv2.waitKey(0)但是,当我使用这段代码时,它给出了整个对象的质心,而不是每个单独的对象都给出了这个。我不知道从这里去哪里,所以向正确的方向轻推将不胜感激!
查看完整描述

2 回答

?
DIEA

TA贡献1820条经验 获得超2个赞

您可以在您的案例中使用模块 scikit-image 中的函数regionprops 。这是我得到的。

//img1.sycdn.imooc.com//6412858e00012b8e03850350.jpg

这是我使用的代码。


import cv2

import matplotlib.pyplot as plt

from skimage import measure

import numpy as np


cells = cv2.imread('cells.png',0)


ret,thresh = cv2.threshold(cells,20,255,cv2.THRESH_BINARY_INV)



labels= measure.label(thresh, background=0)

bg_label = labels[0,0] 

labels[labels==bg_label] = 0 # Assign background label to 0


props = measure.regionprops(labels)


fig,ax = plt.subplots(1,1)

plt.axis('off')

ax.imshow(cells,cmap='gray')

centroids = np.zeros(shape=(len(np.unique(labels)),2)) # Access the coordinates of centroids

for i,prop in enumerate(props):

    my_centroid = prop.centroid

    centroids[i,:]= my_centroid

    ax.plot(my_centroid[1],my_centroid[0],'r.')


# print(centroids)

# fig.savefig('out.png', bbox_inches='tight', pad_inches=0)

plt.show()


祝你研究顺利!


查看完整回答
反对 回复 2023-03-16
?
POPMUISE

TA贡献1765条经验 获得超5个赞

问题

cv2.findContours使用具有几种不同“检索模式”的算法。这些会影响返回哪些轮廓以及返回方式。这记录在这里。这些作为 的第二个参数给出findContours。您的代码使用cv2.RETR_EXTERNALwhich 意味着findContours只会返回单独对象的最外层边框。

解决方案

将此参数更改为cv2.RETR_LIST将为您提供图像中的所有轮廓(包括最外层的边框)。这是最简单的解决方案。

例如

import cv2

import imutils


img = cv2.imread('/Users/kate/Desktop/SegmenterTest/SegmentedCells/Seg1.png')

image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

thresh = cv2.threshold(image, 60, 255, cv2.THRESH_BINARY)[1]


cnts = cv2.findContours(thresh.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

cnts = imutils.grab_contours(cnts)


# loop over the contours

for c in cnts:

    # compute the center of the contour

    M = cv2.moments(c)

    cX = int(M["m10"] / M["m00"])

    cY = int(M["m01"] / M["m00"])

    # draw the contour and center of the shape on the image

    cv2.drawContours(image, [c], -1, (0, 255, 0), 2)

    cv2.circle(image, (cX, cY), 7, (255, 255, 255), -1)

    cv2.putText(image, "center", (cX - 20, cY - 20),

        cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)

    # show the image

    cv2.imshow("Image", image)

    cv2.waitKey(0)

只选择最里面的对象

要可靠地忽略外部轮廓,您可以利用findContours返回它检测到的轮廓的层次结构的能力。为此,您可以再次将检索模式参数更改为RETR_TREE,这将生成完整的层次结构。

层次结构是一个数组,其中包含图像中每个轮廓的 4 个值的数组。每个值都是轮廓数组中轮廓的索引。从文档

对于每个第 i 个轮廓contours[i],元素hierarchy[i][0]、 hierarchy[i][1]hierarchy[i][2]hierarchy[i][3]分别设置为同一层级下一个和上一个轮廓、第一个子轮廓和父轮廓的轮廓中从 0 开始的索引。如果轮廓 i 没有下一个、上一个、父级或嵌套轮廓,则相应的元素 hierarchy[i]将为负数。

当我们说“最里面”时,我们的意思是没有孩子的轮廓(它们内部的轮廓)。所以我们想要那些在层次结构中的条目具有负的第三值的轮廓。也就是说, contours[i],使得hierarchy[i][2] < 0

一个小问题是,虽然findContours返回一个包含层次结构的元组,但imutils.grabContours会丢弃层次结构并仅返回轮廓数组。grabContours所有这一切意味着,如果我们打算使用不同版本的 OpenCV,我们必须自己完成工作。这只是一个简单的if else声明。

res = cv2.findContours(thresh.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)


# switch for different versions of OpenCV

if len(cnts) == 3:

    _, cnts, hierarchy = res

else:

    cnts, hierarchy = res

一旦你有了hierarchy,检查一个轮廓是否cnts[i]是“最里面的”可以用 完成hierarchy[0][i][2] < 0,这应该是False针对包含其他轮廓的轮廓。


基于您问题代码的完整示例:


import cv2

import imutils


img = cv2.imread('/Users/kate/Desktop/SegmenterTest/SegmentedCells/Seg1.png')

image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

thresh = cv2.threshold(image, 60, 255, cv2.THRESH_BINARY)[1]


cnts = cv2.findContours(thresh.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)


# switch for different versions of OpenCV

if len(cnts) == 3:

    _, cnts, hierarchy = cnts

else:

    cnts, hierarchy = cnts


# loop over the contours

for i, c in enumerate(cnts):

    # check that it is 'innermost'

    if hierarchy[0][i][2] < 0:

        # compute the center of the contour

        M = cv2.moments(c)

        cX = int(M["m10"] / M["m00"])

        cY = int(M["m01"] / M["m00"])


        # draw the contour and center of the shape on the image

        cv2.drawContours(image, [c], -1, (0, 255, 0), 2)

        cv2.circle(image, (cX, cY), 7, (255, 255, 255), -1)

        cv2.putText(image, "center", (cX - 20, cY - 20),

                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)

        # show the image

        cv2.imshow("Image", image)

        cv2.waitKey(0)


查看完整回答
反对 回复 2023-03-16
  • 2 回答
  • 0 关注
  • 86 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信