def grow_regions(input, output, window=3, val=50): """ Threshold water classification and grow lakes by 1 pixel""" print(f"Growing regions (window = {window})") p50 = threshold(input, val=val) # Write out50 = np.empty_like(p50) modal(p50, selem=np.ones((window, window)), out=out50) p50 = None maximum_filter(out50, size=window, output=out50) du.write_array_like(input, output, out50, dtype=2)
def modefilter(input, output, window=7): """ Threshold water classification at 50% water likelihood""" print(f"Running mode filter (window = {window})") # split into 50% and 100% water p50 = threshold(input, val=50) # Write out50 = np.empty_like(p50) modal(p50, selem=np.ones((window, window)), out=out50) p50 = None du.write_array_like(input, output, out50, dtype=2)
def check_all(): selem = morphology.disk(1) refs = np.load( os.path.join(skimage.data_dir, "rank_filter_tests.npz")) assert_equal(refs["autolevel"], rank.autolevel(self.image, selem)) assert_equal(refs["autolevel_percentile"], rank.autolevel_percentile(self.image, selem)) assert_equal(refs["bottomhat"], rank.bottomhat(self.image, selem)) assert_equal(refs["equalize"], rank.equalize(self.image, selem)) assert_equal(refs["gradient"], rank.gradient(self.image, selem)) assert_equal(refs["gradient_percentile"], rank.gradient_percentile(self.image, selem)) assert_equal(refs["maximum"], rank.maximum(self.image, selem)) assert_equal(refs["mean"], rank.mean(self.image, selem)) assert_equal(refs["geometric_mean"], rank.geometric_mean(self.image, selem)), assert_equal(refs["mean_percentile"], rank.mean_percentile(self.image, selem)) assert_equal(refs["mean_bilateral"], rank.mean_bilateral(self.image, selem)) assert_equal(refs["subtract_mean"], rank.subtract_mean(self.image, selem)) assert_equal(refs["subtract_mean_percentile"], rank.subtract_mean_percentile(self.image, selem)) assert_equal(refs["median"], rank.median(self.image, selem)) assert_equal(refs["minimum"], rank.minimum(self.image, selem)) assert_equal(refs["modal"], rank.modal(self.image, selem)) assert_equal(refs["enhance_contrast"], rank.enhance_contrast(self.image, selem)) assert_equal(refs["enhance_contrast_percentile"], rank.enhance_contrast_percentile(self.image, selem)) assert_equal(refs["pop"], rank.pop(self.image, selem)) assert_equal(refs["pop_percentile"], rank.pop_percentile(self.image, selem)) assert_equal(refs["pop_bilateral"], rank.pop_bilateral(self.image, selem)) assert_equal(refs["sum"], rank.sum(self.image, selem)) assert_equal(refs["sum_bilateral"], rank.sum_bilateral(self.image, selem)) assert_equal(refs["sum_percentile"], rank.sum_percentile(self.image, selem)) assert_equal(refs["threshold"], rank.threshold(self.image, selem)) assert_equal(refs["threshold_percentile"], rank.threshold_percentile(self.image, selem)) assert_equal(refs["tophat"], rank.tophat(self.image, selem)) assert_equal(refs["noise_filter"], rank.noise_filter(self.image, selem)) assert_equal(refs["entropy"], rank.entropy(self.image, selem)) assert_equal(refs["otsu"], rank.otsu(self.image, selem)) assert_equal(refs["percentile"], rank.percentile(self.image, selem)) assert_equal(refs["windowed_histogram"], rank.windowed_histogram(self.image, selem))
def lone_object_filter(image, min_size=2, connectivity=1, kernel_size=3): """ Replaces isolated, contiguous regions of values in a raster with values representing the surrounding pixels. More specifically, this reduces noise in a raster by setting contiguous regions of values of a specified minimum size to the modal value in a specified neighborhood. The default argument values filter out lone, singular pixels. This filter is not idempotent, so it may need to be applied repeatedly until the output stops changing or the results are acceptable. Args: image (numpy.ndarray): The image to filter. min_size (int): Defines the minimum number of contiguous pixels that will not be set to the modal value of their neighborhood. Setting this to 1 is pointless, since this function will then do nothing to the raster. connectivity (int): The maximum distance between any two pixels such that they are considered one group. For example, a connectivity of 1 considers only adjacent values to be within one group, but a connectivity of 2 also considers diagonally connected values to be within one group. kernel_size (int or float): The diameter of the circular kernel to use for the modal filter. If there are still large, contiguous regions of lone pixels, increase this value to remove them. Note that the larger this value is, the more detail may be lost in the image. Returns: The filtered image. Authors: Andrew Lubawy ([email protected])\n John Rattz ([email protected]) """ assert kernel_size % 2 == 1, "The parameter `kernel_size` must be an odd number." modal_filtered = modal(image, create_circular_mask(kernel_size, kernel_size)) da = xr.DataArray(image) for i, val in enumerate(np.unique(image)): layer = remove_small_objects(image == val, min_size=min_size, connectivity=connectivity) filtered = da.where(layer) if i == 0 else filtered.combine_first( da.where(layer)) filtered.values[np.isnan(filtered.values)] = modal_filtered[np.isnan( filtered.values)] return filtered.values
def majority_filter(self, classes_map, selems): """ :param classes_map: 2 dim image :param selems: elements: [disk(1),square(2)...] :return: """ from skimage.filters.rank import modal # from skimage.morphology import disk,square classes_map__ = classes_map.astype(np.uint16) # convert dtype to uint16 out = classes_map__ for selem in selems: out = modal(classes_map__, selem) classes_map__ = out return out.astype(np.int8)
def check_all(): np.random.seed(0) image = np.random.rand(25, 25) selem = morphology.disk(1) refs = np.load(os.path.join(skimage.data_dir, "rank_filter_tests.npz")) assert_equal(refs["autolevel"], rank.autolevel(image, selem)) assert_equal(refs["autolevel_percentile"], rank.autolevel_percentile(image, selem)) assert_equal(refs["bottomhat"], rank.bottomhat(image, selem)) assert_equal(refs["equalize"], rank.equalize(image, selem)) assert_equal(refs["gradient"], rank.gradient(image, selem)) assert_equal(refs["gradient_percentile"], rank.gradient_percentile(image, selem)) assert_equal(refs["maximum"], rank.maximum(image, selem)) assert_equal(refs["mean"], rank.mean(image, selem)) assert_equal(refs["mean_percentile"], rank.mean_percentile(image, selem)) assert_equal(refs["mean_bilateral"], rank.mean_bilateral(image, selem)) assert_equal(refs["subtract_mean"], rank.subtract_mean(image, selem)) assert_equal(refs["subtract_mean_percentile"], rank.subtract_mean_percentile(image, selem)) assert_equal(refs["median"], rank.median(image, selem)) assert_equal(refs["minimum"], rank.minimum(image, selem)) assert_equal(refs["modal"], rank.modal(image, selem)) assert_equal(refs["enhance_contrast"], rank.enhance_contrast(image, selem)) assert_equal(refs["enhance_contrast_percentile"], rank.enhance_contrast_percentile(image, selem)) assert_equal(refs["pop"], rank.pop(image, selem)) assert_equal(refs["pop_percentile"], rank.pop_percentile(image, selem)) assert_equal(refs["pop_bilateral"], rank.pop_bilateral(image, selem)) assert_equal(refs["sum"], rank.sum(image, selem)) assert_equal(refs["sum_bilateral"], rank.sum_bilateral(image, selem)) assert_equal(refs["sum_percentile"], rank.sum_percentile(image, selem)) assert_equal(refs["threshold"], rank.threshold(image, selem)) assert_equal(refs["threshold_percentile"], rank.threshold_percentile(image, selem)) assert_equal(refs["tophat"], rank.tophat(image, selem)) assert_equal(refs["noise_filter"], rank.noise_filter(image, selem)) assert_equal(refs["entropy"], rank.entropy(image, selem)) assert_equal(refs["otsu"], rank.otsu(image, selem)) assert_equal(refs["percentile"], rank.percentile(image, selem)) assert_equal(refs["windowed_histogram"], rank.windowed_histogram(image, selem))
def lone_object_filter(image, min_size=2, connectivity=1, kernel_size=3, unique_vals=None): """ Replaces isolated, contiguous regions of values in a raster with values representing the surrounding pixels. More specifically, this reduces noise in a raster by setting contiguous regions of values greater than a specified minimum size to the modal value in a specified neighborhood. The default argument values filter out lone, singular pixels. This filter is not idempotent, so it may need to be applied repeatedly until the output stops changing or the results are acceptable. Args: image (numpy.ndarray): The image to filter. Must not contain NaNs. min_size (int): Defines the minimum number of contiguous pixels that will not be set to the modal value of their neighborhood. Must be greater than 2. Setting this to 1 is pointless, since this function will then do nothing to the raster. connectivity (int): The maximum distance between any two pixels such that they are considered one group. For example, a connectivity of 1 considers only adjacent values to be within one group (contiguous areas), but a connectivity of 2 also considers diagonally connected values to be within one group. Must be greater than 0. kernel_size (int or float): The diameter of the circular kernel to use for the modal filter. If there are still pixels that should be set to the modal value of their neighborhood, increase this value to remove them. Note that the larger this value is, the more detail will tend to be lost in the image and the slower this function will run. unique_vals: numpy.ndarray The unique values in `image`. If this is not supplied, the unique values will be determined on each call. Returns: The filtered image. Authors: Andrew Lubawy ([email protected])\n John Rattz ([email protected]) """ import dask from .clean_mask import create_circular_mask from skimage.filters.rank import modal from skimage.morphology import remove_small_objects from .unique import dask_array_uniques assert kernel_size % 2 == 1, "The parameter `kernel_size` must be an odd number." image_min, image_max = image.min(), image.max() image_dtype = image.dtype image = (((image - image_min) / (image_max - image_min)) * 255).astype( np.uint8) if isinstance(image, np.ndarray): modal_filtered = modal(image, create_circular_mask(kernel_size, kernel_size)) elif isinstance(image, dask.array.core.Array): modal_filtered = image.map_blocks(modal, selem=create_circular_mask( kernel_size, kernel_size)) image_da = xr.DataArray(image) if unique_vals is None: unique_vals = [] if isinstance(image, np.ndarray): unique_vals = np.unique(image) elif isinstance(image, dask.array.core.Array): unique_vals = dask_array_uniques(image) else: # Scale to the range [0,1]. unique_vals = (((unique_vals - image_min) / (image_max - image_min)) * 255).astype(np.uint8) for i, val in enumerate(unique_vals): # Determine the pixels with this value that will not be filtered (True to keep). if isinstance(image, np.ndarray): layer = remove_small_objects(image == val, min_size=min_size, connectivity=connectivity) elif isinstance(image, dask.array.core.Array): layer = (image == val).map_blocks(remove_small_objects, min_size=min_size, connectivity=connectivity) # Select the values from the image that will remain (filter it). filtered = image_da.where(layer) if i == 0 else filtered.combine_first( image_da.where(layer)) # Fill in the removed values with their local modes. filtered_nan_mask = xr_nan(filtered).data filtered = filtered.where(~filtered_nan_mask, modal_filtered) filtered = ((filtered / 255) * (image_max - image_min) + image_min).astype(image_dtype) return filtered.data
PredictedTiles = ConvNetmodel.predict(I_tiles, batch_size=32, verbose=Chatty) #Convert the convnet one-hot predictions to a new class label image PredictedTiles[PredictedTiles < RecogThresh] = 0 PredictedClass = class_prediction_to_image(Class, PredictedTiles, size) PredictedClass = SimplifyClass(PredictedClass, ClassKey) #Set classes to 0 if they do not have MinTiles detected by the CNN #for c in range(0,NClasses+1): # count = np.sum(PredictedClass.reshape(-1,1) == c) # if count <= MinTiles*size*size: # PredictedClass[PredictedClass == c] = 0 if MinTiles > 0: PredictedClass = modal( np.uint8(PredictedClass), np.ones((2 * MinTiles * size + 1, 2 * MinTiles * size + 1))) #PredictedClass = modal(np.uint8(PredictedClass), disk(2*(MinTiles*size*size)+1)) #Prep the pixel data from the cropped image and new class label image print('Processing Entropy and Median filter') Entropy = entropy(Im3D[:, :, 0], selem=np.ones([11, 11]), shift_x=3, shift_y=0) MedImage = ColourFilter(Im3D) #Median filter on all 3 bands rv = MedImage[:, :, 0].reshape(-1, 1) #Split and vectorise the bands gv = MedImage[:, :, 1].reshape(-1, 1) bv = MedImage[:, :, 2].reshape(-1, 1) #Vectorise the bands, use the classification prdicted by the CNN #m = np.ndarray.flatten(PredictedClass).reshape(-1,1)
def cleanup_mask(mask, n): """Eliminate small islands in the mask""" m = minify(mask, n).astype(np.uint8) m = m & modal(m, ELEMENT) return oversample(m, n).astype(bool)
def processAlgorithm(self, parameters, context, feedback): try: import networkx as nx from osgeo import gdal as osgdal from skimage.io import imread from skimage.color import rgb2gray from skimage.filters import threshold_local, threshold_otsu from skimage.util import invert from skimage.morphology import disk from skimage.filters.rank import modal, threshold_percentile, otsu from skimage.util import img_as_ubyte except Exception as e: feedback.reportError( QCoreApplication.translate('Error', '%s' % (e))) feedback.reportError(QCoreApplication.translate('Error', ' ')) feedback.reportError( QCoreApplication.translate( 'Error', 'Error loading modules - please install the necessary dependencies' )) return {} rlayer = self.parameterAsRasterLayer(parameters, self.Raster, context) inv = parameters[self.inv] block_size = parameters[self.blocks] adaptMethod = parameters[self.adaptMethod] mode = parameters[self.blur] method = parameters[self.Method] p = parameters[self.percent] aMethod = {0: "gaussian", 1: "mean", 2: "median"} outputRaster = self.parameterAsOutputLayer(parameters, self.outRaster, context) fname = ''.join( random.choice(string.ascii_lowercase) for i in range(10)) outFname = os.path.join(tempfile.gettempdir(), '%s.tif' % (fname)) rect = rlayer.extent() dp = rlayer.dataProvider() raster = dp.dataSourceUri() img = imread(raster) if dp.bandCount() == 1: grayscale = img else: try: grayscale = rgb2gray(img) except Exception as e: feedback.reportError( QCoreApplication.translate('Error', str(e))) feedback.reportError(QCoreApplication.translate('Error', ' ')) feedback.reportError( QCoreApplication.translate( 'Error', 'Failed to convert image from RGB to grayscale')) return {} if inv: grayscale = invert(grayscale) if block_size > 0 and block_size % 2 == 0: block_size += 1 feedback.reportError( QCoreApplication.translate( 'Info', 'Warning: Algorithm requires an odd value for the block size parameter - selecting a value of %s' % (block_size))) nrows, ncols = grayscale.shape if method == 0: if block_size > 0: grayscale = img_as_ubyte(grayscale) thresh = otsu(grayscale, disk(block_size)) binary = (grayscale < thresh).astype(float) else: thresh = threshold_otsu(grayscale) binary = (grayscale < thresh).astype(float) else: if block_size == 0.0: block_size = int((nrows * 0.01) * (ncols * 0.01)) if block_size % 2 == 0: block_size += 1 feedback.pushInfo( QCoreApplication.translate( 'Info', 'Automatically selecting a block size of %s' % (block_size))) if method == 1: local_thresh = threshold_local(image=grayscale, block_size=block_size, method=aMethod[adaptMethod]) binary = (grayscale < local_thresh).astype(float) else: thresh = threshold_percentile(grayscale, disk(block_size), p0=p) binary = (grayscale > thresh).astype(float) if mode > 0: binary = modal(binary, disk(mode)) binary = (binary > 1).astype(float) xres = rlayer.rasterUnitsPerPixelX() yres = rlayer.rasterUnitsPerPixelY() driver = osgdal.GetDriverByName('GTiff') dataset = driver.Create( outputRaster, ncols, nrows, 1, osgdal.GDT_Float32, ) dataset.SetGeoTransform( (rect.xMinimum(), xres, 0, rect.yMaximum(), 0, -yres)) wkt_prj = rlayer.crs().toWkt() dataset.SetProjection(wkt_prj) band = dataset.GetRasterBand(1) band.SetNoDataValue(0) band.WriteArray(binary) dataset, band = None, None return {self.outRaster: outputRaster}
for r in range(0, Im3D.shape[0] - Kernel_size): if r % 1000 == 0: print("%d: %s" % (r, 'of ' + str(Im3D.shape[0]))) #print('row '+str(r)+' of '+str(Im3D.shape[0])) Irow = Im3D[r:r + Kernel_size, :, :] #tile the image Tiles = np.squeeze(slide_rasters_to_tiles( Irow, Kernel_size)) / NormFactor Predicted = model.predict(Tiles, batch_size=25000) PredictedSubImage[r, :] = np.argmax(Predicted, axis=1) if SmallestElement > 0: PredictedSubImage = modal( np.uint8(PredictedSubImage), disk(2 * SmallestElement)) #clean up the class with a mode filter PredictedImage = np.zeros((Im3D.shape[0], Im3D.shape[1])) PredictedImage[Kernel_size // 2:Im3D.shape[0] - Kernel_size // 2, Kernel_size // 2:Im3D.shape[1] - Kernel_size // 2] = PredictedSubImage Predicted = None PredictedSubImage = None #close the TF session session.close() # # ============================================================================= #'''Detect Calving front from binary morphology operations and active contours''' print('Detecting Calving Front') try: import feather
def modal_skimage(img): img = to_gray(img) img = img.astype(np.uint8) edges = modal(img, disk(6)) return edges
def segmentation(model=None, params=None, src=None, bands=[1, 2, 3], image=None, mask=None, modal_radius=None, sieve_size=250): """ Segment the image. Segment the image using an algorithm from sklearn.segmentation. Parameters ---------- model: sklearn.segmentation model A model from sklearn.segmentation (e.g., slic, slic0, felzenswalb) params: sklearn.segmentation model parameters The unique parameters for the selected segmentation algorithm. Will be passed to the model as the kwargs argument. src: Rasterio datasource A rasterio-style datasource, created using: with rasterio.open('path') as src. There must be at least 3 bands of image data. If there are more than 3 bands, the first three will be used (see 'bands' parameter). This parameter is optional. **If it is not provided, then image and transform must be supplied.--really?? Not any more, right?** bands: array of integers The array of 3 bands to read from src as the RGB image for segmentation. image: numpy.array A 3-band (RGB) image used for segmentation. The shape of the image must be ordered as follows: (bands, rows, columns). This parameter is optional. mask: numpy.array A 1-band image mask. The shape of the mask must be ordered as follows: (rows, columns). This parameter is optional. modal_radius: integer Integer representing the radius of a raster disk (i.e., circular roving window). Optional. If not set, no modal filter will be applied. sieve_size: integer An integer representing the smallest number of pixels that will be included as a unique segment. Segments this size or smaller will be merged with the neighboring segment with the most pixels. Returns ------- numpy.array A numpy array arranged as rasterio would read it (bands=1, rows, cols) so it's ready to be written by rasterio """ if src is not None: img = bsq_to_bip(src.read(bands, masked=True)) mask = src.read_masks(1) mask[mask > 0] = 1 else: img = bsq_to_bip(image) mask[mask > 255] = 1 output = model(img, **params).astype('int32') while np.ndarray.min(output) < 1: output += 1 if modal_radius != None: output = modal(output.astype('int16'), selem=disk(modal_radius), mask=mask) # output = features.sieve(output, sieve_size, mask=mask, # connectivity=8) * mask output = features.sieve(output, sieve_size, mask=mask) * mask # output = label(output, connectivity=2) output = label(output, connectivity=1) output = bip_to_bsq(output[:, :, np.newaxis]) * mask return output
original_image = color.rgb2gray(data.camera()) plt.imshow(original_image, cmap=plt.cm.gray) filtered_images = [] filtered_images.append(sfr.autolevel(original_image, disk(5))) filtered_images.append(sfr.bottomhat(original_image, disk(5))) filtered_images.append(sfr.tophat(original_image, disk(5))) filtered_images.append(sfr.enhance_contrast(original_image, disk(5))) filtered_images.append(sfr.entropy(original_image, disk(5))) filtered_images.append(sfr.equalize(original_image, disk(5))) filtered_images.append(sfr.gradient(original_image, disk(5))) filtered_images.append(sfr.maximum(original_image, disk(5))) filtered_images.append(sfr.minimum(original_image, disk(5))) filtered_images.append(sfr.mean(original_image, disk(5))) filtered_images.append(sfr.median(original_image, disk(5))) filtered_images.append(sfr.modal(original_image, disk(5))) filtered_images.append(sfr.otsu(original_image, disk(5))) filtered_images.append(sfr.threshold(original_image, disk(5))) filtered_images.append(sfr.subtract_mean(original_image, disk(5))) filtered_images.append(sfr.sum(original_image, disk(5))) name_list = [ 'autolevel', 'bottomhat', 'tophat', 'enhance_contrast', 'entropy', 'equalize', 'gradient', 'maximum', 'minimum', 'mean', 'median', 'modal', 'otsu', 'threshold', 'subtract_mean', 'sum' ] fig, axes = plt.subplots(nrows=4, ncols=4, figsize=(8, 8)) axes = axes.ravel() for ax, img, name in zip(axes, filtered_images, name_list): ax.imshow(img, cmap=plt.cm.gray, interpolation='nearest')
def lone_object_filter(image, min_size=2, connectivity=1, kernel_size=3): """ Replaces isolated, contiguous regions of values in a raster with values representing the surrounding pixels. More specifically, this reduces noise in a raster by setting contiguous regions of values greater than a specified minimum size to the modal value in a specified neighborhood. The default argument values filter out lone, singular pixels. This filter is not idempotent, so it may need to be applied repeatedly until the output stops changing or the results are acceptable. Args: image (numpy.ndarray): The image to filter. Must not contain NaNs. min_size (int): Defines the minimum number of contiguous pixels that will not be set to the modal value of their neighborhood. Must be greater than 2. Setting this to 1 is pointless, since this function will then do nothing to the raster. connectivity (int): The maximum distance between any two pixels such that they are considered one group. For example, a connectivity of 1 considers only adjacent values to be within one group, but a connectivity of 2 also considers diagonally connected values to be within one group. Must be greater than 0. kernel_size (int or float): The diameter of the circular kernel to use for the modal filter. If there are still contiguous regions of pixels that should be set to the modal value of their neighborhood, increase this value to remove them. This parameter generally should scale roughly with the square root of the `min_size` parameter. Note that the larger this value is, the more detail may be lost in the image and the slower this function will run. Returns: The filtered image. Authors: Andrew Lubawy ([email protected])\n John Rattz ([email protected]) """ assert kernel_size % 2 == 1, "The parameter `kernel_size` must be an odd number." image_min, image_max = image.min(), image.max() image_dtype = image.dtype image = np.interp(image, [image_min, image_max], [0, 255]).astype(np.uint8) modal_filtered = modal(image, create_circular_mask(kernel_size, kernel_size)) da = xr.DataArray(image) for i, val in enumerate(np.unique(image)): # Determine the pixels with this value that will be not be filtered (True to keep). layer = remove_small_objects(image == val, min_size=min_size, connectivity=connectivity) # Select the values from the image that will remain (filter it). filtered = da.where(layer) if i == 0 else filtered.combine_first( da.where(layer)) # Fill in the removed values with their local modes. filtered_nan_mask = np.isnan(filtered.values) filtered.values[filtered_nan_mask] = modal_filtered[filtered_nan_mask] filtered.values = np.interp(filtered.values, [0, 255], [image_min, image_max]).astype(image_dtype) return filtered.values