def test_morphsnakes_black(): img = np.zeros((11, 11)) ls = circle_level_set(img.shape, (5, 5), 3) ref_zeros = np.zeros(img.shape, dtype=np.int8) ref_ones = np.ones(img.shape, dtype=np.int8) acwe_ls = morphological_chan_vese(img, iterations=6, init_level_set=ls) assert_array_equal(acwe_ls, ref_zeros) gac_ls = morphological_geodesic_active_contour(img, iterations=6, init_level_set=ls) assert_array_equal(gac_ls, ref_zeros) gac_ls2 = morphological_geodesic_active_contour(img, iterations=6, init_level_set=ls, balloon=1, threshold=-1, smoothing=0) assert_array_equal(gac_ls2, ref_ones) assert acwe_ls.dtype == gac_ls.dtype == gac_ls2.dtype == np.int8
def test_morphsnakes_incorrect_ndim(): img = np.zeros((4, 4, 4, 4)) ls = np.zeros((4, 4, 4, 4)) with testing.raises(ValueError): morphological_chan_vese(img, iterations=1, init_level_set=ls) with testing.raises(ValueError): morphological_geodesic_active_contour(img, iterations=1, init_level_set=ls)
def test_morphsnakes_incorrect_ndim(): img = np.zeros((4, 4, 4, 4)) ls = np.zeros((4, 4, 4, 4)) with pytest.raises(ValueError): morphological_chan_vese(img, num_iter=1, init_level_set=ls) with pytest.raises(ValueError): morphological_geodesic_active_contour(img, num_iter=1, init_level_set=ls)
def test_morphsnakes_incorrect_image_shape(): img = np.zeros((10, 10, 3)) ls = np.zeros((10, 9)) with testing.raises(ValueError): morphological_chan_vese(img, iterations=1, init_level_set=ls) with testing.raises(ValueError): morphological_geodesic_active_contour(img, iterations=1, init_level_set=ls)
def test_MorphGeodesicActiveContour(): """Unit test for MorphGeodesicActiveContour method. Checks if evaluate function output\ is the same as manually running the skimage function.""" ac1 = Segmentors.MorphGeodesicActiveContour() assert ac1.evaluate(TEST_IM_COLOR).all() == segmentation.morphological_geodesic_active_contour(\ segmentation.inverse_gaussian_gradient(color.rgb2gray(TEST_IM_COLOR), 0.2, 0.3),\ iterations=10, init_level_set='checkerboard', smoothing=5, threshold='auto',\ balloon=10).all() assert ac1.evaluate(TEST_IM_GRAY).all() == segmentation.morphological_geodesic_active_contour(\ segmentation.inverse_gaussian_gradient(TEST_IM_GRAY, 0.2, 0.3), iterations=10,\ init_level_set='checkerboard', smoothing=5, threshold='auto', balloon=10).all()
def createMask(x0, y0, x1, y1, fileName, patientID, rawDataPath): filePath = (rawDataPath + '/' + fileName) maskDataPath = '/home/faqih/ITB/TA/Web/server/static/maskData' segmentedImPath = '/home/faqih/ITB/TA/Web/server/static/segmentedImage' binaryCircle = _init(x0, y0, x1, y1) image = pydicom.filereader.dcmread(filePath).pixel_array gimage = inverse_gaussian_gradient(image, 200, 8) mask = morphological_geodesic_active_contour(gimage, 100, binaryCircle, smoothing=3, balloon=-1, threshold=0.6) fig, ax = plt.subplots(figsize=(7, 7)) plt.subplots_adjust(left=0, bottom=0, right=1, top=1, wspace=0, hspace=0) ax.imshow(image, cmap=plt.cm.gray) ax.contour(mask, [0.5], colors='r', linestyles='dashed', linewidths=2) ax.set_xticks([]), ax.set_yticks([]) ax.axis([0, image.shape[1], image.shape[0], 0]) #plt.show() ax.figure.savefig(os.path.join(segmentedImPath, fileName.split('.', 1)[0])) np.savez_compressed(os.path.join(maskDataPath, fileName.split('.', 1)[0] + '.npz'), mask=mask) return (fileName, patientID)
def preview(self, ips, para): snap, img = ips.snap, ips.img gimage = inverse_gaussian_gradient(img_as_float(snap)) init = np.ones(img.shape, dtype=np.bool) msk = morphological_geodesic_active_contour(gimage, para['iter'], init_level_set=init, smoothing=para['smooth'], threshold='auto' if para['auto'] else para['thr'], balloon=para['balloon']) > 0 (c1, c2), img[:] = ips.range, snap if para['out'] == 'mask': img[~msk], img[msk] = c1, c2 else: img[binary_dilation(msk) ^ msk] = c2 ips.update()
def run(self, ips, snap, img, para=None): gimage = inverse_gaussian_gradient(img_as_float(snap)) init = ips.get_msk('out') msk = morphological_geodesic_active_contour( gimage, para['iter'], init_level_set=init, smoothing=para['smooth'], threshold='auto' if para['auto'] else para['thr'], balloon=para['balloon']) > 0 (c1, c2), img[:] = ips.range, snap if para['out'] == 'mask': img[~msk], img[msk] = c1, c2 else: img[binary_dilation(msk) ^ msk] = c2
def run(self, ips, snap, img, para = None): stackimg = [] callback = lambda x: stackimg.append((x*255).astype(np.uint8)) if para['sub'] else 0 gimage = inverse_gaussian_gradient(img_as_float(snap)) init = np.ones(img.shape, dtype=np.bool) msk = morphological_geodesic_active_contour(gimage, para['iter'], init_level_set=init, smoothing=para['smooth'], threshold='auto' if para['auto'] else para['thr'], balloon=para['balloon'], iter_callback=callback) > 0 (c1, c2), img[:] = ips.range, snap if para['out'] == 'mask': img[~msk], img[msk] = c1, c2 else: img[binary_dilation(msk) ^ msk] = c2 if para['sub']: self.app.show_img(stackimg, ips.title+'-sub')
def snake_GAC(filename): image = io.imread(filename) gimage = inverse_gaussian_gradient(image) # Initial level set init_ls = np.zeros(image.shape, dtype=np.int8) init_ls[10:-10, 10:-10] = 1 # List with intermediate results for plotting the evolution evolution2 = [] callback = store_evolution_in(evolution2) ls = morphological_geodesic_active_contour(gimage, iterations, iter_callback=callback) return evolution2[-1]
def _segment_gac(img, init_level_set, iterations=20): """ refines initial segmentation contours using geodesic active contours :param imgs: list of 2 images [2D] imgs[0] = slice to segment: imgs[1] = initial level set :param iterations: number of refinement iterations :return: """ return segmentation.morphological_geodesic_active_contour( img, iterations, init_level_set=init_level_set, smoothing=2, balloon=1.2)
def supercluster(self,clustered_data): gimage = inverse_gaussian_gradient(clustered_data) # Initial level set # this makes alternate squares active at the first iteration of 10 macro-pixels #init_ls = checkerboard_level_set(clustered_data.shape, 10) init_ls = np.zeros(clustered_data.shape, dtype=np.int8) init_ls[10:-10, 10:-10] = 1 # List with intermediate results for plotting the evolution evolution = [] callback = self.store_evolution_in(evolution) ls = morphological_geodesic_active_contour(gimage, 300, init_ls, smoothing=1, balloon=-1, threshold=0.69, iter_callback=callback) return ls
def test_morphsnakes_iterations_kwarg_deprecation(): img = np.zeros((11, 11)) ls = disk_level_set(img.shape, center=(5, 5), radius=3) ref_zeros = np.zeros(img.shape, dtype=np.int8) ref_ones = np.ones(img.shape, dtype=np.int8) with expected_warnings(["`iterations` is a deprecated argument"]): acwe_ls = morphological_chan_vese(img, iterations=6, init_level_set=ls) assert_array_equal(acwe_ls, ref_zeros) with expected_warnings(["`iterations` is a deprecated argument"]): gac_ls = morphological_geodesic_active_contour(img, iterations=6, init_level_set=ls) assert_array_equal(gac_ls, ref_zeros)
def test_init_level_sets(): image = np.zeros((6, 6)) checkerboard_ls = morphological_chan_vese(image, 0, 'checkerboard') checkerboard_ref = np.array( [[0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 0]], dtype=np.int8) circle_ls = morphological_geodesic_active_contour(image, 0, 'circle') circle_ref = np.array( [[0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1], [0, 0, 1, 1, 1, 0]], dtype=np.int8) assert_array_equal(checkerboard_ls, checkerboard_ref) assert_array_equal(circle_ls, circle_ref)
def probmap2bound_slicewise(i, prob_map_b, thres=0.7, ks=9): """ obtain boundary from probability map for each slice :param prob_map_b: ndarray of size [B, H, W], probability map :param thres: float, thres for filtering out pixels with prob lower than given thres :param outer_ks: int, kernel size for bound detection :return: lses: list of obtained bounds """ n_channel, height, width = prob_map_b.shape iter_max = 30 lses = [] for bound_inx in range(1, n_channel): # inner and outer bound prob_map_bb = prob_map_b[bound_inx] pred_filter = (prob_map_bb >= thres).astype(np.uint8) kernel_close = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (ks, ks)) for inx in range(iter_max): image_close = cv2.morphologyEx(pred_filter, cv2.MORPH_CLOSE, kernel_close, iterations=inx+1) _, contours, _ = cv2.findContours(image_close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) contours = [contour for contour in contours if len(contour) > 4 and cv2.contourArea(contour) / len(contour) >= 4.0] if len(contours) > 0: # find the optimal number of iterations break if len(contours) > 0: mask = np.zeros(image_close.shape[:2], np.uint8) ls = cv2.drawContours(mask, contours, -1, 1, -1) else: # use Snake to find contours if cv2.findContours doesn't work well if bound_inx == 1: gimage = inverse_gaussian_gradient(img_as_float(image_close), alpha=100, sigma=5.0) else: gimage = inverse_gaussian_gradient(img_as_float(image_close), alpha=100, sigma=3.0) init = np.zeros(gimage.shape, dtype=np.int8) init[5:-5, 5:-5] = 1 ls = morphological_geodesic_active_contour(gimage, 100, init, smoothing=1, balloon=-1, threshold='auto') lses.append(ls) reg = lslist2bound(lses) return reg
def _morph_snakes(img: np.ndarray, labels: np.ndarray, sigma: int = SNAKES_SIGMA, iterations: int = SNAKES_ITERATIONS, balloon: int = SNAKES_BALLOON, threshold: float = SNAKES_THRESHOLD, smoothing: float = SNAKES_SMOOTHING) -> List[np.ndarray]: """ Applies morphological active contour method to given image starting from given labels. """ gradient = ndimage.gaussian_gradient_magnitude(img.astype(np.float32), sigma=sigma) return [ segment.morphological_geodesic_active_contour(gradient, iterations, labels == region_id, smoothing=smoothing, balloon=balloon, threshold=threshold) for region_id in range(1, np.amax(labels)) ]
def test_init_level_sets(): image = np.zeros((6, 6)) checkerboard_ls = morphological_chan_vese(image, 0, 'checkerboard') checkerboard_ref = np.array([[0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 0]], dtype=np.int8) circle_ls = morphological_geodesic_active_contour(image, 0, 'circle') circle_ref = np.array([[0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1], [0, 0, 1, 1, 1, 0]], dtype=np.int8) assert_array_equal(checkerboard_ls, checkerboard_ref) assert_array_equal(circle_ls, circle_ref)
def test_morphsnakes_simple_shape_geodesic_active_contour(): img = np.float_(circle_level_set((11, 11), (5, 5), 3.5)) gimg = inverse_gaussian_gradient(img, alpha=10.0, sigma=1.0) ls = circle_level_set(img.shape, (5, 5), 6) ref = np.array( [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=np.int8) gac_ls = morphological_geodesic_active_contour(gimg, iterations=10, init_level_set=ls, balloon=-1) assert_array_equal(gac_ls, ref) assert gac_ls.dtype == np.int8
def test_morphsnakes_simple_shape_geodesic_active_contour(): img = (disk_level_set((11, 11), center=(5, 5), radius=3.5)).astype(float) gimg = inverse_gaussian_gradient(img, alpha=10.0, sigma=1.0) ls = disk_level_set(img.shape, center=(5, 5), radius=6) ref = np.array( [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=np.int8) gac_ls = morphological_geodesic_active_contour(gimg, num_iter=10, init_level_set=ls, balloon=-1) assert_array_equal(gac_ls, ref) assert gac_ls.dtype == np.int8
def test_morphsnakes_simple_shape_geodesic_active_contour(): img = np.float_(circle_level_set((11, 11), (5, 5), 3.5)) gimg = inverse_gaussian_gradient(img, alpha=10.0, sigma=1.0) ls = circle_level_set(img.shape, (5, 5), 6) ref = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=np.int8) gac_ls = morphological_geodesic_active_contour(gimg, iterations=10, init_level_set=ls, balloon=-1) assert_array_equal(gac_ls, ref) assert gac_ls.dtype == np.int8
title = "Morphological ACWE evolution" ax[1].set_title(title, fontsize=12) # Morphological GAC image = img_as_float(data.coins()) gimage = inverse_gaussian_gradient(image) # Initial level set init_ls = np.zeros(image.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=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")
c = c[1:] count = count[1:] RealGlacier = 1 * (G2label == np.argmax(count) + 1) # RealGlacier=binary_closing(RealGlacier, selem=np.ones((3,3))) # RealOcean=binary_closing(RealOcean, selem=np.ones((3,3))) # GO2=BlankFrame(scipy.ndimage.binary_fill_holes(RealGlacier)) RO2 = 1 * scipy.ndimage.binary_fill_holes(RealOcean) #deploy the geodetic active contours RealGlacier = scipy.ndimage.binary_fill_holes(RealGlacier) init_ls = 1 * binary_dilation(1 * RealGlacier, selem=np.ones((5, 5))) init_ls = 1 * binary_closing(init_ls, selem=np.ones((30, 30))) init_ls = 1 * scipy.ndimage.binary_fill_holes(init_ls) image = 1 - (np.float32(1 * RealGlacier)) GO2 = morphological_geodesic_active_contour(image, 30, init_ls, smoothing=1, balloon=-0.5, threshold=0.6) GO2 = scipy.ndimage.morphology.binary_erosion(GO2, iterations=2) RO2 = np.logical_and(RO2, np.logical_not(GO2)) GO2 = BlankFrame(GO2) C = measure.find_contours(GO2, level=0.5) csize = np.zeros(len(C)) for i in range(len(C)): csize = C[i].shape[0] MainContour = np.int16(C[np.argmax(csize)]) GlacierContour = np.zeros((GO2.shape)) for c in range(len(MainContour)): GlacierContour[MainContour[c, 0], MainContour[c, 1]] = 1
a = dmap_test[i, :, :, :].reshape(dmap_test.shape[1:3]) b = dmap_test_pred c = mask_test[i, :, :, 0] plt.imshow(np.abs((b - a)) * c) plt.colorbar() plt.title('error |est - gt| * mask') input("Press Enter to continue...") mask = np.zeros(shape=) from skimage.segmentation import morphological_geodesic_active_contour contours = morphological_geodesic_active_contour(dmap_test_pred[0, :, :, 0], iterations=10000, init_level_set='checkerboard', smoothing=4, balloon=0.0) contours = cv2.Laplacian(dmap_test_pred[0, :, :, 0], cv2.CV_32F) import CGAL from CGAL.CGAL_Point_set_processing_3 import jet_estimate_normals plt.clf() plt.subplot(211) plt.imshow(dmap_test_pred.reshape(dmap_test_pred.shape[1:3])) plt.subplot(212) plt.imshow(contours)
ax[1].set_title(title, fontsize=12) # Morphological GAC image = img_as_float(data.coins()) gimage = inverse_gaussian_gradient(image) # Initial level set init_ls = np.zeros(image.shape, dtype=np.int8) init_ls[10:-10, 10:-10] = 1 # List with intermediate results for plotting the evolution evolution2 = [] callback = store_evolution_in(evolution2) 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(evolution2[0], [0.5], colors='g') contour.collections[0].set_label("Iteration 0") contour = ax[3].contour(evolution2[100], [0.5], colors='y') contour.collections[0].set_label("Iteration 100")
def run(self): self.beginTaskRun() # Get input 0 : input = self.getInput(0) # Get output : output = self.getOutput(0) # Get parameters : param = self.getParam() # Get image from input/output (numpy array): srcImage = input.getImage() # Convert to grey Image if RGB if len(srcImage.shape) == 3: image = cv2.cvtColor(srcImage, cv2.COLOR_RGB2GRAY) else: image = srcImage # Convert to float imagef = img_as_float(image) # enhances borders if param.mgac_amplification_contour == "Inverse gaussian gradient": gimage = inverse_gaussian_gradient(imagef) else: gimage = imagef # initial level set initlevelSetInput = self.getInput(2) if initlevelSetInput.isDataAvailable(): initlevelSetBinary = initlevelSetInput.getImage() if param.method == "mgac": proc_img = morphological_geodesic_active_contour( gimage, param.mgac_iterations, init_level_set=initlevelSetBinary, smoothing=param.mgac_smoothing, threshold=param.mgac_threshold, balloon=param.mgac_balloon, iter_callback=(lambda callback: self.emitStepProgress() )).astype(np.uint8) * 255 else: proc_img = morphological_chan_vese( gimage, param.mcv_iterations, init_level_set=initlevelSetBinary, smoothing=param.mcv_smoothing, lambda1=param.mcv_lambda1, lambda2=param.mcv_lambda2, iter_callback=(lambda callback: self.emitStepProgress() )).astype(np.uint8) * 255 else: # input graph -> by user / by previous aoperation in worflow graphInput = self.getInput(1) if graphInput.isDataAvailable(): self.createGraphicsMask(imagef.shape[1], imagef.shape[0], graphInput) binImg = self.getGraphicsMask(0) if param.method == "mgac": proc_img = morphological_geodesic_active_contour( gimage, param.mgac_iterations, init_level_set=binImg, smoothing=param.mgac_smoothing, threshold=param.mgac_threshold, balloon=param.mgac_balloon, iter_callback=( lambda callback: self.emitStepProgress())).astype( np.uint8) * 255 else: proc_img = morphological_chan_vese( gimage, param.mcv_iterations, init_level_set=binImg, smoothing=param.mcv_smoothing, lambda1=param.mcv_lambda1, lambda2=param.mcv_lambda2, iter_callback=( lambda callback: self.emitStepProgress())).astype( np.uint8) * 255 else: raise Exception( "No initial level-set given: it must be graphics input or binary image." ) # set output mask binary image output.setImage(proc_img) # add foward input image self.forwardInputImage(0, 1) # Call endTaskRun to finalize process self.endTaskRun()
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()
############################################################################### # Finally, we use morphological geodesic active contours, # :func:`skimage.segmentation.morphological_geodesic_active_contour`, a method # that generally produces good results, but requires a long time to converge on # a good answer. We purposefully cut short the procedure at 100 iterations, so # that the final result is *undersegmented*, meaning that many regions are # merged into one segment. We will see the corresponding effect on the # segmentation metrics. image = img_as_float(image) gradient = inverse_gaussian_gradient(image) init_ls = np.zeros(image.shape, dtype=np.int8) init_ls[10:-10, 10:-10] = 1 im_test3 = morphological_geodesic_active_contour(gradient, iterations=100, init_level_set=init_ls, smoothing=1, balloon=-1, threshold=0.69) im_test3 = label(im_test3) method_names = [ 'Compact watershed', 'Canny filter', 'Morphological Geodesic Active Contours' ] short_method_names = ['Compact WS', 'Canny', 'GAC'] precision_list = [] recall_list = [] split_list = [] merge_list = [] for name, im_test in zip(method_names, [im_test1, im_test2, im_test3]):
def morphSnakes(fp, frame, alph, sig, thresh): """{ ****************************************************************** * Fnc: read_arf() * Desc: reads an arf file and returns dictionary of parsed info * Inputs: fp - full path to arf file * Outputs: ****************************************************************** }""" ############################ Read Public Release Data ################################################## # print('Reading data...') _, fn = os.path.split(fp) basename, _ext = os.path.splitext(fn) df = pd.read_csv(f"{DATA_DIR}/Metric/{basename}.bbox_met", header=None, names=[ "site", "unknown1", "unknown2", "sensor", "scenario", "frame", "ply_id", "unknown3", "unknown4", "upperx", "uppery", "unknown5", "unknown6", "unknown7", "unknown8", "unknown9", "unknown10", "unknown11" ]) agt = read_agt(f"{DATA_DIR}/cegr/agt/{basename}.agt") f = open(fp, "rb") header = f.read(8 * 4) header = list(struct.iter_unpack(">I", header)) fptr = np.memmap(fp, dtype="uint16", mode='r', shape=(header[5][0], header[2][0], header[3][0]), offset=32) frames, cols, rows = fptr.shape # print('Data loaded!') im = fptr[frame].T.byteswap() tgtx, tgty = map( int, agt['Agt']['TgtSect'][f'TgtUpd.{frame}'][f'Tgt.{frame}'] ['PixLoc'].split()) upper_left_x, upper_left_y = df[df['frame'] == frame + 1][['upperx', 'uppery']].iloc[0] tgt_width = 2 * (tgtx - upper_left_x) tgt_height = 2 * (tgty - upper_left_y) ######################################### Find BB with GAC ################################################ 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 plt.ioff() fig, axes = plt.subplots(2, 2, figsize=(8, 8)) ax = axes.flatten() # Morphological GAC image = img_as_float(im.T) gimage = inverse_gaussian_gradient(image, alpha=alph, sigma=sig) ax[0].imshow(image, cmap="gray") ax[0].set_axis_off() ax[0].set_title("MWIR", fontsize=12) ax[1].imshow(gimage, cmap="gray") ax[1].set_axis_off() ax[1].set_title("Inverse Gaussian Gradient", fontsize=12) ######################################## Set Initial Contour ########################################### ## Here you will want to set it as the bounding box, then you can set the morph snake to shrink instead ## of dialate. ######################################################################################################## # Initial level set init_ls = circle_level_set(image.shape, center=(tgty, tgtx), radius=5) # init_ls[10:-10, 10:-10] = 1 # List with intermediate results for plotting the evolution evolution = [] callback = store_evolution_in(evolution) ## Initialize the Morph Snake, you will want it to shrink (balloon=-1) ls = morphological_geodesic_active_contour(gimage, 230, init_ls, smoothing=1, balloon=1, threshold=thresh, 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("Center Point 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 = "Center Point GAC Evolution" ax[3].set_title(title, fontsize=12) fig.tight_layout() fig.tight_layout(rect=[0, 0.03, 1, 0.95]) plt.suptitle( f'Morph Snakes, alpha={alph}, sigma={sig}, threshold={thresh}') # plt.savefig(f"{DATA_DIR}\\morphSnakes\\{basename}_{alph}_{sig}_{thresh}.png") # plt.close(fig) plt.show()
def main(): filePath = '../Img/' fileList = os.listdir(filePath) # name = '13.png' for i in range(len(fileList)): # len(fileList) Image = cv2.imread(os.path.join(filePath, fileList[i]), 1) # 读入原图 image = cv2.cvtColor(Image, cv2.COLOR_BGR2GRAY) image = img_as_float(image) # image = np.array(image, dtype=np.float64) # 读入到np的array中,并转化浮点类型 # Initial level set init_ls = checkerboard_level_set(image.shape, 6) # List with intermediate results for plotting the evolution ls = morphological_chan_vese(image, 35, init_level_set=init_ls, smoothing=0) 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(fileList[i] + 'MAC', fontsize=12) # Morphological GAC gimage = inverse_gaussian_gradient(image) # Initial level set init_ls = np.zeros(image.shape, dtype=np.int8) init_ls[10:-10, 10:-10] = 1 # List with intermediate results for plotting the evolution ls = morphological_geodesic_active_contour(gimage, 230, init_ls, smoothing=1, balloon=-1, threshold=0.69) ax[1].imshow(image, cmap="gray") ax[1].set_axis_off() ax[1].contour(ls, [0.5], colors='r') ax[1].set_title('MGAC', fontsize=12) #CV cv = chan_vese(image, mu=0.25, lambda1=1, lambda2=1, tol=1e-3, max_iter=200, dt=0.5, init_level_set="checkerboard", extended_output=True) ax[2].imshow(image, cmap="gray") ax[2].set_axis_off() ax[2].contour(cv[0], [0.5], colors='r') ax[2].set_title('AC', fontsize=12) #My CV from MyCV import my_chan_vese # CV cv = my_chan_vese(image, mu=0.25, lambda1=1, lambda2=1, tol=1e-3, max_iter=200, dt=0.5, init_level_set="checkerboard", extended_output=True) ax[3].imshow(image, cmap="gray") ax[3].set_axis_off() ax[3].contour(cv[0], [0.5], colors='r') ax[3].set_title('MyAC', fontsize=12) fig.tight_layout() plt.savefig('./MCVSeg2/' + fileList[i] + '.png') plt.show(block=False)
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()
def main(): current_path = os.path.abspath(os.path.dirname(__file__)) dice_results = [] hausdorff_results = [] # Final report text file initialization summary_file = open('contour_report.txt', 'w+') summary_file.write('Script run: {a}\n'.format( a=datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) for image_number in range(1, 110): image_path = os.path.join(current_path, 'input_images', '{}_no_contour.jpg'.format(image_number)) image = io.imread(image_path) image = color.rgb2gray(image) # Displaying the image to get the clicks coordinates fig = plt.figure() plt.imshow(image, cmap='gray') plt.axis('Off') cid = fig.canvas.mpl_connect('button_press_event', onclick) plt.show() # Calculating the radius, used to initialize the level set algorithm radius = np.sqrt( np.square(coords[1][0] - coords[0][0]) + np.square(coords[1][1] - coords[0][1])) # Main part of the script - image processing and creating the contour: # 1. Histogram equalization # 2. Gaussian filtration # 3. Anisotropic diffusion filtration # 4. Inverse Gaussian Gradient # 5. Unsharp Masking # 6. Morphological snakes # Hyperparameter optimization were performed using grid search for every method. equalized_image = equalize_hist(image) filtered_image = nd.gaussian_filter(equalized_image, sigma=5) diff_image = anisodiff(filtered_image, niter=50) gimage = inverse_gaussian_gradient(diff_image, alpha=50) sharpened_image = unsharp_mask(gimage, radius=100, amount=1.0) init_level_set = circle_level_set(gimage.shape, coords[0], radius) level_set = morphological_geodesic_active_contour(sharpened_image, 250, init_level_set, smoothing=4, balloon=1) level_set = nd.morphology.binary_fill_holes(level_set).astype(int) contour_access = os.path.join('input_images', '{}_contour.jpg'.format(image_number)) given_contour = contour_to_binary_mask(contour_access, level_set.shape) dice_result = dice(given_contour, level_set) hausdorff_result = hausdorff(given_contour, level_set) print('Dice =', dice_result) print('Hausdorff =', hausdorff_result) # Updating the report with new coefficients. summary_file.write('\n{a}:\nDice: {b}\nHausdorff: {c}\n'.format( a=image_number, b=format(dice_result, '.2f'), c=format(hausdorff_result, '.2f'))) dice_results.append(dice_result) hausdorff_results.append(hausdorff_result) # Displaying the result plt.figure() plt.imshow(image, cmap="gray") plt.axis('Off') plt.contour(level_set, [0.5], colors='r') plt.show() # Calculating and appending mean and standard deviation of the test to the end of the report summary_file.write('\n\nDICE:\nMEAN: {d}\nSTD DEV: {e}'.format( d=format(mean(dice_results), '.2f'), e=format(stddev(dice_results), '.2f'))) summary_file.write('\n\nHAUSDORFF:\nMEAN: {d}\nSTD DEV: {e}'.format( d=format(mean(hausdorff_results), '.2f'), e=format(stddev(hausdorff_results), '.2f'))) summary_file.close()
def level_set3D(data, seed3D, resol, lambda1=1, lambda2=4, smoothing=0, iterations=100, rad=3, method='ACWE', alpha=100, sigma=2, balloon=1): ## init res_fac = resol[1] / resol[ 0] # resolution factor to scale chunk to real dimensions N = 60 # approximately the chunk size (in mm) around nodule num_slices = int(round(N / res_fac)) # number of slices before reg = 30 # window of interest centered around seed point s = seed3D[1:] # 2D seed point for (x,y)-plane num = seed3D[0] # slice number seed point is selected from # apply lungmask on each slice of interest around seed point tmp_data = np.zeros((num_slices, data.shape[1], data.shape[2])) ii = 0 for i in range(data.shape[0]): if (i >= num - int(round(num_slices / 2)) and i <= num + int(round(num_slices / 2)) - 1): mask = lungmask_pro(data[i, :, :].copy()) tmp = data[i, :, :].copy() tmp[mask == 0] = np.amin( tmp ) # OBS: -1024 maybe not far away enough from lung intensities tmp_data[ii, :, :] = tmp.copy() ii += 1 # only apply level set on small volume around seed point -> increases speed and accuracy for fixed number of iterations tmp = tmp_data.copy() tmp = tmp[:, s[0] - reg:s[0] + reg, s[1] - reg:s[1] + reg] # transform chunk to true size (in mm) by stretching the slice-axis relevant to a resolution factor tmp = zoom(tmp.copy(), zoom=[res_fac, 1, 1], order=1) # apply 3D level set from single seed point from initial 3D blob around current seed point inits = circle_level_set(tmp.shape, center=(int(num_slices / 2 * res_fac), reg, reg), radius=rad) # choose between two types of level set methods if method == 'ACWE': tmp = morphological_chan_vese(tmp.copy(), iterations=iterations, init_level_set=inits, smoothing=smoothing, lambda1=lambda1, lambda2=lambda2).astype(int) elif method == 'GAC': tmp = tmp.astype(np.float32) tmp = inverse_gaussian_gradient(tmp, alpha=alpha, sigma=alpha) tmp = morphological_geodesic_active_contour(tmp, iterations=iterations, init_level_set=inits, smoothing=smoothing, threshold='auto', balloon=1) else: print('Please choose a valid method!') return None # if no nodule was segmented, break if (len(np.unique(tmp)) == 1): #print('No nodule was segmented. Try changing parameters...') return None # check if leakage has occured #if ((tmp[0,0,0] > 0) or (tmp[0,0,-1] > 0) or (tmp[0,-1,0] > 0) or (tmp[0,-1,-1] > 0) or (tmp[-1,0,0] > 0) or (tmp[-1,-1,0] > 0) or (tmp[-1,0,-1] > 0) or (tmp[-1,-1,-1] > 0)): # if ((len(np.unique(tmp[0,:,:])) > 1) or (len(np.unique(tmp[:,0,:])) > 1) or (len(np.unique(tmp[:,:,0])) > 1) or # (len(np.unique(tmp[-1,:,:])) > 1) or (len(np.unique(tmp[:,-1,:])) > 1) or (len(np.unique(tmp[:,:,-1])) > 1)): # print("Leakage problems? Growing reached boundaries... Discards segmentation") # return None # only keep segments connected to seed point (blood vessels will hopefully not be connected with nodule after level set, if leakage has occured) labels_tmp = label(tmp.copy()) res = np.zeros(tmp.shape) if (labels_tmp[int(num_slices / 2 * res_fac), reg, reg] > 0): res[labels_tmp == labels_tmp[int(num_slices / 2 * res_fac), reg, reg]] = 1 # need to transform chunk back to original size res = zoom(res.copy(), zoom=[1 / res_fac, 1, 1], order=1) # # just in case some parts are not connected anymore after interpolation -> remove not connected components # labels_tmp = label(res.copy()) # res = np.zeros(res.shape) # if (labels_tmp[int(num_slices/2), reg, reg] > 0): # res[labels_tmp == labels_tmp[int(num_slices/2), reg, reg]] = 1 # get the final nodule mask to the original image stack shape # but handle cases where seed point is selected at ends of image stack, and window is outside of range new_res = np.zeros(data.shape) if (num + int(num_slices / 2) > new_res.shape[0]): new_res[num - int(num_slices / 2):num + int(num_slices / 2), s[0] - reg:s[0] + reg, s[1] - reg:s[1] + reg] = res[:num + int(num_slices / 2) - new_res.shape[0]] elif (num - int(num_slices / 2) < 0): new_res[0:num + int(num_slices / 2), s[0] - reg:s[0] + reg, s[1] - reg:s[1] + reg] = res[:num + int(num_slices / 2)] else: new_res[num - int(np.floor(num_slices / 2)):num + int(np.ceil(num_slices / 2)), s[0] - reg:s[0] + reg, s[1] - reg:s[1] + reg] = res return new_res