Meine anfängliche Aufgabe war die Segmentierung von Kernen aus einem beschnittenen Bereich eines 40-fachen Vergrößerungs-Slidescan. Viele Kerne berühren sich, manche überlappen sich potentiell. Ich begann mit dem Watershed-Algorithmus mit fairen Ergebnissen. Was ich jetzt tun möchte, ist vollständig zu beseitigen alle Konturen, die eine Grenze mit anderen Konturen teilen. Im Grunde sind alles, was mich interessiert, Konturen, die vollständig isoliert sind. Ich weiß, dass dies den Zweck des Watershed-Algorithmus zunichte macht, aber ich bin gespannt, wie dies durchgeführt werden würde. Hier ist der Code, mit dem ich arbeite. Vieles davon wurde von einer PY-Bildersuche article ausgeliehen.OpenCV gibt nur Konturen zurück, die keine Umrandung mit anderen Konturen haben
# USAGE
# python watershed.py --image images/coins_01.png
import argparse
import cv2
import numpy as np
import tifffile as tiff
from scipy import ndimage
# import the necessary packages
from skimage.feature import peak_local_max
from skimage.morphology import watershed
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True,
help="path to input image")
ap.add_argument("-m", "--min_distance", required=False, default=10, nargs="?", type=int,
help="minimum distance used for distance transformation")
args = vars(ap.parse_args())
# load the image and perform pyramid mean shift filtering
# to aid the thresholding step
filename = args["image"]
minimum_distance = args["min_distance"]
print("minimum distance is " + str(minimum_distance))
if filename.lower().endswith('.tif'):
image = tiff.imread(filename)
image = np.uint8(image)
image *= 1/256
else:
image = cv2.imread(args["image"])
shifted = cv2.pyrMeanShiftFiltering(image, 21, 51)
cv2.imshow("Input", image)
# convert the mean shift image to grayscale, then apply
# Otsu's thresholding
gray = cv2.cvtColor(shifted, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255,
cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv2.imshow("Thresh", thresh)
# compute the exact Euclidean distance from every binary
# pixel to the nearest zero pixel, then find peaks in this
# distance map
D = ndimage.distance_transform_edt(thresh)
localMax = peak_local_max(D, indices=False, min_distance=minimum_distance,
labels=thresh)
# perform a connected component analysis on the local peaks,
# using 8-connectivity, then apply the Watershed algorithm
markers = ndimage.label(localMax, structure=np.ones((3, 3)))[0]
labels = watershed(-D, markers, mask=thresh)
print("[INFO] {} unique segments found".format(len(np.unique(labels)) - 1))
# loop over the unique labels returned by the Watershed
# algorithm
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)[-2]
for idx, c in enumerate(cnts):
# compute the center of the contour
M = cv2.moments(c)
area = cv2.contourArea(c)
equi_diameter = np.sqrt(4 * area/np.pi)
arc_length = cv2.arcLength(c, closed=1)
perimeter_over_diameter = arc_length/equi_diameter
ellipse = cv2.fitEllipse(c)
center, axes, orientation = ellipse
major_axis_length = max(axes)
minor_axis_length = min(axes)
eccentricity = np.sqrt(1 - (minor_axis_length/major_axis_length) ** 2)
if 500 <= area <= 2000 and perimeter_over_diameter > 3.6 and eccentricity < 0.9:
if M["m00"] == 0:
M["m00"] = 1
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, (255, 0, 0), 2)
cv2.circle(image, (cX, cY), 3, (255, 255, 255), 1)
# show the output image
cv2.imwrite("dapi_segmented.png", image)
cv2.namedWindow("Output", cv2.WINDOW_NORMAL)
cv2.imshow("Output", image)
cv2.waitKey(0)
Mit anderen Worten, ich möchte nur die Konturen Kreise in rot zurückgegeben werden: