def __surface_distances(result, reference, voxelspacing=None, connectivity=1): """ The distances between the surface voxel of binary objects in result and their nearest partner surface voxel of a binary object in reference. """ result = numpy.atleast_1d(result.astype(numpy.bool)) reference = numpy.atleast_1d(reference.astype(numpy.bool)) if voxelspacing is not None: voxelspacing = _ni_support._normalize_sequence(voxelspacing, result.ndim) voxelspacing = numpy.asarray(voxelspacing, dtype=numpy.float64) if not voxelspacing.flags.contiguous: voxelspacing = voxelspacing.copy() # binary structure footprint = generate_binary_structure(result.ndim, connectivity) # test for emptiness if 0 == numpy.count_nonzero(result): raise RuntimeError('The first supplied array does not contain any binary object.') if 0 == numpy.count_nonzero(reference): raise RuntimeError('The second supplied array does not contain any binary object.') # extract only 1-pixel border line of objects result_border = result - binary_erosion(result, structure=footprint, iterations=1) reference_border = reference - binary_erosion(reference, structure=footprint, iterations=1) # compute average surface distance # Note: scipys distance transform is calculated only inside the borders of the # foreground objects, therefore the input has to be reversed dt = distance_transform_edt(~reference_border, sampling=voxelspacing) sds = dt[result_border] return sds
def __surface_distances(input1, input2, voxelspacing=None, connectivity=1): """ The distances between the surface voxel of binary objects in input1 and their nearest partner surface voxel of a binary object in input2. """ input1 = numpy.atleast_1d(input1.astype(numpy.bool)) input2 = numpy.atleast_1d(input2.astype(numpy.bool)) if voxelspacing is not None: voxelspacing = _ni_support._normalize_sequence(voxelspacing, input1.ndim) voxelspacing = numpy.asarray(voxelspacing, dtype=numpy.float64) if not voxelspacing.flags.contiguous: voxelspacing = voxelspacing.copy() # binary structure footprint = generate_binary_structure(input1.ndim, connectivity) # extract only 1-pixel border line of objects input1_border = input1 - binary_erosion(input1, structure=footprint, iterations=1) input2_border = input2 - binary_erosion(input2, structure=footprint, iterations=1) # compute average surface distance # Note: scipys distance transform is calculated only inside the borders of the # foreground objects, therefore the input has to be reversed dt = distance_transform_edt(~input2_border, sampling=voxelspacing) sds = dt[input1_border] return sds
def get_2D_peaks(arr2D, plot=False, amp_min=DEFAULT_AMP_MIN): struct = generate_binary_structure(2, 1) neighborhood = iterate_structure(struct, PEAK_NEIGHBORHOOD_SIZE) local_max = maximum_filter(arr2D, footprint=neighborhood) == arr2D background = arr2D == 0 eroded_background = binary_erosion(background, structure=neighborhood, border_value=1) detected_peaks = local_max - eroded_background amps = arr2D[detected_peaks] j, i = np.where(detected_peaks) amps = amps.flatten() peaks = zip(i, j, amps) peaks_filtered = [x for x in peaks if x[2] > amp_min] # freq, time, amp frequency_idx = [x[1] for x in peaks_filtered] time_idx = [x[0] for x in peaks_filtered] if plot: # scatter of the peaks fig, ax = plt.subplots() ax.imshow(arr2D) ax.scatter(time_idx, frequency_idx) ax.set_xlabel("Time") ax.set_ylabel("Frequency") ax.set_title("Spectrogram") plt.gca().invert_yaxis() plt.show() return zip(frequency_idx, time_idx)
def detect_peaks(image): """ http://stackoverflow.com/questions/3684484/peak-detection-in-a-2d-array Takes an image and detect the peaks using the local maximum filter. Returns a boolean mask of the peaks (i.e. 1 when the pixel's value is the neighborhood maximum, 0 otherwise) """ from scipy.ndimage.filters import maximum_filter from scipy.ndimage.morphology import generate_binary_structure, binary_erosion # define an 8-connected neighborhood neighborhood = generate_binary_structure(2,2) #apply the local maximum filter; all pixel of maximal value #in their neighborhood are set to 1 local_max = maximum_filter(image, footprint=neighborhood)==image background = (image==0) #a little technicality: we must erode the background in order to #successfully subtract it form local_max, otherwise a line will #appear along the background border (artifact of the local maximum filter) eroded_background = binary_erosion(background, structure=neighborhood, border_value=1) detected_peaks = local_max - eroded_background peaks = np.array(np.where(detected_peaks)).T return peaks
def get_2D_peaks(array2D): # This function is based on the function 'get_2D_peaks()' available at the URL below. # https://github.com/worldveil/dejavu/blob/master/dejavu/fingerprint.py # Copyright (c) 2013 Will Drevo, use permitted under the terms of the open-source MIT License. # Create a filter to extract peaks from the image data. struct = generate_binary_structure(2, 1) neighborhood = iterate_structure(struct, 25) # Find local maxima using our fliter shape. These are boolean arrays. local_maxima = maximum_filter(array2D, footprint=neighborhood) == array2D background = (array2D == 0) eroded_background = binary_erosion(background, structure=neighborhood, border_value=1) # Boolean mask of array2D with True at peaks. detected_peaks = local_maxima - eroded_background # Extract peak amplitudes and locations. amps = array2D[detected_peaks] j, i = numpy.where(detected_peaks) # Filter peaks for those exceeding the minimum amplitude. amps = amps.flatten() peaks = zip(i, j, amps) peaks_filtered = [x for x in peaks if x[2] > AMP_MIN] # Get frequency and time at peaks. frequency_idx = [x[1] for x in peaks_filtered] time_idx = [x[0] for x in peaks_filtered] return (frequency_idx, time_idx)
def measure_of_chaos(img,nlevels): ''' Function for calculating a measure of image noise using level sets # Inputs: image - numpy array of pixel intensities nlevels - number of levels to calculate over (note that we approximating a continuious distribution with a 'large enough' number of levels) # Outputs: measure_value This function calculates the number of connected regions above a threshold at an evenly spaced number of threshold between the min and max values of the image. There is some morphological operations to deal with orphaned pixels and heuristic parameters in the image processing. # Usage img = misc.imread('/Users/palmer/Copy/ion_image.png').astype(float) print measure_of_chaos(img,20) ''' # Image in/preparation sum_notnull = np.sum(img > 0) if sum_notnull == 0: return 0 im=clean_image(img) return float(np.sum([ ndimage.label( morphology.binary_erosion( morphology.binary_dilation(im > lev,structure=dilate_mask) , structure=erode_mask) )[1] for lev in np.linspace(np.amin(im),np.amax(im),nlevels)]))/(sum_notnull*nlevels)
def erodeDilate(self, img, method=None): """ Use morphological operators to erode or dilate the ridge structure. Dilate uses a recursive call to first dilate then erode. Dilation alone produces ridge structures that are too thick to look authentic. Recursive call introduces random spurious minutiae when some valley structures are bridged. """ img = np.array(img) if not method: method = random.choice(('erode', 'dilate', 'none')) inkIndex = np.where(img < 250) imgBin = np.zeros(np.shape(img)) imgBin[inkIndex] = 1 strel = morphology.generate_binary_structure(2,2) if method == 'erode': imgBin = morphology.binary_erosion(imgBin, strel) elif method == 'dilate': imgBin = morphology.binary_dilation(imgBin, strel) else: return img inkIndex = np.where(imgBin == 1) returnImg = 255*np.ones(np.shape(img)) returnImg[inkIndex] = 0 # Recursive call to erode after dilation to give more authentic # appearance. Erode after dilate introduces spurious minutiae # but does not make the ridge structure too thick if method == 'dilate': self.erodeDilate(returnImg, method='erode') return returnImg
def get_2D_peaks(arr2D, plot=False, amp_min=DEFAULT_AMP_MIN): struct = generate_binary_structure(2, 1) neighborhood = iterate_structure(struct, PEAK_NEIGHBORHOOD_SIZE) # find local maxima using our fliter shape local_max = maximum_filter(arr2D, footprint=neighborhood) == arr2D background = (arr2D == 0) eroded_background = binary_erosion(background, structure=neighborhood, border_value=1) # Boolean mask of arr2D with True at peaks detected_peaks = local_max - eroded_background # extract peaks amps = arr2D[detected_peaks] j, i = np.where(detected_peaks) # filter peaks amps = amps.flatten() peaks = zip(i, j, amps) peaks_filtered = [x for x in peaks if x[2] > amp_min] # freq, time, amp # get indices for frequency and time frequency_idx = [x[1] for x in peaks_filtered] time_idx = [x[0] for x in peaks_filtered] return zip(frequency_idx, time_idx)
def dietrich_baseline(bands, intensities, half_window=16, num_erosions=10): ''' Fast and precise automatic baseline correction of ... NMR spectra, 1991. http://www.sciencedirect.com/science/article/pii/002223649190402F http://www.inmr.net/articles/AutomaticBaseline.html ''' # Step 1: moving-window smoothing w = half_window * 2 + 1 window = np.ones(w) / float(w) Y = intensities.copy() if Y.ndim == 2: window = window[None] Y[..., half_window:-half_window] = convolve(Y, window, mode='valid') # Step 2: Derivative. dY = np.diff(Y) ** 2 # Step 3: Iterative thresholding. is_baseline = np.ones(Y.shape, dtype=bool) is_baseline[..., 1:] = iterative_threshold(dY) # Step 3: Binary erosion, to get rid of peak-tops. mask = np.zeros_like(is_baseline) mask[..., half_window:-half_window] = True s = np.ones(3, dtype=bool) if Y.ndim == 2: s = s[None] is_baseline = binary_erosion(is_baseline, structure=s, iterations=num_erosions, mask=mask) # Step 4: Reconstruct baseline via interpolation. if Y.ndim == 2: return np.row_stack([np.interp(bands, bands[m], y[m]) for y, m in zip(intensities, is_baseline)]) return np.interp(bands, bands[is_baseline], intensities[is_baseline])
def detect_local_maxima(image): neighborhood = generate_binary_structure(2,2) local_max = maximum_filter(image, footprint=neighborhood)==image background = (image==0) eroded_background = binary_erosion(background, structure=neighborhood, border_value=1) detected_peaks = local_max - eroded_background return detected_peaks*256.0
def getPara(predict, true, threshold, resolution, windowsize): (TP, FP, TN, FN, class_lable) = perf_measure(true, predict, threshold) if((TP + FN) == 0): TPR = 0 else: TPR = np.float(TP) / (TP + FN) class_lable = class_lable.astype(bool).reshape(250, 130) true = true.astype(bool).reshape((250, 130)) num = 2 x = np.arange( -num , num+1, 1) xx, yy = np.meshgrid( x, x ) struc = (xx * xx + yy * yy)<= num * num class_lable = binary_dilation(class_lable, struc) class_lable = binary_erosion(class_lable, struc) # predict2 = remove_small_objects(class_lable, windowsize * resolution, in_place=False) predict2 = remove_small_objects(class_lable, windowsize, in_place=False) labeled_array1, num_features1 = label(predict2) labeled_array2, num_features2 = label(true) FP_num = num_features1 - num_features2 if FP_num < 0: FP_num = 0 return TPR, FP_num
def detect_peaks_3D(image): """Same functionality as detect_peaks, but works on image cubes. Parameters ---------- TODO Returns ------- TODO """ from scipy.ndimage import maximum_filter from scipy.ndimage.morphology import binary_erosion # Set up 3x3 footprint for maximum filter footprint = np.ones((3, 3, 3)) # Apply maximum filter: All pixel in the neighborhood are set # to the maximal value. Peaks are where image = maximum_filter(image) local_max = maximum_filter(image, footprint=footprint, mode='constant') == image # We have false detections, where the image is zero, we call it background. # Create the mask of the background background = (image == 0) # Erode background at the borders, otherwise we would miss eroded_background = binary_erosion(background, structure=footprint, border_value=1) # Remove the background from the local_max mask detected_peaks = local_max - eroded_background return detected_peaks
def filter_peaks(normalized_heights, spread, offset_radii, trial_size, sensitivity_threshold): # Normalise distances and heights: normalized_heights[normalized_heights < 0] = 0 # Forbid negative (concave) Gaussians. spread /= trial_size spread(spread > sqrt(2)) = sqrt(2) ; spread(spread == 0) = sqrt(2) ; offset_radii = offset_radii / trial_size offset_radii[offset_radii == 0] = 0.001 # Remove zeros values to prevent division error later. # Create search metric and screen impossible peaks: search_record = normalized_heights / offset_radii search_record /= 100.0 search_record[search_record > 1] = 1 search_record[spread < 0.5] = 0 # Invalidates negative Gaussian widths. search_record[spread > 1] = 0 # Invalidates Gaussian widths greater than a feature spacing. search_record[offset_radii > 1] = 0 # Invalidates Gaussian widths greater than a feature spacing. kernel = int(np.round(trial_size/3)) if kernel % 2 == 0: kernel += 1 search_record = scipy.signal.medfilt2d(search_record, kernel) # Median filter to strip impossibly local false-positive features. search_record[search_record < sensitivity_threshold ] = 0 # Collapse improbable features to zero likelyhood. search_record[search_record >= sensitivity_threshold ] = 1 # Round likelyhood of genuine features to unity. # Erode regions of likely features down to points. search_record = binary_erosion(search_record, iterations=-1 ) y, x = np.where(search_record==1) return np.vstack((y,x)).T # Extract the locations of the identified features.
def find_local_maxima(arr): """ Find local maxima in a multidimensional array `arr`. Parameters ---------- arr : np.ndarray The array to find maxima in Returns ------- indices : tuple of np.ndarray The indices of local maxima in `arr` """ # http://stackoverflow.com/questions/3684484/peak-detection-in-a-2d-array/3689710#3689710 # neighborhood is simply a 3x3x3 array of True neighborhood = morphology.generate_binary_structure(len(arr.shape), 2) local_max = ( filters.maximum_filter(arr, footprint=neighborhood) == arr ) # http://www.scipy.org/doc/api_docs/SciPy.ndimage.morphology.html#binary_erosion background = ( arr == 0 ) eroded_background = morphology.binary_erosion(background, structure=neighborhood, border_value=1) # we obtain the final mask, containing only peaks, # by removing the background from the local_min mask detected_max = local_max ^ eroded_background # ^ = XOR return np.where(detected_max)
def erode_mask(maskData, erosion=1, isFullSized=False, is2D=False): structuringElement = get_structuring_element(isFullSized, is2D) timesEroded = 0 while timesEroded < erosion: maskData = morphology.binary_erosion(maskData, structuringElement) timesEroded += 1 return maskData
def find_single_seed(image_filename, output_filename): image = Image.from_file(image_filename) w, h = 500, 500 tube_section = image[1024-w:1024+w,1024-h:1024+h] threshold = threshold_otsu(tube_section) thresholded = tube_section > threshold x, y, r = find_inner_circle_parameters(thresholded, 400, 500) # FIXME - think routine is finding outer circle stripped = strip_outside_circle(thresholded, (x, y), 300) eroded = binary_erosion(stripped, structure=np.ones((10, 10))) float_coords = map(np.mean, np.where(eroded > 0)) ix, iy = map(int, float_coords) w, h = 100, 100 selected = tube_section[ix-w:ix+w,iy-h:iy+h] with open(output_filename, 'wb') as f: f.write(selected.view(Image).png())
def get2DPeaks(arr2D): """ Generates peaks of a spectogram. Args: arr2D: spectogram. Returns: List of pairs (time, frequency) of peaks. """ struct = generate_binary_structure(2, 1) neighborhood = iterate_structure(struct, PEAK_NEIGHBORHOOD_SIZE) # find local maxima using our fliter shape local_max = maximum_filter(arr2D, footprint=neighborhood) == arr2D background = (arr2D == 0) eroded_background = binary_erosion(background, structure=neighborhood, border_value=1) # Boolean mask of arr2D with True at peaks detected_peaks = local_max - eroded_background # extract peaks amps = arr2D[detected_peaks] j, i = np.where(detected_peaks) # filter peaks amps = amps.flatten() peaks = zip(i, j, amps) peaks_filtered = [x for x in peaks if x[2] > AMP_MIN] # freq, time, amp # get indices for frequency and time frequency_idx = [x[1] for x in peaks_filtered] time_idx = [x[0] for x in peaks_filtered] return zip(frequency_idx, time_idx)
def detect_peaks(image): """Detect peaks in an image using a maximum filter. Parameters ---------- TODO Returns ------- TODO """ from scipy.ndimage import maximum_filter from scipy.ndimage.morphology import binary_erosion # Set up 3x3 footprint for maximum filter, can also be a different neighborhood if necessary footprint = np.ones((3, 3)) # Apply maximum filter: All pixel in the neighborhood are set # to the maximal value. Peaks are where image = maximum_filter(image) local_maximum = maximum_filter(image, footprint=footprint) == image # We have false detections, where the image is zero, we call it background. # Create the mask of the background zero_background = (image == 0) # Erode background at the borders, otherwise we would miss the points in the neighborhood eroded_background = binary_erosion(zero_background, structure=footprint, border_value=1) # Remove the background from the local_maximum image detected_peaks = local_maximum - eroded_background return detected_peaks
def plotPeaks(arr2D, amp_min=DEFAULT_AMP_MIN): # http://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.morphology.iterate_structure.html#scipy.ndimage.morphology.iterate_structure struct = generate_binary_structure(2, 1) neighborhood = iterate_structure(struct, PEAK_NEIGHBORHOOD_SIZE) # find local maxima using our fliter shape local_max = maximum_filter(arr2D, footprint=neighborhood) == arr2D background = (arr2D == 0) eroded_background = binary_erosion(background, structure=neighborhood, border_value=1) # Boolean mask of arr2D with True at peaks detected_peaks = local_max - eroded_background # extract peaks amps = arr2D[detected_peaks] j, i = np.where(detected_peaks) # filter peaks amps = amps.flatten() peaks = zip(i, j, amps) peaks_filtered = [x for x in peaks if x[2] > amp_min] # freq, time, amp # get indices for frequency and time frequency_idx = [x[1] for x in peaks_filtered] time_idx = [x[0] for x in peaks_filtered] # scatter of the peaks fig, ax = plt.subplots() ax.imshow(arr2D) ax.scatter(time_idx, frequency_idx) ax.set_xlabel('Time') ax.set_ylabel('Frequency') ax.set_title("Spectrogram") plt.gca().invert_yaxis() plt.show()
def find_object(img, thresholds, sizerange, dist_thresh, erode=False, check_centers=True): body = nim.threshold(img, thresholds[0], thresholds[1]) if erode is not False: for i in range(erode): body = binary_erosion(body) if check_centers is False: blobs = nim.find_blobs(body, sizerange=sizerange, aslist=False) else: blobs = nim.find_blobs(body, sizerange=sizerange, aslist=True) body = blobs if check_centers: centers = nim.center_of_blob(blobs) dist = [] for center in centers: diff = np.linalg.norm( center - np.array(img.shape)/2. ) dist.append(diff) body = np.zeros_like(img) for j, d in enumerate(dist): if d < dist_thresh: body += blobs[j] if body.max() > 1: body /= body.max() if body is None: body = np.zeros_like(img) body = np.array(body*255, dtype=np.uint8) return body
def InsideOutside(s): ''' Create inside-outside function for slice and extract nodes, values just inside, just outside and on the boundary Arguments ---- s : 2D numpy integer array Extracted slice of label volume ''' nx, ny = s.shape # Create boundary layer mask from difference between dilation # and erosion of label. The mask represents the layers of # voxels immediately inside and outside the boundary. bound_mask = binary_dilation(s) - binary_erosion(s) # Inside-outside function from complement Euclidian distance transforms # Positive outside, negative inside io = EDT(1-s) - EDT(s) # Extract x, y coordinates and IO function values boundary layers xy = np.argwhere(bound_mask) # N x 2 coordinates of non-zero voxels # Random downsample by 3 # Every third point(ish) on boundary should be sufficient for accurate RBF n = xy.shape[0] samp = np.random.choice(np.arange(n), int(n/3.0)) xy = xy[samp,:] io_xy = io[xy[:,0], xy[:,1]] return io_xy, xy
def detect_local_minima(arr): # http://stackoverflow.com/questions/3684484/peak-detection-in-a-2d-array/3689710#3689710 """ Takes an array and detects the troughs using the local maximum filter. Returns a boolean mask of the troughs (i.e. 1 when the pixel's value is the neighborhood maximum, 0 otherwise) """ # define an connected neighborhood # http://www.scipy.org/doc/api_docs/SciPy.ndimage.morphology.html#generate_binary_structure neighborhood = morphology.generate_binary_structure(len(arr.shape),2) # apply the local minimum filter; all locations of minimum value # in their neighborhood are set to 1 # http://www.scipy.org/doc/api_docs/SciPy.ndimage.filters.html#minimum_filter local_min = (filters.minimum_filter(arr, footprint=neighborhood)==arr) # local_min is a mask that contains the peaks we are # looking for, but also the background. # In order to isolate the peaks we must remove the background from the mask. # # we create the mask of the background background = (arr==0) # # a little technicality: we must erode the background in order to # successfully subtract it from local_min, otherwise a line will # appear along the background border (artifact of the local minimum filter) # http://www.scipy.org/doc/api_docs/SciPy.ndimage.morphology.html#binary_erosion eroded_background = morphology.binary_erosion( background, structure=neighborhood, border_value=1) # # we obtain the final mask, containing only peaks, # by removing the background from the local_min mask detected_minima = local_min - eroded_background return np.where(detected_minima)
def detect_peaks(image): """ from: http://stackoverflow.com/questions/3684484/peak-detection-in-a-2d-array Takes an image and detect the peaks usingthe local maximum filter. Returns a boolean mask of the peaks (i.e. 1 when the pixel's value is the neighborhood maximum, 0 otherwise) """ # define an 8-connected neighborhood neighborhood = generate_binary_structure(2,2) #apply the local maximum filter; all pixel of maximal value #in their neighborhood are set to 1 local_max = maximum_filter(image, footprint=neighborhood)==image #local_max is a mask that contains the peaks we are #looking for, but also the background. #In order to isolate the peaks we must remove the background from the mask. #we create the mask of the background background = (image==0) #a little technicality: we must erode the background in order to #successfully subtract it form local_max, otherwise a line will #appear along the background border (artifact of the local maximum filter) eroded_background = binary_erosion(background, structure=neighborhood, border_value=1) #we obtain the final mask, containing only peaks, #by removing the background from the local_max mask detected_peaks = local_max - eroded_background return detected_peaks
def csf_covars(csfmask_file, func_file, min_nb_of_voxels=20, nb_covars=5, verbose=0, outdir=None): """ Compute covariates that represent the CSF variability in a functional timeserie. Parameters ---------- csfmask_file: str (mandatory) a binary mask of the CSF in the functional space. func_file: str (mandatory) a functional volume of size (X, Y, Z, T). min_nb_of_voxels: int (optional, default 50) the criterion used to select a CSF ROI with specific size. nb_covars: int (optional, default 5) the number of covariates used to explain the CSF variability. verbose: int (optional, default 0) the verbosity level. outdir: str (optional, default None) for debuging purpose: if the verbosity level is > 1 save the mask used to select the functional time series. Returns ------- covars: array (T, nb_covars) the requested number of covariates that represent the CSF variability. """ # Erode the mask in order to have > min_nb_of_voxels ones csf_image = nibabel.load(csfmask_file) csf_array = csf_image.get_data() csf_array[np.where(csf_array != 0)] = 1 if len(np.where(csf_array == 1)[0]) > min_nb_of_voxels: while True: csf_tmp_array = binary_erosion(csf_array, iterations=1) nb_of_ones = len(np.where(csf_tmp_array == 1)[0]) if nb_of_ones < min_nb_of_voxels: break csf_array = csf_tmp_array else: raise ValueError( "Not enough CSF voxels in mask '{0}'.".format(csfmask_file)) if verbose > 1: if outdir is not None: csf_mask = nibabel.Nifti1Image(csf_array.astype(int), csf_image.get_affine()) nibabel.save(csf_mask, os.path.join(outdir, "covars_mask.nii.gz")) # Compute a SVD func_array = nibabel.load(func_file).get_data() csftimeseries = func_array[np.where(csf_array == 1)].T csftimeseries -= csftimeseries.mean(axis=0) u, s, v = np.linalg.svd(csftimeseries, full_matrices=False) if verbose > 1: plt.plot(s) plt.show() # Get the covariates that represent the CSF variability covars = u[:, :nb_covars] return covars
def main(): args = getArguments(getParser()) # prepare logger logger = Logger.getInstance() if args.debug: logger.setLevel(logging.DEBUG) elif args.verbose: logger.setLevel(logging.INFO) # loading input images b0img, b0hdr = load(args.b0image) bximg, bxhdr = load(args.bximage) # convert to float b0img = b0img.astype(numpy.float) bximg = bximg.astype(numpy.float) # check if image are compatible if not b0img.shape == bximg.shape: raise ArgumentError('The input images shapes differ i.e. {} != {}.'.format(b0img.shape, bximg.shape)) if not header.get_pixel_spacing(b0hdr) == header.get_pixel_spacing(bxhdr): raise ArgumentError('The input images voxel spacing differs i.e. {} != {}.'.format(header.get_pixel_spacing(b0hdr), header.get_pixel_spacing(bxhdr))) # check if supplied threshold value as well as the b value is above 0 if args.threshold is not None and not args.threshold >= 0: raise ArgumentError('The supplied threshold value must be greater than 0, otherwise a division through 0 might occur.') if not args.b > 0: raise ArgumentError('The supplied b-value must be greater than 0.') # compute threshold value if not supplied if args.threshold is None: b0thr = otsu(b0img, 32) / 4. # divide by 4 to decrease impact bxthr = otsu(bximg, 32) / 4. if 0 >= b0thr: raise ArgumentError('The supplied b0image seems to contain negative values.') if 0 >= bxthr: raise ArgumentError('The supplied bximage seems to contain negative values.') else: b0thr = bxthr = args.threshold logger.debug('thresholds={}/{}, b-value={}'.format(b0thr, bxthr, args.b)) # threshold b0 + bx DW image to obtain a mask # b0 mask avoid division through 0, bx mask avoids a zero in the ln(x) computation mask = binary_fill_holes(b0img > b0thr) & binary_fill_holes(bximg > bxthr) # perform a number of binary morphology steps to select the brain only mask = binary_erosion(mask, iterations=1) mask = largest_connected_component(mask) mask = binary_dilation(mask, iterations=1) logger.debug('excluding {} of {} voxels from the computation and setting them to zero'.format(numpy.count_nonzero(mask), numpy.prod(mask.shape))) # compute the ADC adc = numpy.zeros(b0img.shape, b0img.dtype) adc[mask] = -1. * args.b * numpy.log(bximg[mask] / b0img[mask]) adc[adc < 0] = 0 # saving the resulting image save(adc, args.output, b0hdr, args.force)
def detect_local_minima(arr): neighborhood = morphology.generate_binary_structure(len(arr.shape), 2) local_min = (filters.minimum_filter(arr, footprint=neighborhood) == arr) background = (arr == 0) eroded_background = morphology.binary_erosion( background, structure=neighborhood, border_value=1) detected_minima = local_min - eroded_background return np.where(detected_minima)
def load_bg_mask_from_seg(self, file_name): ws = io.loadmat(file_name)["ws"] bg_mask = (ws == 1).astype(ws.dtype) bg_mask = binary_erosion(bg_mask, iterations = 15, mask = bg_mask) return bg_mask
def main(): args = getArguments(getParser()) # prepare logger logger = Logger.getInstance() if args.debug: logger.setLevel(logging.DEBUG) elif args.verbose: logger.setLevel(logging.INFO) # load input image data_input, header_input = load(args.input) # treat as binary data_input = data_input.astype(numpy.bool) # check dimension argument if args.dimension and (not args.dimension >= 0 or not args.dimension < data_input.ndim): argparse.ArgumentError(args.dimension, 'Invalid dimension of {} supplied. Image has only {} dimensions.'.format(args.dimension, data_input.ndim)) # compute erosion and dilation steps erosions = int(math.ceil(args.width / 2.)) dilations = int(math.floor(args.width / 2.)) logger.debug("Performing {} erosions and {} dilations to achieve a contour of width {}.".format(erosions, dilations, args.width)) # erode, dilate and compute contour if not args.dimension: eroded = binary_erosion(data_input, iterations=erosions) if not 0 == erosions else data_input dilated = binary_dilation(data_input, iterations=dilations) if not 0 == dilations else data_input data_output = dilated - eroded else: slicer = [slice(None)] * data_input.ndim bs_slicer = [slice(None)] * data_input.ndim data_output = numpy.zeros_like(data_input) for sl in range(data_input.shape[args.dimension]): slicer[args.dimension] = slice(sl, sl+1) bs_slicer[args.dimension] = slice(1, 2) bs = generate_binary_structure(data_input.ndim, 1) eroded = binary_erosion(data_input[slicer], structure=bs[bs_slicer], iterations=erosions) if not 0 == erosions else data_input[slicer] dilated = binary_dilation(data_input[slicer], structure=bs[bs_slicer], iterations=dilations) if not 0 == dilations else data_input[slicer] data_output[slicer] = dilated - eroded logger.debug("Contour image contains {} contour voxels.".format(numpy.count_nonzero(data_output))) # save resulting volume save(data_output, args.output, header_input, args.force) logger.info("Successfully terminated.")
def get_ellipse_cov(img, erode=False, recenter=True): # Pattern. Recogn. 20, Sept. 1998, pp. 31-40 # J. Prakash, and K. Rajesh # Human Face Detection and Segmentation using Eigenvalues of Covariance Matrix, Hough Transform and Raster Scan Algorithms #eroded_img = binary_erosion(img) #boundary = img-eroded_img if img is not None: if erode is not False: try: e = 0 while e < erode: e += 1 img = binary_erosion(img) except: pass img = binary_fill_holes(img) if recenter: center = center_of_blob(img) else: center = np.array([0,0]) if 1: ptsT = np.transpose(np.nonzero(img)) for pt in ptsT: pt -= center pts = (ptsT).T cov = np.cov(pts) cov = np.nan_to_num(cov) e,v = np.linalg.eig(cov) longaxis = v[:,np.argmax(e)] shortaxis = v[:,np.argmin(e)] if len(ptsT) > 2: dl = [np.dot(longaxis, ptsT[i]) for i in range(len(ptsT))] longaxis_radius = np.max( np.abs(dl) ) ds = [np.dot(shortaxis, ptsT[i]) for i in range(len(ptsT))] shortaxis_radius = np.max( np.abs(ds) ) else: longaxis_radius = None shortaxis_radius = None if recenter is False: return longaxis, shortaxis, [longaxis_radius, shortaxis_radius] else: return center, longaxis, shortaxis, [longaxis_radius, shortaxis_radius] else: return [0,0],0
def find_peaks(file): #read image data f=pyfits.open(file) img=f[0].data #set NaN pixels (empty pixels) to zero img[img != img]=0.0 img[img<0.]=0.0 if dim==4: img=img[0,0,:,:] #gets rid of 3 and 4 dimensions, since FIRST fits files have four axis but only first two have data T=ndimage.standard_deviation(img) sourcelabels,num_sources=ndimage.label(img>T) backgroundlabels,num_background=ndimage.label(img<T) # define an 8-connected neighbourhood neighborhood = generate_binary_structure(2,2) fimg=img*sourcelabels #apply the local maximum filter; all pixel of maximal value #in their neighbourhood are set to 1 local_max=maximum_filter(fimg,footprint=neighborhood)==fimg #In order to isolate the peaks we must remove the background from the mask. #we create the mask of the background background=img*backgroundlabels #we must erode the background in order to #successfully subtract it form local_max, otherwise a line will #appear along the background border (artifact of the local maximum filter) eroded_background=binary_erosion(background,structure=neighborhood,border_value=1) #we obtain the final mask, containing only peaks, #by removing the background from the local_max mask detected_peaks=local_max-eroded_background #contains some peaks not in source (background bright features), but code can remove these #now need to find positions of these maximum #label peaks peaklabels,num_peaks=ndimage.measurements.label(detected_peaks) #get peak positions slices = ndimage.find_objects(peaklabels) x, y = [], [] for dy,dx in slices: x_center = (dx.start + dx.stop - 1)/2 x.append(x_center) y_center = (dy.start + dy.stop - 1)/2 y.append(y_center) peak_positions=zip(x,y) #get peak values, in Jy/beam peak_fluxes=[] for coord in peak_positions: peak_fluxes.append(img[coord[1],coord[0]]) peaks=zip(peak_positions,peak_fluxes) #sort by peak_fluxes. Two brightest peaks will be the first two in the list peaks=sorted(peaks,key=lambda l: l[1]) peaks.reverse() return peaks,img,f
def distance_metrics(mask): res_dist = np.zeros(mask.shape) # (l,w,h) = header.get_zooms() tmp_0 = mask.copy() tmp_1 = mask.copy() cnt = 1 while True: tmp_1 = morph.binary_erosion(tmp_0) tmp_0 = np.logical_xor(tmp_1, tmp_0) if not tmp_0.max(): break for i in range(mask.shape[0]): for j in range(mask.shape[1]): for k in range(mask.shape[2]): if tmp_0[i, j, k]: res_dist[i, j, k] = cnt cnt = cnt + 1 tmp_0 = tmp_1.copy() return res_dist
def _binary_erosion(self): vol_name = str(self.out_edit.text()) num = self.structure_combo.currentIndex() + 3 self.structure_array = np.ones((num, num, num), dtype=np.int) if not vol_name: self.out_edit.setFocus() return source_row = self.source_combo.currentIndex() source_data = self._model.data(self._model.index(source_row), Qt.UserRole + 6) binary_vol = imtool.binaryzation( source_data, (source_data.max() + source_data.min()) / 2) new_vol = morphology.binary_erosion(binary_vol, structure=self.structure_array) self._model.addItem(new_vol, None, vol_name, self._model._data[0].get_header()) self.done(0)
def adaptivethresh2blocks(img, holder, ADAPTIVEBLOCK=21, DEBRISAREA=50, MAXSIZE=1000, OPENING=2, FILTERSIZE=1, SHRINK=0, REGWSHED=10): img = gaussian_filter(img, FILTERSIZE) bw = skifilter.threshold_adaptive(img, ADAPTIVEBLOCK, 'gaussian') bw2 = skifilter.threshold_adaptive(img, img.shape[0] / 4, 'gaussian') bw = bw * bw2 bw = sizefilterandopen(bw, DEBRISAREA, MAXSIZE, OPENING) if SHRINK > 0: bw = binary_erosion(bw, np.ones((SHRINK, SHRINK))) label = devide_and_label_objects(bw, REGWSHED) label = sizefilter_for_label(label, DEBRISAREA, MAXSIZE, OPENING) label = skilabel(clear_border(label, buffer_size=2)) return label
def processImage(self): log.debug("IMAGE: " + self.image.z + ',' + self.image.t + ',' + self.image.ch) print 'In process image' if int(self.image.z) == 1 and int(self.image.t) == 1 and (int(self.image.ch) ==1 or int(self.image.ch) == 3): # read image from Bisque system resp, content = request(self.image.src + '?format=tiff', "GET", userpass = self.userpass ) # convert stream into Image im = cStringIO.StringIO(content) img = Image.open(im) log.debug("IMAGE: " + str(img.format) + ',' + str(img.size) + ',' + str(img.mode)) ''' IMAGE PROCESSING ''' # convert color image into grayscale image grayimg = ImageOps.grayscale(img) # convert Image into numpy array in_im = asarray(grayimg) # normalize image norm_im = self.normalizeImage(in_im) # set the threshold value thNorm = double((double(self.thValue)/100.0)) # threshold image with thNorm value th_im = norm_im < thNorm; # label image with 8conn structure = [[1,1,1], [1,1,1], [1,1,1]] th_im = binary_erosion(~th_im,structure) label_tuple = label(th_im,structure) #(data, dtype, number of labels) label_im = label_tuple[0]-1 # wathershed wh_im = watershed_ift(in_im, label_im) # convert numpy array into Image img_out = Image.fromarray(wh_im.astype('uint8')) ''' IMAGE PROCESSING ''' # convert Image into stream buffer = StringIO.StringIO() img_out.save(buffer, 'TIFF') # upload image into Bisque system buffer.seek(0) buffer.name = 'file.tif' fields = { 'file' : buffer } resp, content = post_files (self.client_server + '/bisquik/upload_images', fields=fields, userpass = self.userpass,) log.debug("RESP: " + str(content)) self.image_out_url = str(content)
def generate_cpatches(nsamples, patches_path ='./patches.npz'): print("g",nsamples) combined_dims = 4 while True: counts = nsamples #n_samples -> n_experiments, probabity sample_rates X_all = None #load all images from each class (i) X_masks = np.load(patches_path)['x_mask'] X_reals = np.load(patches_path)['x_real'] try: # get (c) images shuffle_idx = np.random.choice(len(X_masks), counts, replace=False) except: pdb.set_trace() #get mask and reals X_masks = X_masks[shuffle_idx] X_reals = X_reals[shuffle_idx] X_ = [] for i,_ in enumerate(X_masks): X_mask = X_masks[i].reshape((patch_size, patch_size)) X_real = normalize(X_reals[i].reshape((patch_size, patch_size))) X_rand = np.random.uniform(0, 1, X_mask.shape)*X_mask X_corrupt = (np.multiply(X_real, np.logical_not(X_mask).astype(int))+X_rand) boundary = np.multiply(np.invert(morph.binary_erosion(X_mask)), X_mask) X_boundary = normalize(filters.gaussian_filter(255.0*boundary,10)).reshape((patch_size, patch_size, 1)) X_combined = np.concatenate((X_corrupt.reshape(patch_size, patch_size, 1), X_mask.reshape(patch_size, patch_size, 1), X_real.reshape(patch_size, patch_size, 1), X_boundary), axis=-1) X_.append(X_combined) X_ = np.stack(X_) print("Patches size {}".format(X_.shape)) shuffle_idx = np.random.choice(len(X_), len(X_), replace=False) yield X_[shuffle_idx]
def morph_oper(path='../../data/empire.jpg', threshold=128): print "\n Starting Morphoocal Operations" colorlist = ['g', 'b', 'y', 'c', 'm'] im = array(Image.open(path).convert('L')) im = 1 * (im < threshold) im = morphology.binary_opening(im) im = morphology.binary_erosion(im) im = morphology.binary_closing(im) im = morphology.binary_dilation(im) im = morphology.binary_opening(im) com = measurements.center_of_mass(im) plt.figure("Morpholocal Operations with Center of Masses", figsize=(13, 5)) plt.imshow(im, cmap=cm.Greys_r) print "Unlabeled center of mass:", com plt.plot(com[0], com[1], 'ro') lbl = ndimage.label(im)[0] coms = measurements.center_of_mass(im, lbl, [1, 2]) print "\nLabeld center of mass:" for i, mass in enumerate(coms): print "\t Center of mass", i + 1, ":", mass plt.plot(mass[0], mass[1], 'go') plt.show() print "\n DONE\n"
def detect_peaks(image, overlap_thresh=10): """ https://stackoverflow.com/questions/3684484/peak-detection-in-a-2d-array Takes an image and detect the peaks usingthe local maximum filter. Returns a boolean mask of the peaks (i.e. 1 when the pixel's value is the neighborhood maximum, 0 otherwise) """ from scipy.ndimage.filters import maximum_filter from scipy.ndimage.morphology import generate_binary_structure, binary_erosion # define an 8-connected neighborhood neighborhood = generate_binary_structure(2, 2) # apply the local maximum filter; all pixel of maximal value # in their neighborhood are set to 1 local_max = maximum_filter(image, footprint=neighborhood) == image # local_max is a mask that contains the peaks we are # looking for, but also the background. # In order to isolate the peaks we must remove the background from the mask. # we create the mask of the background background = (image == 0) # a little technicality: we must erode the background in order to # successfully subtract it form local_max, otherwise a line will # appear along the background border (artifact of the local maximum filter) eroded_background = binary_erosion(background, structure=neighborhood, border_value=1) # we obtain the final mask, containing only peaks, # by removing the background from the local_max mask (xor operation) detected_peaks = local_max ^ eroded_background peak_coords = np.array(np.where(detected_peaks)).T detected_peaks, peak_coords = non_max_suppression_fast( detected_peaks, image, overlap_thresh=overlap_thresh) return detected_peaks, peak_coords
def filter_peaks(normalized_heights, spread, offset_radii, trial_size, sensitivity_threshold): # Normalise distances and heights: normalized_heights[ normalized_heights < 0] = 0 # Forbid negative (concave) Gaussians. spread /= trial_size spread[spread > math.sqrt(2)] = math.sqrt(2) spread[spread == 0] = math.sqrt(2) offset_radii = offset_radii / trial_size offset_radii[ offset_radii == 0] = 0.001 # Remove zeros values to prevent division error later. # Create search metric and screen impossible peaks: search_record = normalized_heights / offset_radii search_record[search_record > 1] = 1 search_record[search_record < 0] = 0 search_record[spread < 0.05] = 0 # Invalidates negative Gaussian widths. search_record[ spread > 1] = 0 # Invalidates Gaussian widths greater than a feature spacing. search_record[ offset_radii > 1] = 0 # Invalidates Gaussian widths greater than a feature spacing. kernel = int(np.round(trial_size / 3)) if kernel % 2 == 0: kernel += 1 # Median filter to strip impossibly local false-positive features. search_record = scipy.signal.medfilt2d(search_record, kernel_size=kernel) search_record[ search_record < sensitivity_threshold] = 0 # Collapse improbable features to zero likelyhood. search_record[ search_record >= sensitivity_threshold] = 1 # Round likelyhood of genuine features to unity. # Erode regions of likely features down to points. search_record = binary_erosion(search_record, iterations=-1) y, x = np.where(search_record == 1) return np.vstack( (y, x)).T # Extract the locations of the identified features.
def get_2D_peaks(arr2D, plot=False, amp_min=DEFAULT_AMP_MIN): # http://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.iterate_structure.html#scipy.ndimage.iterate_structure struct = generate_binary_structure(2, 1) neighborhood = iterate_structure(struct, PEAK_NEIGHBORHOOD_SIZE) # find local maxima using our filter shape local_max = maximum_filter(arr2D, footprint=neighborhood) == arr2D background = (arr2D == 0) eroded_background = binary_erosion(background, structure=neighborhood, border_value=1) # Boolean mask of arr2D with True at peaks (Fixed deprecated boolean operator by changing '-' to '^') detected_peaks = local_max ^ eroded_background # extract peaks amps = arr2D[detected_peaks] j, i = np.where(detected_peaks) # filter peaks amps = amps.flatten() peaks = zip(i, j, amps) peaks_filtered = filter(lambda x: x[2]>amp_min, peaks) # freq, time, amp # get indices for frequency and time frequency_idx = [] time_idx = [] for x in peaks_filtered: frequency_idx.append(x[1]) time_idx.append(x[0]) if plot: # scatter of the peaks fig, ax = plt.subplots() ax.imshow(arr2D) ax.scatter(time_idx, frequency_idx) ax.set_xlabel('Time') ax.set_ylabel('Frequency') ax.set_title("Spectrogram") plt.gca().invert_yaxis() plt.show() return zip(frequency_idx, time_idx)
def get_2D_peaks(arr2D, plot=False, amp_min=DEFAULT_AMP_MIN): # http://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.morphology.iterate_structure.html#scipy.ndimage.morphology.iterate_structure struct = generate_binary_structure(2, 1) neighborhood = iterate_structure(struct, PEAK_NEIGHBORHOOD_SIZE) # find local maxima using our fliter shape local_max = maximum_filter(arr2D, footprint=neighborhood) == arr2D background = (arr2D == 0) eroded_background = binary_erosion(background, structure=neighborhood, border_value=1) # Boolean mask of arr2D with True at peaks detected_peaks = local_max ^ eroded_background # extract peaks amps = arr2D[detected_peaks] j, i = np.where(detected_peaks) # filter peaks amps = amps.flatten() peaks = zip(i, j, amps) peaks_filtered = [x for x in peaks if x[2] > amp_min] # freq, time, amp # get indices for frequency and time frequency_idx = [x[1] for x in peaks_filtered] time_idx = [x[0] for x in peaks_filtered] # scatter of the peaks if plot: fig, ax = plt.subplots() ax.imshow(arr2D) ax.scatter(time_idx, frequency_idx) ax.set_xlabel('Time') ax.set_ylabel('Frequency') ax.set_title("Spectrogram") plt.gca().invert_yaxis() plt.show() # J'AI RAJOUTE LA LIST() return list(zip(frequency_idx, time_idx))
def dietrich_baseline(bands, intensities, half_window=16, num_erosions=10): ''' Fast and precise automatic baseline correction of ... NMR spectra, 1991. http://www.sciencedirect.com/science/article/pii/002223649190402F http://www.inmr.net/articles/AutomaticBaseline.html ''' Y = intensities.copy() half_window = np.clip(half_window, 1, Y.shape[-1] // 2) # Step 1: moving-window smoothing window_len = 2 * half_window + 1 window = np.full(window_len, 1. / window_len) if Y.ndim == 2: window = window[None] Y[..., half_window:-half_window] = convolve(Y, window, mode='valid') # Step 2: Derivative. dY = np.diff(Y)**2 # Step 3: Iterative thresholding. is_baseline = np.ones(Y.shape, dtype=bool) is_baseline[..., 1:] = iterative_threshold(dY) # Step 3: Binary erosion, to get rid of peak-tops. mask = np.zeros_like(is_baseline) mask[..., half_window:-half_window] = True s = np.ones(3, dtype=bool) if Y.ndim == 2: s = s[None] is_baseline = binary_erosion(is_baseline, structure=s, iterations=num_erosions, mask=mask) # Step 4: Reconstruct baseline via interpolation. if Y.ndim == 2: return np.row_stack([ np.interp(bands, bands[m], y[m]) for y, m in zip(intensities, is_baseline) ]) return np.interp(bands, bands[is_baseline], intensities[is_baseline])
def SubtractDominantMotion(image1, image2): # Input: # Images at time t and t+1 # Output: # mask: [nxm] # put your implementation here mask = np.ones(image1.shape, dtype=bool) M = LucasKanadeAffine(image1, image2) image2_w = cv2.warpAffine(image2, M, image1.T.shape) # UNCOMMENT THE FOLLOWING IF YOU WANT TO USE INVERSE COMPOSITION # M = InverseCompositionAffine(image1, image2) # image2_w = cv2.warpAffine(image2, M[:2, :], image1.T.shape) image2_w = binary_erosion(image2_w) image2_w = binary_dilation(image2_w) diff = np.abs(image1 - image2_w) threshold = 0.75 mask = (diff > threshold) return mask
def my_boundary(img): """ Compute boundary of binary image. Parameters ---------- img : ndarray of bools A binary image. Returns ------- boundary : ndarray of bools The boundary as a binary image. """ structuring_element = np.ones((3, 3)) structuring_element[0, 0] = 0 structuring_element[2, 2] = 0 structuring_element[0, 2] = 0 structuring_element[2, 0] = 0 return img ^ morph.binary_erosion(img, structuring_element)
def remove_surface_voxels(voxels, **kwargs): """Removes surface voxels. """ # Use bounding boxes to keep matrix small bb_min = voxels.min(axis=0) bb_max = voxels.max(axis=0) dim = bb_max - bb_min # Voxel offset voxel_off = voxels - bb_min # Generate empty array mat = _voxels_to_matrix(voxel_off) # Erode mat_erode = binary_erosion(mat, **kwargs) # Turn back into voxels voxels_erode = _matrix_to_voxels(mat_erode) + bb_min return voxels_erode
def get_surface(self, mask, voxel_spacing): """ :param mask: ndarray :param voxel_spacing: 体数据的spacing :return: 提取array的表面点的真实坐标(以mm为单位) """ # 卷积核采用的是三维18邻域 kernel = morphology.generate_binary_structure(3, 2) surface = morphology.binary_erosion(mask, kernel) ^ mask surface_pts = surface.nonzero() surface_pts = np.array( list(zip(surface_pts[0], surface_pts[1], surface_pts[2]))) # (0.7808688879013062, 0.7808688879013062, 2.5) (88, 410, 512) # 读出来的数据spacing和shape不是对应的,所以需要反向 return surface_pts * np.array(self.voxel_sapcing[::-1]).reshape(1, 3)
def segmentCt(self, series_uid): with torch.no_grad(): ct = getCt(series_uid) output_a = np.zeros_like(ct.hu_a, dtype=np.float32) seg_dl = self.initSegmentationDl(series_uid) for batch_tup in seg_dl: input_t = batch_tup[0] ndx_list = batch_tup[6] input_g = input_t.to(self.device) prediction_g = self.seg_model(input_g) for i, sample_ndx in enumerate(ndx_list): output_a[sample_ndx] = prediction_g[i].cpu().numpy() mask_a = output_a > 0.5 clean_a = morph.binary_erosion(mask_a, iterations=1) clean_a = morph.binary_dilation(clean_a, iterations=2) return ct, output_a, mask_a, clean_a
def gauss_degrade(image,margin=1.0,change=None,noise=0.02,minmargin=0.5,inner=1.0): if image.ndim==3: image = mean(image,axis=2) m = mean([amin(image),amax(image)]) image = 1*(image>m) if margin<minmargin: return 1.0*image pixels = sum(image) if change is not None: npixels = int((1.0+change)*pixels) else: edt = distance_transform_edt(image==0) npixels = sum(edt<=(margin+1e-4)) r = int(max(1,2*margin+0.5)) ri = int(margin+0.5-inner) if ri<=0: mask = binary_dilation(image,iterations=r)-image else: mask = binary_dilation(image,iterations=r)-binary_erosion(image,iterations=ri) image += mask*randn(*image.shape)*noise*min(1.0,margin**2) smoothed = gaussian_filter(1.0*image,margin) frac = max(0.0,min(1.0,npixels*1.0/prod(image.shape))) threshold = mquantiles(smoothed,prob=[1.0-frac])[0] result = (smoothed>threshold) return 1.0*result
def adaptivethreshwithglobal(img, holder, ADAPTIVEBLOCK=21, DEBRISAREA=50, MAXSIZE=1000, OPENING=2, FILTERSIZE=1, THRESHRELATIVE=1, SHRINK=0, REGWSHED=10): img = gaussian_filter(img, FILTERSIZE) global_thresh = skifilter.threshold_otsu(img) bw = skifilter.threshold_adaptive(img, ADAPTIVEBLOCK, 'gaussian') bw = bw * img > global_thresh * THRESHRELATIVE bw = sizefilterandopen(bw, DEBRISAREA, MAXSIZE, OPENING) if SHRINK > 0: bw = binary_erosion(bw, np.ones((SHRINK, SHRINK))) label = devide_and_label_objects(bw, REGWSHED) label = sizefilter_for_label(label, DEBRISAREA, MAXSIZE, OPENING) label = skilabel(clear_border(label, buffer_size=2)) return label
def detect_peaks(image): """Detect peaks in an image using a maximum filter""" #Set up 3x3 footprint for maximum filter footprint = np.ones((3, 3)) #Apply maximum filter: All pixel in the neighborhood are set #to the maximal value. Peaks are where image = maximum_filter(image) local_maximum = maximum_filter(image, footprint=footprint) == image #We have false detections, where the image is zero, we call it background. #Create the mask of the background background = (image == 0) #Erode background at the borders, otherwise we would miss eroded_background = binary_erosion(background, structure=footprint, border_value=1) #Remove the background from the local_maximum image detected_peaks = local_maximum - eroded_background return detected_peaks
def signal_noise_split(audio): S, _ = spectrum._spectrogram(y=audio, power=1.0, n_fft=2048, hop_length=512, win_length=2048) col_median = np.median(S, axis=0, keepdims=True) row_median = np.median(S, axis=1, keepdims=True) S[S < row_median * 3] = 0.0 S[S < col_median * 3] = 0.0 S[S > 0] = 1 S = binary_erosion(S, structure=np.ones((4, 4))) S = binary_dilation(S, structure=np.ones((4, 4))) indicator = S.any(axis=0) indicator = binary_dilation(indicator, structure=np.ones(4), iterations=2) mask = np.repeat(indicator, hop_length) mask = binary_dilation(mask, structure=np.ones(win_length - hop_length), origin=-(win_length - hop_length)//2) mask = mask[:len(audio)] signal = audio[mask] noise = audio[~mask] return signal, noise
def get_2D_peaks(arr2D, amp_min=DEFAULT_AMP_MIN): struct = generate_binary_structure(2, 1) neighborhood = iterate_structure(struct, PEAK_NEIGHBORHOOD_SIZE) local_max = maximum_filter(arr2D, footprint=neighborhood) == arr2D background = (arr2D == 0) eroded_background = binary_erosion(background, structure=neighborhood, border_value=1) detected_peaks = local_max ^ eroded_background amps = arr2D[detected_peaks] j, i = np.where(detected_peaks) amps = amps.flatten() peaks = zip(i, j, amps) peaks_filtered = [x for x in peaks if x[2] > amp_min] frequency_idx = [x[1] for x in peaks_filtered] time_idx = [x[0] for x in peaks_filtered] return zip(frequency_idx, time_idx)
def remove_edge_fast(mask): """Remove the edge of a masked region. The image border is left untouched. Parameters ---------- mask: np.array(bool) Array of bools of masked pixels. Returns ------- The mask with edges removed. """ # A faster implementation using scipy.binary_erosion # A huge improvement ... but can we do even better? is_interior = np.full(mask.shape, True) is_interior[[0, -1], :] = False # Boundary must be left untouched is_interior[:, [0, -1]] = False erosion_structure = np.ones((3, 3)) return binary_erosion(mask, mask=is_interior, structure=erosion_structure)
def recursion(binary_mask, binary_mask_selected, labels, erosion_iteration, min_size, max_size): #apply erosion(iteration) if erosion_iteration == 0: binary_mask_eroded = binary_mask_selected else: binary_mask_eroded = binary_erosion(binary_mask_selected,iterations=erosion_iteration*3) #do watershed labels_eroded,_ = watershed_erosion_edt(binary_mask_selected,binary_mask_eroded) unique, counts = np.unique(labels_eroded, return_counts=True) #check if there is a nucleus left, if not return last iteration if len(unique)==1: return labels #remove 0 label unique = unique[1:] counts = counts[1:] #for all elements/labels for u,c in zip(unique,counts): if c < min_size: #to small? return labels from binary_mask # do nothing continue if (c >= min_size and c < max_size): #ok size? return labels from binary_mask_erosion #update label map labels[labels_eroded==u] = np.max(labels)+1 else: #to large? recursion(binary_mask, erosion+1) if erosion_iteration == 5: #increase this value to try to segment even further labels[labels_eroded==u] = np.max(labels)+1 #extract just that blob else: binary_mask_selected = labels_eroded==u labels = recursion(binary_mask, binary_mask_selected, labels, erosion_iteration+1, min_size, max_size) return labels
def agglomeration_seed(labels, img, MINSIZE=50, STEPS=100, FILSIZE=5, RATIO=0): """ MINSIZE: minimum area for a seed object. It can be smaller than actual objects. STEPS: Larger it is, more resolution and computation FILSIZE: argument for adaptive thresholding. Larger if capturing too much backrgound. RATIO: argument for adaptive thresholding. Larger if capturing too much backrgound. """ seed = binary_erosion(labels, np.ones((3, 3))) li = [] img = img.astype(np.float32) mask = adaptive_thresh(img, RATIO, FILSIZE) mask = binary_opening(mask, np.ones((3, 3))) mask = remove_small_objects(mask, MINSIZE) foreground = img[mask] perclist = [ np.percentile(foreground, r) for r in np.linspace(0, 100, STEPS) ] for _r in perclist: thresed = remove_small_objects(img > _r, MINSIZE, connectivity=2) > 0 li.append(thresed.astype(np.uint16)) if seed is not None: li.append((seed > 0).astype(np.uint16)) for l in li: l[seed > 0] = 1 q = np.sum(np.dstack(li), axis=2) p = label(q) for ind in reversed(np.unique(q).tolist()): c = seeding_separate(label(q >= ind), p) w = watershed(q >= ind, markers=c, mask=(q >= ind), watershed_line=True) w[mask == 0] = 0 w = remove_small_objects(w, MINSIZE) p = label(w, connectivity=2) return p
def detect_local_maxima(self, arr): # https://stackoverflow.com/questions/3684484/peak-detection-in-a-2d-array/3689710#3689710 """ Takes an array and detects the troughs using the local maximum filter. Returns a boolean mask of the troughs (i.e. 1 when the pixel's value is the neighborhood maximum, 0 otherwise) """ # arr = np.abs(arr) avg = np.average(arr) # arr[(arr > avg * 2)] = 0 arr[(arr < avg)] = 0 # define an connected neighborhood # http://www.scipy.org/doc/api_docs/SciPy.ndimage.morphology.html#generate_binary_structure # neighborhood = morphology.generate_binary_structure(rank=len(arr.shape), connectivity=2) # apply the local minimum filter; all locations of minimum value # in their neighborhood are set to 1 # http://www.scipy.org/doc/api_docs/SciPy.ndimage.filters.html#minimum_filter neighborhood = np.ones(shape=(3, 3, 3)) local_max = (ndimage.maximum_filter(arr, footprint=neighborhood, mode='constant') == arr) # local_min is a mask that contains the peaks we are # looking for, but also the background. # In order to isolate the peaks we must remove the background from the mask. # # we create the mask of the background background = (arr == 0) # # a little technicality: we must erode the background in order to # successfully subtract it from local_min, otherwise a line will # appear along the background border (artifact of the local minimum filter) # http://www.scipy.org/doc/api_docs/SciPy.ndimage.morphology.html#binary_erosion eroded_background = morphology.binary_erosion(background, structure=neighborhood, border_value=1) # # we obtain the final mask, containing only peaks, # by removing the background from the local_min mask detected_maxima = local_max ^ eroded_background return np.where(detected_maxima)
def SubtractDominantMotion(image1, image2): # Input: # Images at time t and t+1 # Output: # mask: [nxm] # put your implementation here y, x = image1.shape #M = LucasKanadeAffine(image1, image2) #--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--# # ----------- WARNING: !!!!!!!!!!!!!!! ----------------- # # ------------------------------------------------------ # # If you want to run inverse composition affine, you need # to comment out LucasKanadeAffine above, and uncomment # the next 4 lines of code M = InverseCompositionAffine(image1, image2) #--#--#--#--#--#--#--#--#--#--#--#--#--#--#--# img1_mask = image1 * af_trans(np.ones((y, x)), M) img2_aff = af_trans(image2, M) mask = abs(img1_mask - img2_aff) #print (mask) # What value should I make the threshold? # I have tried: # 0.1 | 0.2 | 0.3 # ============================= # Good | Ok | Shit mask[mask >= 0.1] = 1 mask[mask < 0.1] = 0 #plt.imshow(mask) #plt.show() #plt.close() mask = binary_erosion(mask, iterations=1) mask = binary_dilation(mask, iterations=5) return mask
def detect_local_minima(grid_obj): # https://stackoverflow.com/questions/3684484/peak-detection-in-a-2d-array/3689710#3689710 """ Takes an array and detects the troughs using the local maximum filter. Returns a boolean mask of the troughs (i.e. 1 when the pixel's value is the neighborhood maximum, 0 otherwise) This can be very useful in molecular siting later on. """ import scipy.ndimage.filters as filters import scipy.ndimage.morphology as morphology import numpy as np arr = grid_obj.pot_repeat # define an connected neighborhood # http://www.scipy.org/doc/api_docs/SciPy.ndimage.morphology.html#generate_binary_structure neighborhood = morphology.generate_binary_structure(len(arr.shape), 2) # apply the local minimum filter; all locations of minimum value # in their neighborhood are set to 1 # http://www.scipy.org/doc/api_docs/SciPy.ndimage.filters.html#minimum_filter local_min = (filters.minimum_filter(arr, footprint=neighborhood) == arr) # local_min is a mask that contains the peaks we are # looking for, but also the background. # In order to isolate the peaks we must remove the background from the mask. # # we create the mask of the background background = (arr == 0) # # a little technicality: we must erode the background in order to # successfully subtract it from local_min, otherwise a line will # appear along the background border (artifact of the local minimum filter) # http://www.scipy.org/doc/api_docs/SciPy.ndimage.morphology.html#binary_erosion eroded_background = morphology.binary_erosion( background, structure=neighborhood, border_value=1) # # we obtain the final mask, containing only peaks, # by removing the background from the local_min mask detected_minima = local_min - eroded_background return np.where(detected_minima)
def _refine_rooms_info(rooms_info): """ Adjust room masks and edgeness maps """ global_mask = np.zeros(rooms_info[0]['mask'].shape, dtype=np.float32) mask_size = [room_info['mask'].sum() for room_info in rooms_info] orders = np.argsort(mask_size) # sort to put larger rooms first rooms_info = [rooms_info[x] for x in list(orders)] for room_info in rooms_info: room_mask = room_info['mask'].astype(np.float32) room_mask[np.where(global_mask != 0)] = 0 expanded_room_mask = gaussian_filter(room_mask, 5) expanded_room_mask[np.where(expanded_room_mask > 0.1)] = 1 expanded_room_mask[np.where(expanded_room_mask <= 0.1)] = 0 global_mask += expanded_room_mask # expand and binarize edge map room_info['mask'] = room_mask room_edge_map = room_info['edge_map'] room_edge_map[np.where(room_edge_map > 0.5)] = 1 room_edge_map = gaussian_filter(room_edge_map, 3) room_edge_map[np.where(room_edge_map > 0.5)] = 1 room_info['edge_map'] = room_edge_map # filter room instances that are completely overlapped with others rooms_info = [ room_info for room_info in rooms_info if room_info['mask'].sum() > 50 ] for room_info in rooms_info: room_mask = room_info['mask'] shrinked_room_mask = binary_erosion(room_mask, iterations=2).astype( room_mask.dtype) if shrinked_room_mask.sum() > 50: room_mask = shrinked_room_mask room_info['mask'] = room_mask return rooms_info
def erode_mask(mask_image, iterations=1): """ Erode a binary mask file. Parameters ---------- mask_image: Nifti image the mask to erode. iterations: int (optional, default 1) the number of path for the erosion. white_thresh: float (optional, default 1.) threshold to apply to mask_image. Returns ------- erode_mask: Nifti image the eroded binary Nifti image. """ # specific case if iterations == 0: return mask_image # Generate structural element structuring_element = np.array( [[[0, 0, 0], [0, 1, 0], [0, 0, 0]], [[0, 1, 0], [1, 1, 1], [0, 1, 0]], [[0, 0, 0], [0, 1, 0], [0, 0, 0]]]) # Erode source mask source_data = mask_image.get_data() erode_data = binary_erosion(source_data, iterations=iterations, structure=structuring_element) erode_data = erode_data.astype(source_data.dtype) erode_mask = ni.Nifti1Image(erode_data, mask_image.get_affine()) return erode_mask
def cloudShapes(im): """ Function to get the Contours of clouds from Radar Data. Args: im: Array where clouds have only one value (return of countClouds) Returns: np.array where the contours of clouds are marked as 1, the rest is set to np.nan. The value [0,0] of the array is set to -9999 for the right coloring later. """ im[np.where(im != 0)] = 1 im1 = binary_erosion(im,iterations=2) im = np.subtract(im,im1) im[np.where(im == 0)] = np.nan im[0,0] = -9999 return im