2 回答

TA貢獻1820條經驗 獲得超2個贊
您可以在您的案例中使用模塊 scikit-image 中的函數regionprops 。這是我得到的。
這是我使用的代碼。
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()
祝你研究順利!

TA貢獻1765條經驗 獲得超5個贊
問題
cv2.findContours
使用具有幾種不同“檢索模式”的算法。這些會影響返回哪些輪廓以及返回方式。這記錄在這里。這些作為 的第二個參數給出findContours
。您的代碼使用cv2.RETR_EXTERNAL
which 意味著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)
添加回答
舉報