def apply_ACWE(img): ''' ''' image = img_as_float(img) init_ls = checkerboard_level_set(image.shape, 6) # List with intermediate results for plotting the evolution evolution = [] callback = store_evolution_in(evolution) ls = morphological_chan_vese(image, 35, init_level_set=init_ls, smoothing=3, iter_callback=callback) fig, axes = plt.subplots(2, 2, figsize=(8, 8)) ax = axes.flatten() ax[1].imshow(ls, cmap="gray") ax[1].set_axis_off() contour = ax[1].contour(evolution[2], [0.5], colors='g') contour.collections[0].set_label("Iteration 2") contour = ax[1].contour(evolution[7], [0.5], colors='y') contour.collections[0].set_label("Iteration 7") contour = ax[1].contour(evolution[-1], [0.5], colors='r') contour.collections[0].set_label("Iteration 35") ax[1].legend(loc="upper right") title = "Morphological ACWE evolution" ax[1].set_title(title, fontsize=12)
def process_file(filename): """Process contour method""" image = io.imread(filename) init_ls = checkerboard_level_set(image.shape, 5) evolution = [] callback = store_evolution_in(evolution) ls = morphological_chan_vese(image, iterations, init_level_set=init_ls, smoothing=1, iter_callback=callback) return evolution[-1]
def calculate_profile(image): # Initial level set init_ls = checkerboard_level_set(image.shape, 5) # List with intermediate results for plotting the evolution ls = morphological_chan_vese(image, 10, init_level_set=init_ls, smoothing=5) return ls
def morphological_snakes(img, verts, SHOW_RESULTS=False): from skimage import data, img_as_float from skimage.segmentation import (morphological_chan_vese, morphological_geodesic_active_contour, inverse_gaussian_gradient, checkerboard_level_set) img = rgb2gray(img.copy()) image = img_as_float(img) # Initial level set init_ls = checkerboard_level_set(img.shape, 6) # verts = np.array(verts).reshape((-1,1,2)).astype(np.int32) # init_ls = np.zeros(image.shape, dtype=np.int8) # cv2.drawContours(init_ls, [verts], -1, 1, 2) plt.imshow(init_ls) plt.show() # List with intermediate results for plotting the evolution evolution = [] callback = store_evolution_in(evolution) ls = morphological_chan_vese(image, 32, init_level_set=init_ls, smoothing=3, iter_callback=callback) fig, axes = plt.subplots(2, 2, figsize=(8, 8)) ax = axes.flatten() ax[0].imshow(image, cmap="gray") ax[0].set_axis_off() ax[0].contour(ls, [0.5], colors='r') ax[0].set_title("Morphological ACWE segmentation", fontsize=12) ax[1].imshow(ls, cmap="gray") ax[1].set_axis_off() contour = ax[1].contour(evolution[2], [0.5], colors='g') contour.collections[0].set_label("Iteration 2") contour = ax[1].contour(evolution[7], [0.5], colors='y') contour.collections[0].set_label("Iteration 7") contour = ax[1].contour(evolution[-1], [0.5], colors='r') contour.collections[0].set_label("Iteration 32") ax[1].legend(loc="upper right") title = "Morphological ACWE evolution" ax[1].set_title(title, fontsize=12) return ls
def store_evolution_in(lst): def _store(x): lst.append(np.copy(x)) return _store max = np.amax(image) eimage = (image * 255 / max)**5 init_ls = checkerboard_level_set(image.shape, 6) evolution = [] callback = store_evolution_in(evolution) ls = morphological_chan_vese(eimage, 35, init_level_set=init_ls, smoothing=3, iter_callback=callback) l = ls
def apply_ACWE(img): ''' Segments largest region using ACWE. ''' init_ls = checkerboard_level_set(img.shape, 6) evolution = [] callback = store_evolution_in(evolution) l = morphological_chan_vese(img, 3, init_level_set=init_ls, smoothing=1, iter_callback=callback) #plt.figure(figsize=(9, 3)) #plt.imshow(ls, cmap="gray") #plt.contour(evolution[3], [0.5], colors='y') return l
def morphChaneVese(image, itr=120, p=3): """ calculate the segmentation mask of the image using morphological_chan_vese built in function. Args: img: RGB image to calculate the segmentation mask over it. itr: number of iterations used to get the segmentation mask, default = 120. p: square width of the initial segmentation mask, default = 3. Returns: Binary image represents the filled object. """ image = copy.deepcopy(image) #turn RGB image to gray scaled one. image = rgb2gray(image) #apply hestogram equalization to enhance the image. image = equalize_hist(image) #set the initial segmentation mask base on p value. init_ls = checkerboard_level_set(image.shape, p) #calculate the mask using morphological_chan_vese algorithm. mask = morphological_chan_vese(image, iterations=itr, init_level_set=init_ls, smoothing=2) #return the calculated mask return mask
def segment_with_level_sets(img): """ Function to perform segmentation with level sets. img_gray should not contain hairs nor black zones Parameters ---------- binary Binary mask with result of level sets Returns ------- output_image Binary image with segmentation result """ #First, find out if it is necessary to appy inpainting to remove black zones img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) r1 = img_gray[:5, :5] r2 = img_gray[:5, -5:] r3 = img_gray[-5:, :5] r4 = img_gray[-5:, -5:] if (np.mean(r1) < 50 or np.mean(r2) < 50 or np.mean(r3) < 50 or np.mean(r4) < 50 ): #If zones of the corners are too dark, apply ellipse inpainting elliptical_mask = 1 - mask_eliptical(img_gray) to_process = cv.inpaint(img_gray, elliptical_mask, 21, cv.INPAINT_NS) else: to_process = img_gray init_ls = checkerboard_level_set(img_gray.shape, 6) ls = morphological_chan_vese(to_process, 35, init_level_set=init_ls, smoothing=3) segmented = find_segmented(ls) return segmented
def get_snake(file, plot=False): def store_evolution_in(lst): def _store(x): lst.append(np.copy(x)) return _store evolution = [] callback = store_evolution_in(evolution) raster_filepath = os.path.dirname(file) + "/" raster_filename = os.path.basename(file) with rasterio.open(file, driver='GTiff') as src: kwargs = src.meta kwargs.update(count=1, dtype=rasterio.uint8) input = src.read(1).astype(rasterio.uint8) if plot: plt.imshow(input, cmap='gray') plt.show() init_lvl_set = checkerboard_level_set(input.shape) lvl_set = morphological_chan_vese(input, 100, init_level_set=init_lvl_set, iter_callback=callback, smoothing=1) if plot: plt.imshow(lvl_set, cmap='gray') plt.show() noise_reduced = morph_transform(lvl_set.astype(rasterio.uint8), 9, 9) if plot: plt.imshow(noise_reduced) plt.show() out_filename = raster_filepath + raster_filename.split( sep=".")[0] + "_chan_vese.tif" with rasterio.open(out_filename, 'w', **kwargs) as dst: dst.write_band(1, noise_reduced.astype(rasterio.uint8)) return lvl_set
I = pydicom.dcmread('000001.dcm') I = I.pixel_array x = I.copy() y = x.resize((256, 256)) max = np.amax(I) sigma = 0.08 sigma_est = np.mean(estimate_sigma(I, multichannel=False)) patch_kw = dict(patch_size=5, patch_distance=6, multichannel=False) I = denoise_nl_means(I, h=1.15 * sigma_est, fast_mode=False, **patch_kw) image = np.copy(I) print(image[10, 10]) print(image[100, 150]) print(np.amax(image[50, 190:210])) print(np.amax(image)) max = np.amax(image) eimage = (image * 255 / max)**5 #eimage = image ** (3) init_ls = checkerboard_level_set(image.shape, 6) evolution = [] callback = store_evolution_in(evolution) ls = morphological_chan_vese(eimage, 35, init_level_set=init_ls, smoothing=3, iter_callback=callback) plt.imshow(image, cmap=plt.cm.bone) plt.contour(ls, [0.5], colors='r') plt.show()
def execute(self, arg, trans): # Number of Chan-Vese iterations nIter = 20 std = 1.5 # [mm], original squareSize = 1.5 # [mm] saveMetaImage = False savePNGImage = False # Actual work - now done using SciPy # Gaussian smoothing dx, dy, dz = arg.GetSpacing() sx, sy = std / dx, std / dy smoother = vtk.vtkImageGaussianSmooth() smoother.SetStandardDeviations(sx, sy) smoother.SetDimensionality(2) smoother.SetInputData(arg) smoother.Update() if savePNGImage: writer = vtk.vtkPNGWriter() writer.SetFileName('./output.png') writer.SetInputConnection(smoother.GetOutputPort()) writer.Write() if saveMetaImage: # Save to disk writer = vtk.vtkMetaImageWriter() writer.SetFileName('./output.mhd') writer.SetInputConnection(smoother.GetOutputPort()) writer.Write() smoothedData = smoother.GetOutput() # Convert VTK to NumPy image dims = arg.GetDimensions() vtk_array = smoothedData.GetPointData().GetScalars() nComponents = vtk_array.GetNumberOfComponents() npData = vtk_to_numpy(vtk_array).reshape( dims[2], dims[1], dims[0], nComponents)[:, :, :, 0].reshape(dims[1], dims[0]) # Seed for active contours iSquareSize = int(squareSize / dx) init_ls = checkerboard_level_set(npData.shape, iSquareSize) contours = morphological_chan_vese(npData, nIter, init_level_set=init_ls, smoothing=2) # Add singleton to get 3-dimensional data data = contours[None, :] # Convert Numpy to VTK data importer = vtk.vtkImageImport() importer.SetDataScalarType(vtk.VTK_SIGNED_CHAR) importer.SetDataExtent(0, data.shape[2] - 1, 0, data.shape[1] - 1, 0, data.shape[0] - 1) importer.SetWholeExtent(0, data.shape[2] - 1, 0, data.shape[1] - 1, 0, data.shape[0] - 1) importer.SetImportVoidPointer(data.data) importer.Update() vtkData = importer.GetOutput() vtkData.SetSpacing(smoothedData.GetSpacing()) vtkData.SetOrigin(0, 0, 0) # Contour filter contourFilter = vtk.vtkContourFilter() iso_value = 0.5 contourFilter.SetInputData(vtkData) contourFilter.SetValue(0, iso_value) contourFilter.Update() contourFilter.ReleaseDataFlagOn() # Compute normals normals = vtk.vtkPolyDataNormals() normals.SetInputConnection(contourFilter.GetOutputPort()) normals.SetFeatureAngle(60.0) normals.ReleaseDataFlagOn() # Join line segments stripper = vtk.vtkStripper() stripper.SetInputConnection(normals.GetOutputPort()) stripper.ReleaseDataFlagOn() stripper.Update() # Transform data from scaled screen to world coordinates transformFilter = vtk.vtkTransformPolyDataFilter() transformFilter.SetInputConnection(stripper.GetOutputPort()) transformFilter.SetTransform(trans) transformFilter.Update() result = transformFilter.GetOutput() # Emit done with output self.done.emit(result)
def segment_lesion(image, mode="KMeans"): ## Unsupervised Segmentation # K-Means Clustering if (mode == "KMeans"): # K-Means Clustering deim = denoise(cv2.cvtColor(image, cv2.COLOR_RGB2GRAY), weight=150) kmeans = KMeans(n_clusters=2, random_state=0, n_jobs=-1).fit(deim.reshape(-1, 1)) mask = (kmeans.labels_).reshape(deim.shape[0], deim.shape[1]).astype('uint8') # Expectation-Maximization Gaussian Mixture Model elif (mode == "EM"): # K-Means Clustering feature_vector = (denoise(cv2.cvtColor(image, cv2.COLOR_RGB2GRAY), weight=150)).reshape(-1, 1) kmeans = KMeans(n_clusters=2, random_state=0, n_jobs=-1).fit(feature_vector) KMpredict = kmeans.predict(feature_vector) # Expectation Step: Initialization with K-Means KM_BG = feature_vector[KMpredict == 0] KM_FG = feature_vector[KMpredict == 1] # Expectation Step: Mean and Covariance mean_BG = np.mean(KM_BG, axis=0) mean_FG = np.mean(KM_FG, axis=0) covar_BG = np.cov(KM_BG, rowvar=False) covar_FG = np.cov(KM_FG, rowvar=False) # Expectation Step: Prior Probabilities prob_BG = KM_BG.shape[0] / feature_vector.shape[0] prob_FG = KM_FG.shape[0] / feature_vector.shape[0] # Iterative Update min_change = 0.01 max_steps = 5 for i in range(max_steps): # Expectation Step: Probability Density Function PDF_BG = multivariate_normal.pdf(feature_vector, mean=mean_BG, cov=covar_BG) PDF_FG = multivariate_normal.pdf(feature_vector, mean=mean_FG, cov=covar_FG) weights_BG = (prob_BG * PDF_BG) / ((prob_FG * PDF_FG) + (prob_BG * PDF_BG)) weights_FG = (prob_FG * PDF_FG) / ((prob_FG * PDF_FG) + (prob_BG * PDF_BG)) weights = np.concatenate( (weights_BG.reshape(-1, 1), weights_FG.reshape(-1, 1)), axis=1) log_B = sum((np.log(sum(weights)))) # Maximization Step: New Probabilities _, counts = np.unique(np.argmax(weights, axis=1), return_counts=True) prob_BG = counts[0] / feature_vector.shape[0] prob_FG = counts[1] / feature_vector.shape[0] # Maximization Step: New Mean and Covariance mean_BG = (1 / counts[0]) * (weights[:, 0] @ feature_vector) mean_FG = (1 / counts[1]) * (weights[:, 1] @ feature_vector) covar_BG = (1 / counts[0]) * ( weights[:, 0] * np.transpose(feature_vector - mean_BG)) @ ( feature_vector - mean_BG) covar_FG = (1 / counts[1]) * ( weights[:, 1] * np.transpose(feature_vector - mean_FG)) @ ( feature_vector - mean_FG) # Maximization Step: Probability Density Function PDF_BG = multivariate_normal.pdf(feature_vector, mean=mean_BG, cov=covar_BG) PDF_FG = multivariate_normal.pdf(feature_vector, mean=mean_FG, cov=covar_FG) weights_BG = (prob_BG * PDF_BG) / ((prob_FG * PDF_FG) + (prob_BG * PDF_BG)) weights_FG = (prob_FG * PDF_FG) / ((prob_FG * PDF_FG) + (prob_BG * PDF_BG)) weights = np.concatenate( (weights_BG.reshape(-1, 1), weights_FG.reshape(-1, 1)), axis=1) log_N = sum((np.log(sum(weights)))) # Update Trackers, Verify Conditions change_log = np.linalg.norm(log_N - log_B) if (change_log <= min_change): continue else: break # Output Image Reconstruction mask = (np.argmax(weights, axis=1)).reshape(-1, 1) mask = np.reshape(mask, (image.shape[0], image.shape[1])).astype('uint8') # Chan-Vese Active Contours elif (mode == "active_contours"): # Morphological ACWE image = img_as_float(cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)) # Initial level Set init_ls = checkerboard_level_set(image.shape, 6) # List with Intermediate Results for Plotting the Evolution evolution = [] callback = store_evolution_in(evolution) mask = morphological_chan_vese(image, 5, init_level_set=init_ls, smoothing=10, iter_callback=callback).astype(np.uint8) # Watershed elif (mode == "mod_watershed"): ret, thresh = cv2.threshold(cv2.cvtColor(image, cv2.COLOR_RGB2GRAY), 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) kernel = np.ones((3, 3), np.uint8) opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2) sure_bg = cv2.dilate(opening, kernel, iterations=3) dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5) ret, sure_fg = cv2.threshold(dist_transform, 0.01 * dist_transform.max(), 255, 0) ls = np.uint8(sure_fg) / 255 circle_mask = create_circular_mask(image.shape[0], image.shape[1], radius=220) ls = ls * circle_mask # Discard Edge-to-Edge Connected Component large = getLargestCC(ls).astype(np.uint8) if (corner_mean(large) > 1): large = getLargestCC(ls - large).astype(np.uint8) # Post-Process Masks post = ndimage.binary_fill_holes(large, structure=np.ones( (5, 5))).astype(bool) else: print("ERROR: Undefined Segmentation Mode") ## Segmentation Label Selection # Define Target Scope candidate_mask_1 = mask.copy() * create_circular_mask( image.shape[0], image.shape[1], radius=230) candidate_mask_2 = (np.invert(mask.copy()) + 2) * create_circular_mask( image.shape[0], image.shape[1], radius=230) # Compute Area of Convex Hulls convex_hull_1 = convex_hull_image(candidate_mask_1) convex_hull_2 = convex_hull_image(candidate_mask_2) # Set Segmentation Component Labels kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (10, 10)) if (np.sum(convex_hull_1) < np.sum(convex_hull_2)): dilation = cv2.dilate(candidate_mask_1, kernel, iterations=1) mask = ndimage.binary_fill_holes(dilation, structure=np.ones((5, 5))) else: dilation = cv2.dilate(candidate_mask_2, kernel, iterations=1) mask = ndimage.binary_fill_holes(dilation, structure=np.ones((5, 5))) if (np.sum(mask) < 5000): mask = create_circular_mask(image.shape[0], image.shape[1], radius=230) return mask
def store_evolution_in(lst): """Returns a callback function to store the evolution of the level sets in the given list. """ def _store(x): lst.append(np.copy(x)) return _store # Morphological ACWE image = img_as_float(data.camera()) # Initial level set init_ls = checkerboard_level_set(image.shape, 6) # List with intermediate results for plotting the evolution evolution = [] callback = store_evolution_in(evolution) ls = morphological_chan_vese(image, 35, init_level_set=init_ls, smoothing=3, iter_callback=callback) fig, axes = plt.subplots(2, 2, figsize=(8, 8)) ax = axes.flatten() ax[0].imshow(image, cmap="gray") ax[0].set_axis_off() ax[0].contour(ls, [0.5], colors='r') ax[0].set_title("Morphological ACWE segmentation", fontsize=12) ax[1].imshow(ls, cmap="gray")
def active_contour(image): def store_evolution_in(lst): def _store(x): lst.append(np.copy(x)) return _store image = img_as_float(data.camera()) init_ls = checkerboard_level_set(image.shape, 6) evolution = [] callback = store_evolution_in(evolution) ls = morphological_chan_vese(image, 35, init_level_set=init_ls, smoothing=3, iter_callback=callback) fig, axes = plt.subplots(2, 2, figsize=(8, 8)) ax = axes.flatten() ax[0].imshow(image, cmap="gray") ax[0].set_axis_off() ax[0].contour(ls, [0.5], colors='r') ax[0].set_title("Morphological ACWE segmentation", fontsize=12) ax[1].imshow(ls, cmap="gray") ax[1].set_axis_off() contour = ax[1].contour(evolution[2], [0.5], colors='g') contour.collections[0].set_label("Iteration 2") contour = ax[1].contour(evolution[7], [0.5], colors='y') contour.collections[0].set_label("Iteration 7") contour = ax[1].contour(evolution[-1], [0.5], colors='r') contour.collections[0].set_label("Iteration 35") ax[1].legend(loc="upper right") title = "Morphological ACWE evolution" ax[1].set_title(title, fontsize=12) image = img_as_float(data.coins()) gimage = inverse_gaussian_gradient(image) init_ls = np.zeros(image.shape, dtype=np.int8) init_ls[10:-10, 10:-10] = 1 evolution = [] callback = store_evolution_in(evolution) ls = morphological_geodesic_active_contour(gimage, 230, init_ls, smoothing=1, balloon=-1, threshold=0.69, iter_callback=callback) ax[2].imshow(image, cmap="gray") ax[2].set_axis_off() ax[2].contour(ls, [0.5], colors='r') ax[2].set_title("Morphological GAC segmentation", fontsize=12) ax[3].imshow(ls, cmap="gray") ax[3].set_axis_off() contour = ax[3].contour(evolution[0], [0.5], colors='g') contour.collections[0].set_label("Iteration 0") contour = ax[3].contour(evolution[100], [0.5], colors='y') contour.collections[0].set_label("Iteration 100") contour = ax[3].contour(evolution[-1], [0.5], colors='r') contour.collections[0].set_label("Iteration 230") ax[3].legend(loc="upper right") title = "Morphological GAC evolution" ax[3].set_title(title, fontsize=12) fig.tight_layout() plt.show()
def morphological(image): # Morphological ACWE img = img_as_float(skimage.color.rgb2gray(image)) # Initial level set init_ls = checkerboard_level_set(img.shape, 6) # List with intermediate results for plotting the evolution evolution = [] callback = store_evolution_in(evolution) ls = morphological_chan_vese(img, 200, init_level_set=init_ls, smoothing=4, iter_callback=callback) fig, axes = plt.subplots(2, 2, figsize=(8, 8)) ax = axes.flatten() ax[0].imshow(img, cmap="gray") ax[0].set_axis_off() ax[0].contour(ls, [0.5], colors='r') ax[0].set_title("Morphological ACWE segmentation", fontsize=12) ax[1].imshow(ls, cmap="gray") ax[1].set_axis_off() contour = ax[1].contour(evolution[2], [0.5], colors='g') contour.collections[0].set_label("Iteration 2") contour = ax[1].contour(evolution[7], [0.5], colors='y') contour.collections[0].set_label("Iteration 7") contour = ax[1].contour(evolution[-1], [0.5], colors='r') contour.collections[0].set_label("Iteration 35") ax[1].legend(loc="upper right") title = "Morphological ACWE evolution" ax[1].set_title(title, fontsize=12) # Morphological GAC img = img_as_float(skimage.color.rgb2gray(image)) gimage = inverse_gaussian_gradient(img) # Initial level set init_ls = np.zeros(img.shape, dtype=np.int8) init_ls[10:-10, 10:-10] = 1 # List with intermediate results for plotting the evolution evolution = [] callback = store_evolution_in(evolution) ls = morphological_geodesic_active_contour(gimage, 230, init_ls, smoothing=5, balloon=-1, threshold=0.5, iter_callback=callback) ax[2].imshow(img, cmap="gray") ax[2].set_axis_off() ax[2].contour(ls, [0.5], colors='r') ax[2].set_title("Morphological GAC segmentation", fontsize=12) ax[3].imshow(ls, cmap="gray") ax[3].set_axis_off() contour = ax[3].contour(evolution[0], [0.5], colors='g') contour.collections[0].set_label("Iteration 0") contour = ax[3].contour(evolution[100], [0.5], colors='y') contour.collections[0].set_label("Iteration 100") contour = ax[3].contour(evolution[-1], [0.5], colors='r') contour.collections[0].set_label("Iteration 230") ax[3].legend(loc="upper right") title = "Morphological GAC evolution" ax[3].set_title(img, fontsize=12) fig.tight_layout() plt.show()