def plot(imag): # Invert the horse image # image = plt.imread("cheval.png", 'L')/255 image = rgb_to_gray(1 - plt.imread(imag)) print(image.shape) print(image[100:105, 115:117]) print(type(image)) # perform skeletonization # skeleton = skeletonize(image) skeleton = local_maxima(image) # display results fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(8, 4), sharex=True, sharey=True, subplot_kw={'adjustable': 'box'}) ax = axes.ravel() ax[0].imshow(image, cmap=plt.cm.gray) ax[0].axis('off') ax[0].set_title('original', fontsize=20) ax[1].imshow(skeleton, cmap=plt.cm.gray) ax[1].axis('off') ax[1].set_title('skeleton', fontsize=20) fig.tight_layout() plt.show()
def pmwatershed(I,estRad,smCoef,fgThr,frg): fwhm = estRad # full width at half maximum sigma = fwhm/2.355 J = imlogfilt(I,sigma) S = imgaussfilt(I,smCoef) M = S > fgThr diskCoef = (1-frg)*fwhm/4+frg d = disk(2*int(diskCoef)+1) lm = local_maxima(J,selem=d)*M markers = label(lm) labels = watershed(-S, markers[0], mask=M, watershed_line=True) return labels > 0
def _get_nucleation_points(self, image): """Set distance and angle thresholds for fibre iterator""" # Get global maxima for smoothed distance matrix maxima = local_maxima(image, connectivity=self.nuc_radius, allow_borders=True) nuc_node_coord = reduce_coord( np.argwhere(maxima * image >= self.nuc_thresh), image[np.where(maxima * image >= self.nuc_thresh)], self.r_thresh) return nuc_node_coord
def _peak_search_skimage(image, **kwargs): '''Default peak detection method: skimage.morphology.get_m**ima (either minima or maxima) Since skimage doesn't handle masked arrays, the masking is a bit of a bodge job here. The basic plan is as follows: * Set the area of the image covered by the mask to a value that cannot include a maxima (or minima, as appropriate) * Search for peak coordinates * Check if, after rounding, any of the peaks are outside the image dimensions * Check if, after rounding, any of the peaks are extremely close to the mask Since the mask is a ahrd-edged area, if there is even a slight rise just outside it, spurious peaks can be detected. Therefore, we automatically reject any peaks for a short distance outside the actual mask ''' connectivity = 2 get_maxima = kwargs.get("maxima", True) mask = kwargs.get("mask", np.zeros(image.shape, dtype=bool)) image_copy = image.copy() if get_maxima: image_copy[mask] = np.nanmin(image_copy) regionalMaxMap = morphology.local_maxima(image_copy, connectivity=connectivity, allow_borders=True) else: image_copy[mask] = np.nanmax(image_copy) regionalMaxMap = morphology.local_minima(image_copy, connectivity=connectivity, allow_borders=True) labelled_max = measure.label(regionalMaxMap, connectivity=connectivity) regions = measure.regionprops(labelled_max) peak_coords = np.zeros(shape=(len(regions), 2), dtype=np.int) distance_from_mask = distance_transform_cdt(image_copy * (1 - mask)) for i, props in enumerate(regions): y0, x0 = props.centroid peak = np.array([y0, x0]) # ensure that there are no peaks off the map (due to rounding) peak[peak < 0] = 0 for j in range(image_copy.ndim): if peak[j] > image_copy.shape[j]: peak[j] = image_copy.shape[j] - 1 peak_index = tuple( np.round(peak, 0).astype(int) ) # indexing with a floating point array sucks, so convert to a more convenient form if distance_from_mask[peak_index] > 2 * connectivity: peak_coords[i, :] = peak return peak_coords
def Mask_Galaxies(data, lim): limg = np.arcsinh(data) limg_N = limg / limg.max() #print (max(limg_N.flatten())) for i in range(0,len(limg_N[0])): for j in range(0,len(limg_N)): if limg_N[j][i] < lim : limg_N[j][i] =0 #low = np.percentile(limg_N, low_percentile) #high = np.percentile(limg_N, high_percentile) #opt_img = skie.exposure.rescale_intensity(limg_N, in_range=(low,high)) lm = morph.local_maxima(limg_N) x1, y1 = np.where(lm.T == True) return limg,limg_N, (x1,y1)
def new_branches(image, coord, ring_filter, max_thresh=0.2): """Find local maxima in image within max_thresh of coord, excluding pixels in ring filter""" filtered = image * ring_filter branch_coord = np.argwhere( local_maxima(filtered) * image >= max_thresh) branch_coord = reduce_coord( branch_coord, image[branch_coord[:, 0], branch_coord[:, 1]]) n_branch = branch_coord.shape[0] branch_vector = np.tile(coord, (n_branch, 1)) - branch_coord branch_r = np.sqrt(np.sum(branch_vector**2, axis=1)) return branch_coord, branch_vector, branch_r
def accumfindcenters(self,acc, senstivity): accumMatrix = np.absolute(acc) # accumulator array sigma = 0.5 kernel = int(2*np.ceil(2*sigma)+1) accumMatrix = cv2.GaussianBlur(accumMatrix , (kernel,kernel),sigmaX=0.5) senstivity = 0.93 # default Hd = cv2.medianBlur(accumMatrix.astype('float32'),5) accumThresh = 1-senstivity suppThreshold = np.max(accumThresh- np.spacing(accumThresh),0) Hd = extrema.h_maxima(Hd, suppThreshold) bw = (local_maxima(Hd)).astype(int) label_img = label(bw, connectivity=bw.ndim) s = regionprops(label_img, intensity_image=accumMatrix) center = np.empty([len(s),2]) metric = np.empty([len(s),1]) for index,i in enumerate(s): center[index] = tuple((np.array(s[index].centroid)).astype(int)) metric[index] = Hd[tuple((np.array(s[index].centroid)).astype(int))] return center, metric
def extract_seeds(seedImageStackIn: np.ndarray) -> np.ndarray: """Determine seed positions from the input images. The initial seeds are determined by finding the regional intensity maximums after erosion and filtering with an adaptive threshold. These initial seeds are then expanded by dilation. Args: seedImageStackIn: a 3 dimensional numpy array arranged as (z,x,y) Returns: a boolean numpy array with the same dimensions as seedImageStackIn where a given (z,x,y) coordinate is True if it corresponds to a seed position and false otherwise. """ seedImages = seedImageStackIn.copy() seedImages = ndimage.grey_erosion( seedImages, footprint=ndimage.morphology.generate_binary_structure(3, 1)) seedImages = np.array([ cv2.erode(x, diskStruct, borderType=cv2.BORDER_REFLECT) for x in seedImages ]) thresholdFilterSize = int(2 * np.floor(seedImages.shape[1] / 16) + 1) seedMask = np.array([ x < 1.1 * filters.threshold_local( x, thresholdFilterSize, method='mean', mode='nearest') for x in seedImages ]) seedImages[seedMask] = 0 seeds = morphology.local_maxima(seedImages, allow_borders=True) seeds = ndimage.morphology.binary_dilation( seeds, structure=ndimage.morphology.generate_binary_structure(3, 1)) seeds = np.array([ ndimage.morphology.binary_dilation( x, structure=morphology.diamond(28)[9:48, 9:48]) for x in seeds ]) return seeds
# Generate an initial image with two overlapping circles x, y = np.indices((80, 80)) x1, y1, x2, y2 = 28, 28, 44, 52 r1, r2 = 20.7, 24.7 mask_circle1 = (x - x1)**2 + (y - y1)**2 < r1**2 mask_circle2 = (x - x2)**2 + (y - y2)**2 < r2**2 image = np.logical_or(mask_circle1, mask_circle2) # Now we want to separate the two objects in image # Generate the markers as local maxima of the distance to the background distance = ndi.distance_transform_cdt(image) imageio.imwrite("dm.png", distance) # local_maxi = peak_local_max(distance, indices=False, footprint=np.ones((3, 3)), # labels=image) local_maxi = morphology.local_maxima(distance) markers = ndi.label(local_maxi, np.ones((3, 3)))[0] labels = watershed(-distance, markers, mask=image) plt.imshow(markers) plt.show() fig, axes = plt.subplots(ncols=3, figsize=(9, 3), sharex=True, sharey=True) ax = axes.ravel() ax[0].imshow(image, cmap=plt.cm.gray, interpolation='nearest') ax[0].set_title('Overlapping objects') ax[1].imshow(-distance, cmap=plt.cm.gray, interpolation='nearest') ax[1].set_title('Distances') ax[2].imshow(labels, cmap=plt.cm.nipy_spectral, interpolation='nearest') ax[2].set_title('Separated objects')
Image_by_reconstruction_open_close_util_uint8 = util.invert( Image_by_reconstruction_open_close_util.astype(np.uint8)) #cv2.imshow( "dilation by util", Image_by_reconstruction_open_close_util_uint8 ); print("dilation by util") plt.imshow(Image_by_reconstruction_open_close_util_uint8) plt.show() # Regional max #RegMax_ndi = ndi.filters.maximum_filter(Image_by_reconstruction_open_close_util, footprint = np.ones((3,3),dtype=np.float64)) #RegMax_ndi = (Image_by_reconstruction_open_close_util == RegMax_ndi) #print("Regional max by ndi") #plt.imshow(RegMax_ndi) #plt.show() RegMax_skimage = local_maxima(Image_by_reconstruction_open_close_util_uint8) #cv2.imshow( "Regional max by skimage", RegMax_skimage ); RegMax_skimage = RegMax_skimage.astype(bool) print("Regional max by skimage") plt.imshow(RegMax_skimage) plt.show() # Remove small objects from binary image RegMax_remove_skimage = remove_small_objects(RegMax_skimage, min_size=5) #cv2.imshow( "Regional max remove by skimage", RegMax_remove_skimage.astype(np.uint8) ); print("Regional max remove by skimage") plt.imshow(RegMax_remove_skimage) plt.show() resta = np.logical_xor(RegMax_skimage, RegMax_remove_skimage)
def getOMaps(Fxy): bw = Fxy > 0.1 bw = morphology.remove_small_objects(bw, 8) Fxy[(bw == 0)] = 0 Fxy = scipy.signal.medfilt2d(Fxy, kernel_size=3) # Fxy = np.delete( Fxy, [26,27,28,29,48,49,50], 0) Fxy = np.delete(Fxy, [26, 27, 28, 29, 48, 49, 50], 0) Fxy = np.delete(Fxy, [20, 21], 1) H = 0.2 * np.matrix(' 0 1 0; 1 1 1; 0 1 0 ') tFxy = scipy.ndimage.correlate(Fxy, H, mode='constant') rng = np.linspace(0, 3.0, num=100) alpha = scipy.stats.norm(0.94, 0.17).pdf(rng) alpha = np.max(alpha) sit = scipy.stats.norm(0.94, 0.17).pdf(tFxy) sit = sit / alpha beta = scipy.stats.norm(1.6, 0.2).pdf(rng) beta = np.max(beta) stand = scipy.stats.norm(1.6, 0.2).pdf(tFxy) stand = stand / beta tFxy[(sit < 0.5) & (stand < 0.5)] = 0 bw = tFxy > 0.1 bw = morphology.remove_small_objects(bw, 8) tFxy[(bw == 0)] = 0 labels = label(tFxy, neighbors=8) regions = regionprops(labels, coordinates='rc') num = len(regions) occlocs = [] occarea = [] occMAL = [] occhgt = [] if num > 0: I = toimage(tFxy) strel = morphology.disk(1) Ie = morphology.erosion(I, strel) Id = morphology.dilation(I, strel) Iobr = morphology.reconstruction(Ie, Id) Fgm = morphology.local_maxima(Iobr) # print( "Fgm = ", Fgm) Iobr[(Fgm == 0)] = 0 labels = label(Fgm) regions = regionprops(labels, tFxy, coordinates='rc') num = len(regions) if num > 0: for props in regions: occlocs.append(props.centroid) # occarea.append( props.area ) # occMAL.append( props.major_axis_length ) occhgt.append(props.max_intensity) return num, occlocs, occhgt
print("Edge detection") sobel = filters.sobel(Contrast_image) io.imshow(sobel) plt.figure() # Gradient magnitude Sobel_gradient_array = filters.rank.gradient(sobel,disk(1)) # Compute the opening-by-reconstruction (erode) print("Compute the opening-by-reconstruction (erode)") Image_erosion = erosion(Contrast_image,disk(1)) Image_by_reconstruction_opening = reconstruction(Image_erosion,Contrast_image) io.imshow(Image_by_reconstruction_opening) plt.figure() # Compute the closing-by-reconstruction (dilation) print("Compute the closing-by-reconstruction (dilation)") Image_dilation = dilation(Image_by_reconstruction_opening,disk(1)) Image_by_reconstruction_closing = reconstruction(util.invert(Image_dilation),util.invert(Image_by_reconstruction_opening)) Image_by_reconstruction_closing = util.invert(Image_by_reconstruction_closing) io.imshow(Image_by_reconstruction_closing) plt.figure() # Regional max print("REGIONAL MAX") Regional_max = local_maxima(Image_by_reconstruction_closing) io.imshow(Regional_max)
def find_focal_points(image, scope='local', maxima_areas='large', local_maxima_threshold=None, num_points=None): """ Finds the 'focal_points' of a model, given a low resolution CAM. Has two modes: a 'local' scope and a 'global' one. If a 'local' scope is selected, the function looks for local maxima in the CAM. Due to the high sensitivity of the algorithm finding the local maxima, usually a large number of maxima is identified (which is, in most cases, undesirable. An interest_threshold can be selected that filters out possibly unwanted maxima (i.e. maxima whose intensity is lower than the threshold). Due to the resizing of the CAM, these local maxima produce large areas in the new image. If this is not desired, the option maxima_areas='small' should be selected, which "skeletonizes" the large areas to shrink them. The 'global' scope looks for global maxima in the CAM. This is accompanied by the parameter num_points, which designates the number of points returned by the function. :param image: An input image. Ideally this should be a low resolution CAM. :param scope: Can either be 'local' or 'global'. A 'local' scope looks for local maxima in the image, while a 'global' scope looks for global ones. :param maxima_areas: Can either be 'large' or 'small', depending on whether or not we want larger or smaller areas. Only relevant for 'local' scopes. :param local_maxima_threshold: A float that filters out any local maxima that are below the threshold. Its default value is the average of the lowest-intensity local maxima with the highest-intensity one. Only relevant for 'local' scopes. :param num_points: An integer that specifies the number of points with the maximum intensity. Only relevant for 'global' scopes. :return: A list of tuples, each containing the x and y coordinates of the 'focal points' in the input CAM. """ # Global scope: looks for 'num_points' global maxima in the input image. if scope == 'global': # If 'num_points' is not defined, picks the square root of one of its dimensions: # e.g. for a 224x224 image: num_points = sqrt(224) = 15 if num_points: if not isinstance(num_points, int): raise TypeError('num_points can only take integer values') else: num_points = int(round(np.sqrt(opt.im_size))) # Resizes the image to the desired size and returns the coordinates of the top 'num_points' pixels that have # the largest values. They are cast as python's default 32-bit integers to be compatible with SimpleITK's # ConnectedThreshold function. The two axes are also reversed. top_points = np.argpartition(resize(image).ravel(), -num_points)[-num_points:] return [(int(x % opt.im_size), int(x // opt.im_size)) for x in top_points] # Local scope: looks for local maxima in the input image. elif scope == 'local': # Identifies the image's local maxima. candidate_points = morphology.local_maxima(image).astype(bool) # Because of the high sensitivity of scikit-image's morphology.local_maxima function, it is often desired to # filter some of the local maxima out via a threshold. If this is not passed explicitly the average of the # local maxima with the minimum and maximum intensities is used. if not isinstance(local_maxima_threshold, float): local_maxima_threshold = (image[candidate_points].max() + image[candidate_points].min()) / 2 # Any local maxima that, whose intensity fails to exceed the threshold is ignored. focal_points = candidate_points * image > local_maxima_threshold # Resizes the map of the local maxima to the desired dimensions. This results in the enlargement of the areas # of the each maxima. If this is undesired, as indicated by the option maxima_areas='small', scikit-image's # morphology.skeletonize is applied, which shrinks the maxima areas. focal_points = resize(focal_points.astype(float), resample_method='nearest') if maxima_areas not in ('small', 'large'): raise ValueError("maxima_areas can either be 'small' or 'large'") elif maxima_areas == 'small': focal_points = morphology.skeletonize(focal_points) # Finally, the coordinates of the maxima are returned. They are cast as python's default 32-bit integers to be # compatible with SimpleITK's ConnectedThreshold function. The two axes are also reversed. focal_point_coods = np.where(focal_points) return [(int(focal_point_coods[1][i]), int(focal_point_coods[0][i])) for i in range(len(focal_point_coods[0]))]