def test_cwatershed(): S = np.array([ [0,0,0,0], [0,1,2,1], [1,1,1,1], [0,0,1,0], [1,1,1,1], [1,2,2,1], [1,1,2,2] ]) M = np.array([ [0,0,0,0], [0,0,1,0], [0,0,0,0], [0,0,0,0], [0,0,0,0], [0,2,0,0], [0,0,0,0], ]) W = pymorph.cwatershed(2-S,M) assert np.all(W == np.array([[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [2, 2, 1, 1], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2]]))
def colorscheme(url): im=image_read(url) pylab.imshow(im) dnaf = ndimage.gaussian_filter(im, 1) rmax = pymorph.regmax(dnaf) seeds,nr_nuclei = ndimage.label(rmax) T = mahotas.thresholding.otsu(dnaf) dist = ndimage.distance_transform_edt(dnaf > T) dist = dist.max() - dist dist -= dist.min() dist = dist/float(dist.ptp()) * 255 dist = dist.astype(np.uint8) nuclei = pymorph.cwatershed(dist, seeds) whole = mahotas.segmentation.gvoronoi(nuclei) im0=pylab.imshow(whole) pylab.show()
def watershed(img): # Diminui ruidos imgf = ndimage.gaussian_filter(img, 16) mahotas.imsave("dnaf.jpeg", imgf) rmax = pymorph.regmax(imgf) T = mahotas.thresholding.otsu(imgf) dist = ndimage.distance_transform_edt(imgf > T) dist = dist.max() - dist dist -= dist.min() dist = dist / float(dist.ptp()) * 255 dist = dist.astype(np.uint8) mahotas.imsave("dist.jpeg", dist) seeds, nr_nuclei = ndimage.label(rmax) nuclei = pymorph.cwatershed(dist, seeds) mahotas.imsave("watershed.jpeg", nuclei)
def start(self): """Segment frame. The returned value is a labeled uint16 image. """ # Preprocessing: subtract minimum pixel value. I = self._image - self._image.min() # 'Bandpass' filtering. I_s = ndimage.filters.gaussian_filter(I, self._sigma_s) # Foreground. I_b = ndimage.filters.gaussian_filter(I, self._sigma_b) # Background. I_bp = I_s - self._alpha * I_b # Thresholding: create binary image. I_bin = (I_bp > self._tau) # Hole filling. I_bin = ndimage.binary_fill_holes(I_bin > 0) I_cells = ndimage.label(I_bin)[0] # Avoid merging nearby cells using watershed. if self._watershed: # Distance transfrom on which to apply the watershed algorithm. I_dist = ndimage.distance_transform_edt(I_bin) I_dist = I_dist/float(I_dist.max()) * 255 I_dist = I_dist.astype(np.uint8) # Find markers for the watershed algorithm. # Reduce false positive using Gaussian smoothing. I_mask = ndimage.filters.gaussian_filter(I_dist, 8)*I_bin rmax = pymorph.regmax(I_mask) I_markers, num_markers = ndimage.label(rmax) I_dist = I_dist.max() - I_dist # Cells are now the basins. I_cells = pymorph.cwatershed(I_dist, I_markers) # Remove cells with area less than threshold. if self._a_min: for label in np.unique(I_cells)[1:]: if (I_cells == label).sum() < self._a_min: I_cells[I_cells == label] = 0 # Remove cells with summed intensity less than threshold. if self._s_min: for label in np.nditer(np.unique(I_cells)[1:]): if I_bp[I_cells == label].sum() < self._s_min: I_cells[I_cells == label] = 0 return I_cells.astype('uint16') # This data type is used by ISBI.
def effect(url): im=image_read(url) pylab.imshow(im) dnaf = ndimage.gaussian_filter(im, 1) rmax = pymorph.regmax(dnaf) T = mahotas.thresholding.otsu(dnaf) seeds,nr_nuclei = ndimage.label(rmax) T = mahotas.thresholding.otsu(dnaf) T = mahotas.thresholding.otsu(dnaf) dist = ndimage.distance_transform_edt(dnaf > T) dist = dist.max() - dist dist -= dist.min() dist = dist/float(dist.ptp()) * 255 dist = dist.astype(np.uint8) nuclei = pymorph.cwatershed(dist, seeds) pylab.imshow(nuclei) # pylab.save("out.png") pylab.show()
def MNUC(datatype, maxrange, outputfile, outputfiletype): h = open(outputfile, outputfiletype) TC = 0 for i in range(0, maxrange + 1): A = datatype[i][0] rmax = pymorph.regmax(A) seeds, nr_nuclei = ndimage.label(rmax) T = mahotas.thresholding.otsu(A) C = A.copy() if T < 1: C[ C <= T ] = 0 C[ C > T ] = 1 else: C[ C < T ] = 0 C[ C >= T ] = 1 filled = scipy.ndimage.morphology.binary_fill_holes(C) filled = filled.astype(np.uint8) dist = ndimage.distance_transform_edt(filled > T) dist = dist.max() - dist dist -= dist.min() dist = dist/float(dist.ptp()) * 255 dist = dist.astype(np.uint8) nuclei = pymorph.cwatershed(dist, seeds) find = mahotas.label(nuclei) for n in range(0, find[1] + 1): CD = np.where(find[0] == n) XY1 = np.vstack((CD[0], CD[1])) edges = filter.canny(XY1, sigma=1) edges = edges.astype(np.uint8) edges = np.where(edges == 1) TC += len(CD[0]) XY1 = np.vstack((CD[0], CD[1], [i*5]*len(CD[0]), [n]*len(CD[0]))) for p in range(0, len(XY1[0])): for yel in range(0, len(XY1)): h.write(str(XY1[yel][p]) + '\t') h.write('\n') h.write(str(TC) + '\n') h.write('.' + '\n') h.close()
def watershedimage(self): """Watershed and extract region centers of mass""" # Generate distribution transform first. self.distimage() if not hasattr(self, "labels"): self.labelimage() # Load regions if available (takes a bit). if not self.load_archive("nps"): self.nps = pymorph.cwatershed(self.dist, self.labels, Bc=numpy.ones((3,3), dtype=bool)) if not self.load_archive("coms"): self.coms = numpy.array(ndimage.center_of_mass(self.filtered, self.nps, range(1,self.nlabels+1))) self.regcom = numpy.zeros(self.img.shape, dtype="uint8") for icom,com in enumerate(self.coms): self.regcom[round(com[0]),round(com[1])] = 1 self.npcount = len(self.coms) self.npconc = 10.0**6*self.npcount/self.area
def runWatershed(arr,seeds): return pymorph.cwatershed(arr,seeds)
pylab.show() writeimg(pymorph.overlay(dna, rmax), 'dnaf-16-rmax-overlay.jpeg') seeds, nr_nuclei = ndimage.label(rmax) print nr_nuclei T = pit.thresholding.otsu(dnaf) dist = ndimage.distance_transform_edt(dnaf > T) dist = dist.max() - dist dist = ((dist - dist.min()) / float(dist.ptp()) * 255).astype(np.uint8) pylab.imshow(dist) pylab.show() savejet(dist, 'dnaf-16-dist.jpeg') nuclei = pymorph.cwatershed(dist, seeds) pylab.imshow(nuclei) pylab.show() savejet(nuclei, 'nuclei-segmented.png') whole = pit.segmentation.gvoronoi(nuclei) pylab.imshow(whole) pylab.show() savejet(whole, 'whole-segmented.png') borders = np.zeros(nuclei.shape, np.bool) borders[0, :] = 1 borders[-1, :] = 1 borders[:, 0] = 1 borders[:, -1] = 1 at_border = np.unique(nuclei[borders])
def _segment(self, I, first): """Return the segmented frame 'I'. If 'first is True, then this is the first segmentation iteration, otherwise the second. The returned value is a labeled image of type uint16, in order to be compatible with ISBI's tool. """ # Compute global threshold. otsu_thresh = mh.thresholding.otsu(I.astype('uint16')) # Threshold using global and local thresholds. fnc = fnc_class(I.shape) I_bin = ndimage.filters.generic_filter(I, fnc.filter, size=self._r, extra_arguments=(I, self._min_var, otsu_thresh)) I_med = ndimage.filters.median_filter(I_bin, size=self._r_med) # Remove cells which are too small (leftovers). labeled = mh.label(I_med)[0] sizes = mh.labeled.labeled_size(labeled) too_small = np.where(sizes < self._a_min) I_cleanup = mh.labeled.remove_regions(labeled, too_small) I_cleanup = mh.labeled.relabel(I_cleanup)[0] # Fill holes. I_holes = ndimage.morphology.binary_fill_holes(I_cleanup > 0) # Binary closing. if first and self._r1: # First iteration. I_morph = morph.binary_closing(I_holes, morph.disk(self._r1)) elif not first and self._r2: # Second iteration. I_morph = morph.binary_closing(I_holes, morph.disk(self._r2)) else: # No binary closing. I_morph = I_holes # Fill yet to be filled holes. labels = measure.label(I_morph) labelCount = np.bincount(labels.ravel()) background = np.argmax(labelCount) I_morph[labels != background] = True # Separate touching cells using watershed. # Distance transfrom on which to apply the watershed algorithm. I_dist = ndimage.distance_transform_edt(I_morph) I_dist = I_dist/float(I_dist.max()) * 255 I_dist = I_dist.astype(np.uint8) # Find markers for the watershed algorithm. # Reduce false positive using Gaussian smoothing. I_mask = ndimage.filters.gaussian_filter(I_dist, 8)*I_morph rmax = pymorph.regmax(I_mask) I_markers, _ = ndimage.label(rmax) I_dist = I_dist.max() - I_dist # Cells are now the basins. I_label = pymorph.cwatershed(I_dist, I_markers) if self._debug: plt.subplot(2, 4, 1) plt.imshow(I) plt.title('Original Image') plt.subplot(2, 4, 2) plt.imshow(I_bin) plt.title('After Thresholding') plt.subplot(2, 4, 3) plt.imshow(I_med) plt.title('After Median Filter') plt.subplot(2, 4, 4) plt.imshow(I_cleanup) plt.title('After Cleanup') plt.subplot(2, 4, 5) plt.imshow(I_holes) plt.title('After Hole Filling') plt.subplot(2, 4, 6) plt.imshow(I_morph) plt.title('After Closing') plt.subplot(2, 4, 7) plt.imshow(I_label) plt.title('Labeled Image') plt.show() return I_label.astype('uint16')
def main(): # Load and show original images pylab.gray() # set gray scale mode print print "0. Reading and formatting images..." images = {f: loadAndFormat(f) for f in IMAGE_FILES} for f in IMAGE_FILES: mShow(images[f]) ########################### # -----> Thresholding print print "1. Thresholding images..." thresholdedImages = {f: getThresholdedImage(images[f]) for f in IMAGE_FILES} for name in IMAGE_FILES: mShow(thresholdedImages[name]) ########################### # -----> Count objects # 1st attempt: label the thresholded image from task 1 print print "2. Object counting" pylab.jet() # back to color mode print "\t1st approach: Label thresholded images" for name in IMAGE_FILES: labeled, nrRegions = ndimage.label(thresholdedImages[name]) print "\t" + name + ": " + str(nrRegions) mShow(labeled) # 2nd attempt: Changing threshold level print print "\t2nd approach: Tuned thresholds" # For 'objects.png' some objects are very small (e.g.: screw) or # have many shades (e.g.: spoon) which makes them disappear or appear # fragmented after thresholding. # The advantage of this image is that the background is very dark, # so we can try using a lower threshold to make all shapes more definite objImage = images['objects.png'] T = mahotas.thresholding.otsu(objImage) thresholdedImage = objImage > T * 0.7 # Looks better, but... labeled, nrRegions = ndimage.label(thresholdedImage) print '\tobjects.png' + ": " + str(nrRegions) # it returns 18! # 3rd attempt: Smoothing before thresholding print print "\t3rd approach: Smoothing + Tuned threshold" # Let's apply some Gaussian smoothing AND a lower threshold smoothImage = ndimage.gaussian_filter(objImage, 3) T = mahotas.thresholding.otsu(smoothImage) thresholdedImage = smoothImage > T * 0.7 labeled, nrRegions = ndimage.label(thresholdedImage) print '\tobjects.png' + ": " + str(nrRegions) # it worked! Let's save the labeled images for later # (we will use them for center calculation) labeledImages = {} labeledImages['objects.png'] = (labeled, nrRegions) mShow(labeled) # Let's see if this approach works on the other images for name in ['circles.png', 'peppers.png']: img = images[name] smoothImage = ndimage.gaussian_filter(img, 3) T = mahotas.thresholding.otsu(smoothImage) thresholdedImage = smoothImage > T * 0.7 labeled, nrRegions = ndimage.label(thresholdedImage) print '\t' + name + ": " + str(nrRegions) # Again no luck with the circles! # (We will take a closer look at the peppers later) # 4th attempt: # 'circles.png': The problem is that some circles appear "glued together". # Let's try another technique: # - smoothing the picture with a Gaussian filter # - then searching for local maxima and counting regions # (smoothing avoids having many scatter maxima and a higher level # must be used than in the previous attempt) # - use watershed with the maxima as seeds over the thresholded image # to complete the labelling of circles print print "\t4th approach: Smoothing + Local maxima + Watershed" smoothImage = ndimage.gaussian_filter(images['circles.png'], 10) localmaxImage = pymorph.regmax(smoothImage) # A distance transform must be applied before doing the watershed dist = ndimage.distance_transform_edt(thresholdedImages['circles.png']) dist = dist.max() - dist dist -= dist.min() dist = dist / float(dist.ptp()) * 255 dist = dist.astype(np.uint8) seeds, nrRegions = ndimage.label(localmaxImage) labeled = pymorph.cwatershed(dist, seeds) print "\t" + 'circles.png' + ": " + str(nrRegions) # worked right only for 'circles.png' ! labeledImages['circles.png'] = (labeled, nrRegions) mShow(labeled) print print "\t5th approach: Smoothing + Multi-threshold +" +\ " Morphology labeling + Size filtering" # 5th approach (only peppers left!) imagePeppers = images['peppers.png'] # Problems with peppers are: # - very different colours, they cause thresholding to work poorly # - each pepper has some brighter parts which are detected as local maxima # We propose to address those issues as follows: # - gaussian filter to smooth regions of light or shadow within each pepper smoothImage = ndimage.gaussian_filter(imagePeppers, 2) # - instead of thresholding to create a binary image, # create multiple thresholds to separate the most frequent colors. # In this case, 3 thresholds will be enough mthrImagePeppers = multiThreshold(smoothImage, 3) # - ndimage.label didn't give good results, we try another # labelling algorithm from skimage import morphology labeled = morphology.label(mthrImagePeppers) nrRegions = np.max(labeled) + 1 print "\t\tTotal number of regions" print "\t\t\t" + 'peppers.png' + ": " + str(nrRegions) # - after counting regions, filter to keep only the sufficiently big ones filtered, nrRegions = filterRegions(labeled, 0.05) print "\t\tBig enough regions" print "\t\t\t" + 'peppers.png' + ": " + str(nrRegions) labeledImages['peppers.png'] = (filtered, nrRegions) mShow(filtered) ########################### # -----> Find center points print print "3. Centers for objects" for img in IMAGE_FILES: labeledImage, nr_objects = labeledImages[img] CenterOfMass = ndimage.measurements.center_of_mass labels = range(1, nr_objects + 1) centers = CenterOfMass(labeledImage, labeledImage, labels) centers = [(int(round(x)), int(round(y))) for (x, y) in centers] print '\t' + img + ": " + str(centers)
pylab.imshow(pymorph.overlay(dna, rmax)) seeds,nr_nuclei = ndimage.label(rmax) print nr_nuclei # prints 22 # Watershed to distance transform of threshold T = mahotas.thresholding.otsu(dnaf) dist = ndimage.distance_transform_edt(dnaf > T) dist = dist.max() - dist dist -= dist.min() dist = dist/float(dist.ptp()) * 255 dist = dist.astype(np.uint8) pylab.imshow(dist) pylab.show() nuclei = pymorph.cwatershed(dist, seeds) pylab.imshow(nuclei) pylab.show() # Extend segmentation to whole plane using generalized voronoi - each px -> nearest nucleus whole = mahotas.segmentation.gvoronoi(nuclei) pylab.imshow(whole) pylab.show() # Quality control - remove cells whose nucleus touches border borders = np.zeros(nuclei.shape, np.bool) # builds an array of zeroes with nuclei shape and np.bool borders[ 0,:] = 1 borders[-1,:] = 1 borders[:, 0] = 1 borders[:,-1] = 1 # Sets borders of array to 1/True at_border = np.unique(nuclei[borders]) # nuclei[borders] gets True borders, unique returns only unique values
import ImageEnhance I_contrast = pow(I_show.astype("uint16"), 3) #find regional maxima regionalMax = pymorph.regmax((I_contrast).astype("uint16")) #find seeds and cell number seeds,numCells = ndimage.label(regionalMax) print numCells #edge detection T = mahotas.thresholding.otsu(I_contrast.astype("uint16")) dist = ndimage.distance_transform_edt(I_contrast.astype("uint16") > T) dist = dist.max() - dist dist -= dist.min() dist = dist/float(dist.ptp()) * 255 dist = dist.astype(np.uint8) #watershed I_mask = pymorph.cwatershed(dist, seeds) frames, x, y = Is.shape label_mask, num_cells = ndimage.label(I_mask.astype(bool)) print frames print num_cells traces = np.zeros((frames, num_cells)) baselined_traces = np.zeros_like(traces) normed_traces = np.zeros_like(traces) for cell in range(1,num_cells): traces[:,cell] = Is[:,label_mask==cell].mean(axis=1) print "Found %d unique cells" % traces.shape[1] print traces