def test_icm_square(): com = ConstantObservationModel() icm = IteratedConditionalModes() initial_segmentation = square.copy() mu, sigma = com.seg_stats(square_1, initial_segmentation, nclasses) sigmasq = sigma ** 2 npt.assert_(mu[0] >= 0.0) npt.assert_(mu[1] >= 0.0) npt.assert_(mu[2] >= 0.0) npt.assert_(mu[3] >= 0.0) npt.assert_(sigmasq[0] >= 0.0) npt.assert_(sigmasq[1] >= 0.0) npt.assert_(sigmasq[2] >= 0.0) npt.assert_(sigmasq[3] >= 0.0) negll = com.negloglikelihood(square_1, mu, sigmasq, nclasses) final_segmentation_1 = np.empty_like(square_1) final_segmentation_2 = np.empty_like(square_1) beta = 0.0 for i in range(max_iter): print('\n') print('>> Iteration: ' + str(i)) print('\n') final_segmentation_1, energy_1 = icm.icm_ising(negll, beta, initial_segmentation) initial_segmentation = final_segmentation_1.copy() beta = 2 initial_segmentation = square.copy() for j in range(max_iter): print('\n') print('>> Iteration: ' + str(j)) print('\n') final_segmentation_2, energy_2 = icm.icm_ising(negll, beta, initial_segmentation) initial_segmentation = final_segmentation_2.copy() difference_map = np.abs(final_segmentation_1 - final_segmentation_2) npt.assert_(np.abs(np.sum(difference_map)) != 0)
def test_greyscale_image(): com = ConstantObservationModel() icm = IteratedConditionalModes() mu, sigma = com.initialize_param_uniform(image, nclasses) sigmasq = sigma ** 2 npt.assert_array_almost_equal(mu, np.array([0., 0.25, 0.5, 0.75])) npt.assert_array_almost_equal(sigma, np.array([1.0, 1.0, 1.0, 1.0])) npt.assert_array_almost_equal(sigmasq, np.array([1.0, 1.0, 1.0, 1.0])) neglogl = com.negloglikelihood(image, mu, sigmasq, nclasses) npt.assert_(neglogl[100, 100, 1, 0] != neglogl[100, 100, 1, 1]) npt.assert_(neglogl[100, 100, 1, 1] != neglogl[100, 100, 1, 2]) npt.assert_(neglogl[100, 100, 1, 2] != neglogl[100, 100, 1, 3]) npt.assert_(neglogl[100, 100, 1, 1] != neglogl[100, 100, 1, 3]) initial_segmentation = icm.initialize_maximum_likelihood(neglogl) npt.assert_(initial_segmentation.max() == nclasses - 1) npt.assert_(initial_segmentation.min() == 0) PLN = icm.prob_neighborhood(initial_segmentation, beta, nclasses) print(PLN.shape) npt.assert_(np.all((PLN >= 0) & (PLN <= 1.0))) if beta == 0.0: npt.assert_almost_equal(PLN[50, 50, 1, 0], 0.25, True) npt.assert_almost_equal(PLN[50, 50, 1, 1], 0.25, True) npt.assert_almost_equal(PLN[50, 50, 1, 2], 0.25, True) npt.assert_almost_equal(PLN[50, 50, 1, 3], 0.25, True) npt.assert_almost_equal(PLN[147, 129, 1, 0], 0.25, True) npt.assert_almost_equal(PLN[147, 129, 1, 1], 0.25, True) npt.assert_almost_equal(PLN[147, 129, 1, 2], 0.25, True) npt.assert_almost_equal(PLN[147, 129, 1, 3], 0.25, True) npt.assert_almost_equal(PLN[61, 152, 1, 0], 0.25, True) npt.assert_almost_equal(PLN[61, 152, 1, 1], 0.25, True) npt.assert_almost_equal(PLN[61, 152, 1, 2], 0.25, True) npt.assert_almost_equal(PLN[61, 152, 1, 3], 0.25, True) npt.assert_almost_equal(PLN[100, 100, 1, 0], 0.25, True) npt.assert_almost_equal(PLN[100, 100, 1, 1], 0.25, True) npt.assert_almost_equal(PLN[100, 100, 1, 2], 0.25, True) npt.assert_almost_equal(PLN[100, 100, 1, 3], 0.25, True) PLY = com.prob_image(image, nclasses, mu, sigmasq, PLN) print(PLY) npt.assert_(np.all((PLY >= 0) & (PLY <= 1.0))) mu_upd, sigmasq_upd = com.update_param(image, PLY, mu, nclasses) print(mu) print(mu_upd) npt.assert_(mu_upd[0] != mu[0]) npt.assert_(mu_upd[1] != mu[1]) npt.assert_(mu_upd[2] != mu[2]) npt.assert_(mu_upd[3] != mu[3]) print(sigmasq) print(sigmasq_upd) npt.assert_(sigmasq_upd[0] != sigmasq[0]) npt.assert_(sigmasq_upd[1] != sigmasq[1]) npt.assert_(sigmasq_upd[2] != sigmasq[2]) npt.assert_(sigmasq_upd[3] != sigmasq[3]) icm_segmentation, energy = icm.icm_ising(neglogl, beta, initial_segmentation) npt.assert_(np.abs(np.sum(icm_segmentation)) != 0) npt.assert_(icm_segmentation.max() == nclasses - 1) npt.assert_(icm_segmentation.min() == 0)
def test_greyscale_iter(): max_iter = 15 beta = np.float64(0.1) com = ConstantObservationModel() icm = IteratedConditionalModes() mu, sigma = com.initialize_param_uniform(image, nclasses) sigmasq = sigma ** 2 neglogl = com.negloglikelihood(image, mu, sigmasq, nclasses) initial_segmentation = icm.initialize_maximum_likelihood(neglogl) npt.assert_(initial_segmentation.max() == nclasses - 1) npt.assert_(initial_segmentation.min() == 0) mu, sigma = com.seg_stats(image, initial_segmentation, nclasses) sigmasq = sigma ** 2 npt.assert_(mu[0] >= 0.0) npt.assert_(mu[1] >= 0.0) npt.assert_(mu[2] >= 0.0) npt.assert_(mu[3] >= 0.0) npt.assert_(sigmasq[0] >= 0.0) npt.assert_(sigmasq[1] >= 0.0) npt.assert_(sigmasq[2] >= 0.0) npt.assert_(sigmasq[3] >= 0.0) if background_noise: zero = np.zeros_like(image) + 0.001 zero_noise = add_noise(zero, 10000, 1, noise_type='gaussian') image_gauss = np.where(image == 0, zero_noise, image) else: image_gauss = image final_segmentation = np.empty_like(image) seg_init = initial_segmentation.copy() energies = [] for i in range(max_iter): PLN = icm.prob_neighborhood(initial_segmentation, beta, nclasses) npt.assert_(np.all((PLN >= 0) & (PLN <= 1.0))) if beta == 0.0: npt.assert_almost_equal(PLN[50, 50, 1, 0], 0.25, True) npt.assert_almost_equal(PLN[50, 50, 1, 1], 0.25, True) npt.assert_almost_equal(PLN[50, 50, 1, 2], 0.25, True) npt.assert_almost_equal(PLN[50, 50, 1, 3], 0.25, True) npt.assert_almost_equal(PLN[147, 129, 1, 0], 0.25, True) npt.assert_almost_equal(PLN[147, 129, 1, 1], 0.25, True) npt.assert_almost_equal(PLN[147, 129, 1, 2], 0.25, True) npt.assert_almost_equal(PLN[147, 129, 1, 3], 0.25, True) npt.assert_almost_equal(PLN[61, 152, 1, 0], 0.25, True) npt.assert_almost_equal(PLN[61, 152, 1, 1], 0.25, True) npt.assert_almost_equal(PLN[61, 152, 1, 2], 0.25, True) npt.assert_almost_equal(PLN[61, 152, 1, 3], 0.25, True) npt.assert_almost_equal(PLN[100, 100, 1, 0], 0.25, True) npt.assert_almost_equal(PLN[100, 100, 1, 1], 0.25, True) npt.assert_almost_equal(PLN[100, 100, 1, 2], 0.25, True) npt.assert_almost_equal(PLN[100, 100, 1, 3], 0.25, True) PLY = com.prob_image(image_gauss, nclasses, mu, sigmasq, PLN) npt.assert_(np.all((PLY >= 0) & (PLY <= 1.0))) npt.assert_(PLY[50, 50, 1, 0] > PLY[50, 50, 1, 1]) npt.assert_(PLY[50, 50, 1, 0] > PLY[50, 50, 1, 2]) npt.assert_(PLY[50, 50, 1, 0] > PLY[50, 50, 1, 3]) npt.assert_(PLY[100, 100, 1, 3] > PLY[100, 100, 1, 0]) npt.assert_(PLY[100, 100, 1, 3] > PLY[100, 100, 1, 1]) npt.assert_(PLY[100, 100, 1, 3] > PLY[100, 100, 1, 2]) mu_upd, sigmasq_upd = com.update_param(image_gauss, PLY, mu, nclasses) npt.assert_(mu_upd[0] >= 0.0) npt.assert_(mu_upd[1] >= 0.0) npt.assert_(mu_upd[2] >= 0.0) npt.assert_(mu_upd[3] >= 0.0) npt.assert_(sigmasq_upd[0] >= 0.0) npt.assert_(sigmasq_upd[1] >= 0.0) npt.assert_(sigmasq_upd[2] >= 0.0) npt.assert_(sigmasq_upd[3] >= 0.0) negll = com.negloglikelihood(image_gauss, mu_upd, sigmasq_upd, nclasses) npt.assert_(negll[50, 50, 1, 0] < negll[50, 50, 1, 1]) npt.assert_(negll[50, 50, 1, 0] < negll[50, 50, 1, 2]) npt.assert_(negll[50, 50, 1, 0] < negll[50, 50, 1, 3]) npt.assert_(negll[100, 100, 1, 3] < negll[100, 100, 1, 0]) npt.assert_(negll[100, 100, 1, 3] < negll[100, 100, 1, 1]) npt.assert_(negll[100, 100, 1, 3] < negll[100, 100, 1, 2]) final_segmentation, energy = icm.icm_ising(negll, beta, initial_segmentation) print(energy[energy > -np.inf].sum()) energies.append(energy[energy > -np.inf].sum()) initial_segmentation = final_segmentation.copy() mu = mu_upd.copy() sigmasq = sigmasq_upd.copy() npt.assert_(energies[-1] < energies[0]) difference_map = np.abs(seg_init - final_segmentation) npt.assert_(np.abs(np.sum(difference_map)) != 0)
def test_square_iter(): com = ConstantObservationModel() icm = IteratedConditionalModes() initial_segmentation = square mu, sigma = com.seg_stats(square_gauss, initial_segmentation, nclasses) sigmasq = sigma ** 2 npt.assert_(mu[0] >= 0.0) npt.assert_(mu[1] >= 0.0) npt.assert_(mu[2] >= 0.0) npt.assert_(mu[3] >= 0.0) npt.assert_(sigmasq[0] >= 0.0) npt.assert_(sigmasq[1] >= 0.0) npt.assert_(sigmasq[2] >= 0.0) npt.assert_(sigmasq[3] >= 0.0) final_segmentation = np.empty_like(square_gauss) seg_init = initial_segmentation.copy() energies = [] for i in range(max_iter): print('\n') print('>> Iteration: ' + str(i)) print('\n') PLN = icm.prob_neighborhood(initial_segmentation, beta, nclasses) npt.assert_(np.all((PLN >= 0) & (PLN <= 1.0))) if beta == 0.0: npt.assert_(PLN[25, 25, 1, 0] == 0.25) npt.assert_(PLN[25, 25, 1, 1] == 0.25) npt.assert_(PLN[25, 25, 1, 2] == 0.25) npt.assert_(PLN[25, 25, 1, 3] == 0.25) npt.assert_(PLN[50, 50, 1, 0] == 0.25) npt.assert_(PLN[50, 50, 1, 1] == 0.25) npt.assert_(PLN[50, 50, 1, 2] == 0.25) npt.assert_(PLN[50, 50, 1, 3] == 0.25) npt.assert_(PLN[90, 90, 1, 0] == 0.25) npt.assert_(PLN[90, 90, 1, 1] == 0.25) npt.assert_(PLN[90, 90, 1, 2] == 0.25) npt.assert_(PLN[90, 90, 1, 3] == 0.25) npt.assert_(PLN[125, 125, 1, 0] == 0.25) npt.assert_(PLN[125, 125, 1, 1] == 0.25) npt.assert_(PLN[125, 125, 1, 2] == 0.25) npt.assert_(PLN[125, 125, 1, 3] == 0.25) PLY = com.prob_image(square_gauss, nclasses, mu, sigmasq, PLN) npt.assert_(np.all((PLY >= 0) & (PLY <= 1.0))) npt.assert_(PLY[25, 25, 1, 0] > PLY[25, 25, 1, 1]) npt.assert_(PLY[25, 25, 1, 0] > PLY[25, 25, 1, 2]) npt.assert_(PLY[25, 25, 1, 0] > PLY[25, 25, 1, 3]) npt.assert_(PLY[125, 125, 1, 3] > PLY[125, 125, 1, 0]) npt.assert_(PLY[125, 125, 1, 3] > PLY[125, 125, 1, 1]) npt.assert_(PLY[125, 125, 1, 3] > PLY[125, 125, 1, 2]) mu_upd, sigmasq_upd = com.update_param(square_gauss, PLY, mu, nclasses) npt.assert_(mu_upd[0] >= 0.0) npt.assert_(mu_upd[1] >= 0.0) npt.assert_(mu_upd[2] >= 0.0) npt.assert_(mu_upd[3] >= 0.0) npt.assert_(sigmasq_upd[0] >= 0.0) npt.assert_(sigmasq_upd[1] >= 0.0) npt.assert_(sigmasq_upd[2] >= 0.0) npt.assert_(sigmasq_upd[3] >= 0.0) negll = com.negloglikelihood(square_gauss, mu_upd, sigmasq_upd, nclasses) npt.assert_(negll[25, 25, 1, 0] < negll[25, 25, 1, 1]) npt.assert_(negll[25, 25, 1, 0] < negll[25, 25, 1, 2]) npt.assert_(negll[25, 25, 1, 0] < negll[25, 25, 1, 3]) npt.assert_(negll[100, 100, 1, 3] < negll[125, 125, 1, 0]) npt.assert_(negll[100, 100, 1, 3] < negll[125, 125, 1, 1]) npt.assert_(negll[100, 100, 1, 3] < negll[125, 125, 1, 2]) final_segmentation, energy = icm.icm_ising(negll, beta, initial_segmentation) energies.append(energy[energy > -np.inf].sum()) initial_segmentation = final_segmentation.copy() mu = mu_upd.copy() sigmasq = sigmasq_upd.copy() difference_map = np.abs(seg_init - final_segmentation) npt.assert_(np.abs(np.sum(difference_map)) == 0.0)
def classify(self, image, nclasses, beta, tolerance=None, max_iter=None): r""" This method uses the Maximum a posteriori - Markov Random Field approach for segmentation by using the Iterative Conditional Modes and Expectation Maximization to estimate the parameters. Parameters ---------- image : ndarray, 3D structural image. nclasses : int, number of desired classes. beta : float, smoothing parameter, the higher this number the smoother the output will be. tolerance: float, value that defines the percentage of change tolerated to prevent the ICM loop to stop. Default is 1e-05. max_iter : float, fixed number of desired iterations. Default is 100. If the user only specifies this parameter, the tolerance value will not be considered. If none of these two parameters Returns ------- initial_segmentation : ndarray, 3D segmented image with all tissue types specified in nclasses. final_segmentation : ndarray, 3D final refined segmentation containing all tissue types. PVE : ndarray, 3D probability map of each tissue type. """ nclasses = nclasses + 1 # One extra class for the background energy_sum = [1e-05] com = ConstantObservationModel() icm = IteratedConditionalModes() if image.max() > 1: image = np.interp(image, [0, image.max()], [0.0, 1.0]) mu, sigma = com.initialize_param_uniform(image, nclasses) p = np.argsort(mu) mu = mu[p] sigma = sigma[p] sigmasq = sigma**2 neglogl = com.negloglikelihood(image, mu, sigmasq, nclasses) seg_init = icm.initialize_maximum_likelihood(neglogl) mu, sigma = com.seg_stats(image, seg_init, nclasses) sigmasq = sigma**2 zero = np.zeros_like(image) + 0.001 zero_noise = add_noise(zero, 10000, 1, noise_type='gaussian') image_gauss = np.where(image == 0, zero_noise, image) final_segmentation = np.empty_like(image) initial_segmentation = seg_init.copy() if max_iter is not None and tolerance is None: for i in range(max_iter): if self.verbose: print('>> Iteration: ' + str(i)) PLN = icm.prob_neighborhood(seg_init, beta, nclasses) PVE = com.prob_image(image_gauss, nclasses, mu, sigmasq, PLN) mu_upd, sigmasq_upd = com.update_param(image_gauss, PVE, mu, nclasses) ind = np.argsort(mu_upd) mu_upd = mu_upd[ind] sigmasq_upd = sigmasq_upd[ind] negll = com.negloglikelihood(image_gauss, mu_upd, sigmasq_upd, nclasses) final_segmentation, energy = icm.icm_ising( negll, beta, seg_init) if self.save_history: self.segmentations.append(final_segmentation) self.pves.append(PVE) self.energies.append(energy) self.energies_sum.append(energy[energy > -np.inf].sum()) seg_init = final_segmentation.copy() mu = mu_upd.copy() sigmasq = sigmasq_upd.copy() else: max_iter = 100 if tolerance is None: tolerance = 1e-05 for i in range(max_iter): if self.verbose: print('>> Iteration: ' + str(i)) PLN = icm.prob_neighborhood(seg_init, beta, nclasses) PVE = com.prob_image(image_gauss, nclasses, mu, sigmasq, PLN) mu_upd, sigmasq_upd = com.update_param(image_gauss, PVE, mu, nclasses) ind = np.argsort(mu_upd) mu_upd = mu_upd[ind] sigmasq_upd = sigmasq_upd[ind] negll = com.negloglikelihood(image_gauss, mu_upd, sigmasq_upd, nclasses) final_segmentation, energy = icm.icm_ising( negll, beta, seg_init) energy_sum.append(energy[energy > -np.inf].sum()) if self.save_history: self.segmentations.append(final_segmentation) self.pves.append(PVE) self.energies.append(energy) self.energies_sum.append(energy[energy > -np.inf].sum()) if i % 10 == 0 and i != 0: tol = tolerance * (np.amax(energy_sum) - np.amin(energy_sum)) test_dist = np.absolute( np.amax(energy_sum[np.size(energy_sum) - 5:i]) - np.amin(energy_sum[np.size(energy_sum) - 5:i])) if test_dist < tol: break seg_init = final_segmentation.copy() mu = mu_upd.copy() sigmasq = sigmasq_upd.copy() PVE = PVE[..., 1:] return initial_segmentation, final_segmentation, PVE