Finding each centroid of multiple connected objects

和自甴很熟 提交于 2020-07-23 06:45:16

问题


I am SUPER new to python coding and would like some help. I was able to segment each cell outline within a biological tissue (super cool!) and now I am trying to find the centroid of each cell within a tissue using this:

I am using this code:

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 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)

However, when I use this code, it is giving me the centroid of the ENTIRE object, and not each individual object to give this.

I have no idea where to go from here, so a nudge in the right direction would be greatly appreciated!


回答1:


You can use the function regionprops from the module scikit-image in your case. Here is what I got.

This is the code I used.

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()

Good luck with your research!




回答2:


Problem

cv2.findContours uses an algorithm which has a few different 'retrieval modes'. These affect which contours are returned and how they are returned. This is documented here. These are given as the second argument to findContours. Your code uses cv2.RETR_EXTERNAL which means findContours will only return the outermost border of separate objects.

Solution

Changing this argument to cv2.RETR_LIST will give you all the contours in the image (including the one outermost border). This is the simplest solution.

E.g.

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)


来源:https://stackoverflow.com/questions/62969818/finding-each-centroid-of-multiple-connected-objects

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!