Я пытаюсь отделить лейкоциты от необработанного изображения, используя алгоритм водораздела. я хотел бы сохранить ROI или boundingbox как новое изображение после процесса сегментации, но я не знаю, как это сделать в python
Вот мой основной код
import numpy as np
import cv2
from matplotlib import pyplot as plt
import matplotlib.image as mpimg
from skimage.morphology import extrema
from skimage.morphology import watershed as skwater
def ShowImage(title,img,ctype):
if ctype=='bgr':
b,g,r = cv2.split(img) # get b,g,r
rgb_img = cv2.merge([r,g,b]) # switch it to rgb
plt.imshow(rgb_img)
elif ctype=='hsv':
rgb = cv2.cvtColor(img,cv2.COLOR_HSV2RGB)
plt.imshow(rgb)
elif ctype=='gray':
plt.imshow(img,cmap='gray')
elif ctype=='rgb':
plt.imshow(img)
else:
raise Exception("Unknown colour type")
plt.title(title)
plt.show()
img=cv2.imread('29-39.jpg')
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ShowImage('Color Threshold',img,'bgr')
cell_hsvmin = (120,100,100) #Lower end of the HSV range defining the nuclei
cell_hsvmax = (155,255,255) #Upper end of the HSV range defining the nuclei
#Transform image to HSV color space
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
#Threshold based on HSV values
color_thresh = cv2.inRange(hsv, cell_hsvmin, cell_hsvmax)
#ShowImage('Color Threshold',color_thresh,'gray')
'''
masked = cv2.bitwise_and(img,img, mask=color_thresh)
ShowImage('Color Threshold Maksed',masked,'bgr')'''
kernel = np.ones((8,8),np.uint8)
opening = cv2.morphologyEx(color_thresh,cv2.MORPH_OPEN, kernel, iterations = 2)
#ShowImage('Opening',opening,'gray')
'''
fraction_foreground = 0.6
dist = cv2.distanceTransform(opening,cv2.DIST_L2,5)
ret, sure_fg = cv2.threshold(dist,fraction_foreground*dist.max(),255,0)
ShowImage('Distance',dist_transform,'gray')
ShowImage('Surely Foreground',sure_fg,'gray')'''
#Identify areas which are surely foreground
h_fraction = 0.1
dist = cv2.distanceTransform(opening,cv2.DIST_L2,5)
maxima = extrema.h_maxima(dist, h_fraction*dist.max())
print("Peaks found: {0}".format(np.sum(maxima)))
#Dilate the maxima so we can see them
maxima = cv2.dilate(maxima, kernel, iterations=2)
ShowImage('Distance',dist,'gray')
ShowImage('Surely Foreground',maxima,'gray')
# Finding unknown region
unknown = cv2.subtract(opening,maxima)
#ShowImage('Unknown',unknown,'gray')
# Marker labelling
ret, markers = cv2.connectedComponents(maxima)
ShowImage('Connected Components',markers,'rgb')
# 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==np.max(unknown)] = 0
ShowImage('markers',markers,'rgb')
dist = cv2.distanceTransform(opening,cv2.DIST_L2,5)
labels = skwater(-dist,markers,watershed_line=True)
ShowImage('Watershed',labels,'rgb')
"""imgout = img.copy()
imgout[markers == 0] = [0,0,255] #Label the watershed_line
ShowImage('img',imgout,'bgr')
"""
print("[INFO] {} unique segments found".format(len(np.unique(labels)) - 1))
def grab_contours(cnts):
# if the length the contours tuple returned by cv2.findContours
# is '2' then we are using either OpenCV v2.4, v4-beta, or
# v4-official
if len(cnts) == 2:
cnts = cnts[0]
# if the length of the contours tuple is '3' then we are using
# either OpenCV v3, v4-pre, or v4-alpha
elif len(cnts) == 3:
cnts = cnts[1]
# otherwise OpenCV has changed their cv2.findContours return
# signature yet again and I have no idea WTH is going on
else:
raise Exception(("Contours tuple must have length 2 or 3, "
"otherwise OpenCV changed their cv2.findContours return "
"signature yet again. Refer to OpenCV's documentation "
"in that case"))
# return the actual contours array
return cnts
for label in np.unique(labels):
# if the label is zero, we are examining the 'background'
# so simply ignore it
if label == 0:
continue
# otherwise, allocate memory for the label region and draw
# it on the mask
mask = np.zeros(gray.shape, dtype="uint8")
mask[labels == label] = 255
# detect contours in the mask and grab the largest one
cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnts = grab_contours(cnts)
c = max(cnts, key=cv2.contourArea)
# draw a circle enclosing the object
((x, y), r) = cv2.minEnclosingCircle(c)
cv2.circle(img, (int(x), int(y)), int(r), (0, 255, 0), 2)
cv2.putText(img, "#{}".format(label), (int(x) - 10, int(y)),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
источник и результирующее изображение вот так . мне нужно отделить каждую метку (# 1, # 2, # 3 и т. д.) как новое изображение
Как можно решить эти проблемы? Большое спасибо за вашу помощь.