def test_label_costs_graph(self): """Test the label_costs argument with cut_from_graph.""" unaries, pairwise, edges, expected = self.binary_data() # Give a slight preference to class 0 unaries[:, :, 1] += 1 result = cut_from_graph(edges, unaries.reshape(-1, 2), pairwise, label_cost=1) result = result.reshape(unaries.shape[:2]) self.assertTrue(np.array_equal(result, expected)) # Try again with a very high label cost to collapse to a single label result = cut_from_graph(edges, unaries.reshape(-1, 2), pairwise, label_cost=1000) result = result.reshape(unaries.shape[:2]) self.assertTrue(np.array_equal(result, np.zeros_like(result)))
def test_label_costs_graph(self): """Test the label_costs argument with cut_from_graph.""" unaries, pairwise, edges, expected = self.binary_data() # unaries, pairwise, edges, expected = self.binary_data_float() # Give a slight preference to class 0 unaries[:, :, 1] += 1 label_cost = np.array([1, 1]) # label_cost = np.random.rand(2) weight = np.random.rand(edges.shape[0]).astype(np.float32) unaries = unaries.astype(np.float32) pairwise = pairwise.astype(np.float32) label_cost = label_cost.astype(np.float32) print(unaries, unaries.dtype) print(pairwise, pairwise.dtype) print(edges.shape) print(expected, expected.dtype) print(label_cost, label_cost.dtype) result = cut_from_graph(edges, weight, unaries.reshape(-1, 2), pairwise, label_cost) result = result.reshape(unaries.shape[:2]) print(result) self.assertTrue(np.array_equal(result, expected))
def cut_graph_profile(cellGraph, Kmean_labels, unary_scale_factor=100, smooth_factor=50, label_cost=10, algorithm='expansion'): ''' Returns new labels and gmm for the cut. :param points: cellGraph (n,3); count: shape (n,); :unary_scale_factor, scalar; smooth_factor, scalar; :label_cost: scalar; algorithm='expansion' :rtype: label shape (n,); gmm object. ''' smooth_factor = smooth_factor unary_scale_factor = unary_scale_factor label_cost = label_cost algorithm = algorithm uniq, count = np.unique(Kmean_labels, return_counts=True) unary_cost = compute_unary_cost_profile(Kmean_labels, unary_scale_factor) pairwise_cost = compute_pairwise_cost(len(uniq), smooth_factor) edges = cellGraph[:, 0:2].astype(np.int32) labels = pygco.cut_from_graph(edges, unary_cost, pairwise_cost, label_cost) # energy = compute_energy(unary_cost, pairwise_cost, edges, labels) return labels
def run_inference(model, thresh=None, n_labels=None, n_iter=5, algorithm='expansion'): import pygco if n_labels is not None: model._update_labels(n_labels) if thresh is not None: model._update_weights(thresh=thresh) if model.n_labels <= 0: raise ValueError('cannot run inference with zero labels') if model.n_labels == 1: labeling = np.zeros(model.n_nodes, dtype=np.int32) else: cutkw = dict(n_iter=n_iter, algorithm=algorithm) if 0: print(ut.code_repr(model.unaries, 'unaries')) print(ut.code_repr(model.weighted_edges, 'weighted_edges')) print(ut.code_repr(model.pairwise_potts, 'pairwise_potts')) print(ut.code_repr(cutkw, 'cutkw')) labeling = pygco.cut_from_graph(model.weighted_edges, model.unaries, model.pairwise_potts, **cutkw) model.labeling = labeling #print('model.total_energy = %r' % (model.total_energy,)) return labeling
def test_cut_from_grpah(self): """Test the cut_from_graph method.""" unaries, pairwise, edges, expected = self.binary_data() result = cut_from_graph(edges, unaries.reshape(-1, 2), pairwise) result = result.reshape(unaries.shape[:2]) self.assertTrue(np.array_equal(result, expected))
def constantEdges() : edges = [] with open(PATH + 'edges.csv', 'rb') as f : reader = csv.reader(f) reader.next() for row in reader : edges.append(row) edges = np.array(edges, dtype='int32', ndmin=2) edges = edges - 1 unary = [] with open(PATH + 'unary.csv', 'rb') as f : reader = csv.reader(f) reader.next() for row in reader : unary.append(row) unary = np.array(unary, dtype = "float32") unary = (-100 * unary).copy("C").astype(np.int32) edge_weights = [] with open(PATH + 'edge_weights.csv', 'rb') as f : reader = csv.reader(f) reader.next() for row in reader : edge_weights.append(row) edge_weights = np.array(edge_weights, dtype = "int32") edge_weights.shape = (len(edges),) num_blocks, num_labels = unary.shape pairwise = -50 * np.eye(num_labels, dtype=np.int32) # pairwise[:, num_labels-1] = -40 # pairwise[num_labels-1, :] = -40 # pairwise[num_labels-1, num_labels-1] = -50 print pairwise edge_weights.shape = (len(edge_weights), 1) edges = np.concatenate((edges, edge_weights), axis=1) (result_graph, energy) = cut_from_graph(edges, unary, pairwise, algorithm="swap", n_iter = -1) print energy print energy_of_graph_assignment(edges, unary, pairwise, result_graph) with open(PATH + 'potts_labels.csv', 'wb') as f: writer = csv.writer(f) writer.writerow(['label']) for label in result_graph : writer.writerow([label + 1])
def segment_edge_cut(self): # noinspection PyUnresolvedReferences from pygco import cut_from_graph height = self.image.shape[0] width = self.image.shape[1] # first, we construct the grid graph # inds is a matrix of cell indices inds = np.arange(height * width).reshape(height, width) # list of all horizontal and vertical edges horizontal_edges = np.c_[inds[:, :-1].ravel(), inds[:, 1:].ravel()] vertical_edges = np.c_[inds[:-1, :].ravel(), inds[1:, :].ravel()] # concatenate both lists edges = np.vstack([horizontal_edges, vertical_edges]).astype(np.int32) # the edge weight multiplies the logarithm of the probability, this is the same as potentiating the probability # and renormalizing def effective_probability(probability, weight): return probability ** weight / (probability ** weight + (1 - probability) ** weight) depth = self.feature_images['depth'].reshape(-1) depth[depth == -1] = np.nan self.edge_depth_diff = np.abs(depth[edges[:, 0]] - depth[edges[:, 1]]) weights = np.ones([edges.shape[0], 1]) # weight is 1 for nan depth_diff_thres = 0.02 # in m # replace nans with threshold to prevent comparing to nan warnings self.edge_depth_diff[np.isnan(self.edge_depth_diff)] = depth_diff_thres smooth_depth_edges = self.edge_depth_diff < depth_diff_thres sharp_depth_edges = self.edge_depth_diff > depth_diff_thres weights[smooth_depth_edges] = 2 # effective for 0.95 + weight 2 -> 0.9972375 weights[sharp_depth_edges] = 0 # add this for displaying the depth edges self.depth_edge_image = np.zeros(height * width) self.depth_edge_image[edges[smooth_depth_edges].reshape(-1)] = -1 self.depth_edge_image[edges[sharp_depth_edges].reshape(-1)] = 1 self.depth_edge_image = self.depth_edge_image.reshape(height, width) edges = np.hstack([edges, weights]) # compute potentials (log of probabilities) unaries = -np.log(np.array([np.clip(self.posterior_images[o],a_min=0.01, a_max=1.0) for o in self.candidate_objects])).transpose((1, 2, 0)) num_labels = unaries.shape[2] p_same_label = 0.95 pairwise = -np.log(1 - p_same_label) * (1 - np.eye(num_labels)) - np.log(p_same_label) * np.eye(num_labels) k = 10 # scaling factor for potentials to reduce aliasing because the potentials need to be converted to integers unaries_c = np.copy((k * unaries).astype('int32'), order='C').reshape(-1, num_labels) pairwise_c = np.copy((k * pairwise).astype('int32'), order='C') edges_c = edges.astype('int32') self.segmentation = cut_from_graph(edges_c, unaries_c, pairwise_c).reshape(height, width)
def graphcut_edge_weight(unary_costs, color_vars, centroids, alpha_val=alpha): #unary_costs_int32 = (alpha*unary_costs).astype('int32') unary_cost_list = np.zeros( (np.shape(unary_costs)[0] * np.shape(unary_costs)[1], np.shape(unary_costs)[2])) rows = np.shape(unary_costs)[0] cols = np.shape(unary_costs)[1] edges_weights = [] for r in range(rows): for c in range(cols): unary_cost_list[get_list_index(r, c, cols), :] = unary_costs[r, c, :] row_safe = r != rows - 1 col_safe = c != cols - 1 if (row_safe): edges_weights.append([ get_list_index(r, c, cols), get_list_index(r + 1, c, cols), get_weight(r, c, r + 1, c, color_vars) ]) if (col_safe): edges_weights.append([ get_list_index(r, c, cols), get_list_index(r, c + 1, cols), get_weight(r, c, r, c + 1, color_vars) ]) if (row_safe and col_safe): edges_weights.append([ get_list_index(r, c + 1, cols), get_list_index(r + 1, c, cols), get_weight(r, c + 1, r + 1, c, color_vars) ]) edges_weights.append([ get_list_index(r + 1, c, cols), get_list_index(r, c + 1, cols), get_weight(r + 1, c, r, c + 1, color_vars) ]) edges_weights_int32 = np.array(edges_weights).astype('int32') binary_costs_int32 = get_binary_costs(centroids) unary_cost_list_int32 = (alpha_val * unary_cost_list).astype('int32') test_labels_list = pygco.cut_from_graph(edges_weights_int32, unary_cost_list_int32, binary_costs_int32, n_iter=-1, algorithm='swap') test_labels = np.zeros( (np.shape(unary_costs)[0], np.shape(unary_costs)[1])) for r in range(rows): for c in range(cols): test_labels[r, c] = test_labels_list[get_list_index(r, c, cols)] return test_labels.astype('int')
def set_data(self, data, voxels1, voxels2, seeds = False, hard_constraints = True): """ Setting of data. You need set seeds if you want use hard_constraints. """ mdl = Model ( modelparams = self.modelparams ) mdl.train(voxels1, 1) mdl.train(voxels2, 2) #pdb.set_trace(); #tdata = {} # as we convert to int, we need to multipy to get sensible values # There is a need to have small vaues for good fit # R(obj) = -ln( Pr (Ip | O) ) # R(bck) = -ln( Pr (Ip | B) ) # Boykov2001a # ln is computed in likelihood tdata1 = (-(mdl.likelihood(data, 1))) * 10 tdata2 = (-(mdl.likelihood(data, 2))) * 10 #pyed = py3DSeedEditor.py3DSeedEditor(tdata1) #pyed = py3DSeedEditor.py3DSeedEditor(seeds) #pyed.show() #pdb.set_trace(); if hard_constraints: #pdb.set_trace(); if (type(seeds)=='bool'): raise Exception ('Seeds variable not set','There is need set seed if you want use hard constraints') tdata1, tdata2 = self.set_hard_hard_constraints(tdata1, tdata2, seeds) unariesalt = (1 * np.dstack([tdata1.reshape(-1,1), tdata2.reshape(-1,1)]).copy("C")).astype(np.int32) # create potts pairwise #pairwiseAlpha = -10 pairwise = -self.gcparams['pairwiseAlpha'] * np.eye(2, dtype=np.int32) # use the gerneral graph algorithm # first, we construct the grid graph inds = np.arange(data.size).reshape(data.shape) edgx = np.c_[inds[:, :, :-1].ravel(), inds[:, :, 1:].ravel()] edgy = np.c_[inds[:, :-1, :].ravel(), inds[:, 1:, :].ravel()] edgz = np.c_[inds[:-1, :, :].ravel(), inds[1:, :, :].ravel()] edges = np.vstack([edgx, edgy, edgz]).astype(np.int32) # edges - seznam indexu hran, kteres spolu sousedi # we flatten the unaries #result_graph = cut_from_graph(edges, unaries.reshape(-1, 2), pairwise) result_graph = cut_from_graph(edges, unariesalt.reshape(-1,2), pairwise) result_labeling = result_graph.reshape(data.shape) return result_labeling
def example_binary(): # generate trivial data x = np.ones((10, 10)) x[:, 5:] = -1 x_noisy = x + np.random.normal(0, 0.8, size=x.shape) x_thresh = x_noisy > 0.0 # create unaries unaries = x_noisy # as we convert to int, we need to multipy to get sensible values unaries = (10 * np.dstack([unaries, -unaries]).copy("C")).astype(np.int32) # create potts pairwise pairwise = -10 * np.eye(2, dtype=np.int32) # do simple cut result = cut_simple(unaries, pairwise) # generalized Potts potentials pix_nums = np.r_[: 10 * 10].reshape(10, 10) pairwise_cost = dict( [(tuple(sorted(pair)), 30) for pair in zip(pix_nums[:, :-1].flatten(), pix_nums[:, 1:].flatten())] + [(tuple(sorted(pair)), 0) for pair in zip(pix_nums[:-1, :].flatten(), pix_nums[1:, :].flatten())] ) result_gp = cut_simple_gen_potts(unaries, pairwise_cost) # use the gerneral graph algorithm # first, we construct the grid graph inds = np.arange(x.size).reshape(x.shape) horz = np.c_[inds[:, :-1].ravel(), inds[:, 1:].ravel()] vert = np.c_[inds[:-1, :].ravel(), inds[1:, :].ravel()] edges = np.vstack([horz, vert]).astype(np.int32) # we flatten the unaries result_graph = cut_from_graph(edges, unaries.reshape(-1, 2), pairwise) # generalized Potts potentials result_graph_gp = cut_from_graph_gen_potts(unaries.reshape(-1, 2), pairwise_cost) # plot results plt.subplot(231, title="original") plt.imshow(x, interpolation="nearest") plt.subplot(232, title="noisy version") plt.imshow(x_noisy, interpolation="nearest") plt.subplot(233, title="rounded to integers") plt.imshow(unaries[:, :, 0], interpolation="nearest") plt.subplot(234, title="thresholding result") plt.imshow(x_thresh, interpolation="nearest") plt.subplot(235, title="cut_simple") plt.imshow(result, interpolation="nearest") plt.subplot(236, title="cut_from_graph") plt.imshow(result_graph.reshape(x.shape), interpolation="nearest") plt.show()
def apply_pygco(transforms, pts): edges = triangulate_query(pts) unaries = compile_transfer_errors(transforms, pts) # Outlier label unaries = np.insert(unaries, 0, OUTLIER_DISTANCE, axis=1) pairwise = PAIRWISE_WEIGHTING * np.eye(len(transforms) + 1).astype(np.int32) ''' print 'edges', edges.shape print 'unaries', unaries.shape print 'transforms', pairwise.shape print 'edges', edges print 'unaries', unaries print 'transforms', pairwise ''' result = cut_from_graph(edges, unaries, pairwise) print 'result', result cnt = collections.Counter() for label in result: cnt[label] += 1 # While the best label is an outlier label (not a good sign to start) counted_items = cnt.items() not_outlier = list(sorted(filter(lambda x: x[0] != 0, cnt.items()), key=itemgetter(1), reverse=True)) print 'not outlier:', not_outlier best_label = not_outlier[0][0] second_best_label = not_outlier[1][0] best_points = [] second_best_points = [] for index, label in enumerate(result): if label == best_label: best_points.append(pts[index]) elif label == second_best_label: second_best_points.append(pts[index]) best_points_scores = [] second_best_points_scores = [] best_points_scores = unaries[:, best_label].tolist() second_best_points_scores = unaries[:, second_best_label].tolist() return (transforms[best_label - 1], transforms[second_best_label - 1], best_points, second_best_points, best_points_scores, second_best_points_scores)
def run_inference(model, thresh=None, n_labels=None, n_iter=5, algorithm='expansion'): import pygco if n_labels is not None: model._update_labels(n_labels) if thresh is not None: model._update_weights(thresh=thresh) if model.n_labels <= 0: raise ValueError('cannot run inference with zero labels') if model.n_labels == 1: labeling = np.zeros(model.n_nodes, dtype=np.int32) else: cutkw = dict(n_iter=n_iter, algorithm=algorithm) labeling = pygco.cut_from_graph(model.weighted_edges, model.unaries, model.pairwise_potts, **cutkw) model.labeling = labeling #print('model.total_energy = %r' % (model.total_energy,)) return labeling
def example_binary(): # generate trivial data x = np.ones((10, 10)) x[:, 5:] = -1 x_noisy = x + np.random.normal(0, 0.8, size=x.shape) x_thresh = x_noisy > .0 # create unaries unaries = x_noisy # as we convert to int, we need to multipy to get sensible values unaries = (10 * np.dstack([unaries, -unaries]).copy("C")).astype(np.int32) # create potts pairwise pairwise = -10 * np.eye(2, dtype=np.int32) # do simple cut result = cut_simple(unaries, pairwise) # use the gerneral graph algorithm # first, we construct the grid graph inds = np.arange(x.size).reshape(x.shape) horz = np.c_[inds[:, :-1].ravel(), inds[:, 1:].ravel()] vert = np.c_[inds[:-1, :].ravel(), inds[1:, :].ravel()] edges = np.vstack([horz, vert]).astype(np.int32) # we flatten the unaries result_graph = cut_from_graph(edges, unaries.reshape(-1, 2), pairwise) # plot results plt.subplot(231, title="original") plt.imshow(x, interpolation='nearest') plt.subplot(232, title="noisy version") plt.imshow(x_noisy, interpolation='nearest') plt.subplot(233, title="rounded to integers") plt.imshow(unaries[:, :, 0], interpolation='nearest') plt.subplot(234, title="thresholding result") plt.imshow(x_thresh, interpolation='nearest') plt.subplot(235, title="cut_simple") plt.imshow(result, interpolation='nearest') plt.subplot(236, title="cut_from_graph") plt.imshow(result_graph.reshape(x.shape), interpolation='nearest') plt.show()
def example_3d(): x = np.ones((10, 10, 10)) x[:, 5:, :] = -1 x_noisy = x + np.random.normal(0, 0.8, size=x.shape) x_thresh = x_noisy > .0 # create unaries unaries = x_noisy # as we convert to int, we need to multipy to get sensible values unariesalt = (10 * np.dstack([unaries.reshape(-1,1), -unaries.reshape(-1,1)]).copy("C")).astype(np.int32) # unariesa = (10 * unaries).astype(np.int32) # unariesb = (-10* unaries).astype(np.int32) # unariescol = np.concatenate([unariesa.reshape(-1,1), unariesb.reshape(-1,1)], axis=1).astype(np.int32) # create potts pairwise pairwise = -10 * np.eye(2, dtype=np.int32) # use the gerneral graph algorithm # first, we construct the grid graph inds = np.arange(x.size).reshape(x.shape) edgx = np.c_[inds[:, :, :-1].ravel(), inds[:, :, 1:].ravel()] edgy = np.c_[inds[:, :-1, :].ravel(), inds[:, 1:, :].ravel()] edgz = np.c_[inds[:-1, :, :].ravel(), inds[1:, :, :].ravel()] edges = np.vstack([edgx, edgy, edgz]).astype(np.int32) pdb.set_trace() # we flatten the unaries #result_graph = cut_from_graph(edges, unaries.reshape(-1, 2), pairwise) result_graph = cut_from_graph(edges, unariesalt.reshape(-1,2), pairwise) result_labeling = result_graph.reshape(x.shape) #show results for 3th slice plt.subplot(311, title="original") plt.imshow(x[:,:,3], interpolation='nearest') plt.subplot(312, title="noisy version") plt.imshow(x_noisy[:,:,3], interpolation='nearest') plt.subplot(313, title="cut_from_graph") plt.imshow(result_labeling[:,:,3], interpolation='nearest') plt.show()
def solve(self, unary_term, pairwise_term, k): ''' Args : unary_term - Numpy 2d array [nvertex, nlabel] unary_term term to be minimized pairwise_term - Numpy 2d array [nvertex, nvertex] pairwise_term term to be minimized k - int ''' assert unary_term.shape[1]==self.nlabel, "Unary term have wrong labels" nvertex = unary_term.shape[0] assert pairwise_term.shape==(nvertex, nvertex), "Pairwise term haver wrong shape" unary_term = unary_term*self.value1*self.value2 unary_term = unary_term.astype(np.int32) nedges = nvertex*(nvertex-1)/2 nedges = int(nedges) self.edges = np.zeros([nedges, 3], dtype=np.float32) idx = 0 for i in range(nvertex): for j in range(i+1, nvertex): self.edges[idx] = [i, j, -self.value2*pairwise_term[i][j]] idx+=1 self.edges = self.edges.astype(np.int32) binary_vector = np.zeros([nvertex, self.nlabel], dtype=np.float32) energy = 0 keep = unary_term for _ in range(k): results = cut_from_graph(edges=self.edges, unary_cost=unary_term, pairwise_cost=self.pairwise_cost, n_iter=self.niter, algorithm='swap') for i, j in enumerate(results): binary_vector[i][j] = 1 unary_term[i][j] = np.iinfo(np.int32).max//2 return binary_vector
def cut_graph_general_profile(cellGraph, count,gmm, unary_scale_factor=100, smooth_factor=50, label_cost=10, algorithm='expansion'): ''' Returns new labels and gmm for the cut with gmm profile. :param points: cellGraph (n,3); count: shape (n,); :unary_scale_factor, scalar; smooth_factor, scalar; :label_cost: scalar; algorithm='expansion' :rtype: label shape (n,); gmm object. ''' unary_scale_factor = unary_scale_factor label_cost = label_cost algorithm = algorithm smooth_factor = smooth_factor gmm=gmm unary_cost = compute_unary_cost_simple_profile(count, gmm, unary_scale_factor) pairwise_cost = compute_pairwise_cost(gmm.means_.shape[0], smooth_factor) edges = cellGraph[:,0:2].astype(np.int32) labels = pygco.cut_from_graph(edges, unary_cost, pairwise_cost, label_cost) # energy = compute_energy(unary_cost, pairwise_cost, edges, labels) return labels
def cut_graph_general(cellGraph, count,gmm, unary_scale_factor=100, smooth_factor=30, label_cost=10, algorithm='expansion', profile=False): ''' Returns new labels and gmm for the cut. :param points: cellGraph (n,3); count: shape (n,); :unary_scale_factor, scalar; smooth_factor, scalar; :label_cost: scalar; algorithm='expansion' :rtype: label shape (n,); gmm object. ''' unary_scale_factor = unary_scale_factor label_cost = label_cost algorithm = algorithm smooth_factor = smooth_factor gmm=gmm # a = count.copy() # if sum(a>1)/len(count) <= 0.1 and sum(a>1)<=30: ### 1-1, 0.25 can modify # np.place(a, a==0, (np.random.rand(sum(a==0))*0.25)) # using 0.1 gives layer 4 300; 0.25 gives 150; 0.5 gives 80? # gmm = find_mixture_2(a) # else: # a=a[a>0] # gmm = find_mixture(a) if profile==False: unary_cost = compute_unary_cost_simple(count, gmm, unary_scale_factor) else: unary_cost = compute_unary_cost_simple_profile(count, gmm, unary_scale_factor) pairwise_cost = compute_pairwise_cost(gmm.means_.shape[0], smooth_factor) edges = cellGraph[:,0:2].astype(np.int32) labels = pygco.cut_from_graph(edges, unary_cost, pairwise_cost.astype(np.int32), np.int32(label_cost)) # energy = compute_energy(unary_cost, pairwise_cost, edges, labels) return labels
def __multiscale_gc(self): # , pyed): """ In first step is performed normal GC. Second step construct finer grid on edges of segmentation from first step. There is no option for use without `use_boundary_penalties` """ deb = False # deb = True # import py3DSeedEditor as ped from PyQt4.QtCore import pyqtRemoveInputHook pyqtRemoveInputHook() import scipy import scipy.ndimage logger.debug('performing multiscale_gc') # default parameters sparams_lo = { 'boundary_dilatation_distance': 2, 'block_size': 6, 'use_boundary_penalties': True, 'boundary_penalties_weight': 1, 'tile_zoom_constant': 1 } sparams_lo.update(self.segparams) sparams_hi = copy.copy(sparams_lo) sparams_lo['boundary_penalties_weight'] = ( sparams_lo['boundary_penalties_weight'] * sparams_lo['block_size']) self.segparams = sparams_lo # step 1: low res GC hiseeds = self.seeds # ms_zoom = 4 # 0.125 #self.segparams['scale'] ms_zoom = self.segparams['block_size'] # loseeds = pyed.getSeeds() # logger.debug("msc " + str(np.unique(hiseeds))) loseeds = self.__seed_zoom(hiseeds, ms_zoom) area_weight = 1 hard_constraints = True self.seeds = loseeds self.voxels1 = self.img[self.seeds == 1] self.voxels2 = self.img[self.seeds == 2] # self.voxels1 = pyed.getSeedsVal(1) # self.voxels2 = pyed.getSeedsVal(2) img_orig = self.img self.img = scipy.ndimage.interpolation.zoom(img_orig, 1.0 / ms_zoom, order=0) self.make_gc() logger.debug( 'segmentation - max: %d min: %d' % ( np.max(self.segmentation), np.min(self.segmentation) ) ) seg = 1 - self.segmentation.astype(np.int8) # in seg is now stored low resolution segmentation # step 2: discontinuity localization # self.segparams = sparams_hi segl = scipy.ndimage.filters.laplace(seg, mode='constant') logger.debug(str(np.max(segl))) logger.debug(str(np.min(segl))) segl[segl != 0] = 1 logger.debug(str(np.max(segl))) logger.debug(str(np.min(segl))) # scipy.ndimage.morphology.distance_transform_edt boundary_dilatation_distance = self.segparams[ 'boundary_dilatation_distance'] seg = scipy.ndimage.morphology.binary_dilation( seg, np.ones([ (boundary_dilatation_distance * 2) + 1, (boundary_dilatation_distance * 2) + 1, (boundary_dilatation_distance * 2) + 1 ]) ) if deb: import sed3 pd = sed3.sed3(seg) # ), contour=seg) pd.show() # segzoom = scipy.ndimage.interpolation.zoom(seg.astype('float'), zoom, # order=0).astype('int8') # step 3: indexes of new dual graph msinds = self.__multiscale_indexes(seg, img_orig.shape, ms_zoom) logger.debug('multiscale inds ' + str(msinds.shape)) # if deb: # import sed3 # pd = sed3.sed3(msinds, contour=seg) # pd.show() # intensity values for indexes # @TODO compute average values for low resolution ms_img = img_orig # @TODO __ms_create_nlinks , use __ordered_values_by_indexes # import pdb; pdb.set_trace() # BREAKPOINT # pyed.setContours(seg) # there is need to set correct weights between neighbooring pixels # this is not nice hack. # @TODO reorganise segparams and create_nlinks function self.img = img_orig # not necessary orig_shape = img_orig.shape def local_ms_npenalty(x): return self.__ms_npenalty_fcn(x, seg, ms_zoom, orig_shape) # return self.__uniform_npenalty_fcn(orig_shape) # ms_npenalty_fcn = lambda x: self.__ms_npenalty_fcn(x, seg, ms_zoom, # orig_shape) # here are not unique couples of nodes nlinks_not_unique = self.__create_nlinks( ms_img, msinds, # boundary_penalties_fcn=ms_npenalty_fcn boundary_penalties_fcn=local_ms_npenalty ) # get unique set # remove repetitive link from one pixel to another nlinks = np.array( [list(x) for x in set(tuple(x) for x in nlinks_not_unique)] ) # now remove cycle link nlinks = np.array([line for line in nlinks if line[0] != line[1]]) # import ipdb; ipdb.set_trace() # noqa BREAKPOINT # tlinks - indexes, data_merge ms_values_lin = self.__ordered_values_by_indexes(img_orig, msinds) seeds = hiseeds # seeds = pyed.getSeeds() # if deb: # import sed3 # se = sed3.sed3(seeds) # se.show() ms_seeds_lin = self.__ordered_values_by_indexes(seeds, msinds) # logger.debug("unique seeds " + str(np.unique(seeds))) # logger.debug("unique seeds " + str(np.unique(ms_seeds_lin))) unariesalt = self.__create_tlinks(ms_values_lin, self.voxels1, self.voxels2, ms_seeds_lin, area_weight, hard_constraints) # create potts pairwise # pairwiseAlpha = -10 pairwise = -(np.eye(2) - 1) pairwise = (self.segparams['pairwise_alpha'] * pairwise ).astype(np.int32) # print 'data shape ', img_orig.shape # print 'nlinks sh ', nlinks.shape # print 'tlinks sh ', unariesalt.shape # Same functionality is in self.seg_data() result_graph = pygco.cut_from_graph( nlinks, unariesalt.reshape(-1, 2), pairwise ) # probably not necessary # del nlinks # del unariesalt # print "unaries %.3g , %.3g" % (np.max(unariesalt),np.min(unariesalt)) # @TODO get back original data # result_labeling = result_graph.reshape(data.shape) result_labeling = result_graph[msinds] # import py3DSeedEditor # ped = py3DSeedEditor.py3DSeedEditor(result_labeling) # ped.show() self.segmentation = result_labeling
# plt.show() # pairwise term alpha = 50 pairwise = - alpha * np.eye(n_components, dtype=np.int32) print 'deriving graph edges...' # use the general graph algorithm # first, we construct the grid graph inds = np.arange(im.size).reshape(im.shape) horz = np.c_[inds[:, :-1].ravel(), inds[:, 1:].ravel()] vert = np.c_[inds[:-1, :].ravel(), inds[1:, :].ravel()] edges = np.vstack([horz, vert]).astype(np.int32) # we flatten the unaries result_graph = cut_from_graph(edges, unaries.reshape(-1, n_components), pairwise) res = result_graph.reshape(im.shape) plt.figure() plt.subplot(121), plt.imshow(im, 'gray'), plt.title('input image') plt.subplot(122), plt.imshow(res, 'gray'), plt.title('segmentation') # plt.show() # plotting results color_iter = itertools.cycle(['r', 'g', 'b', 'c', 'm', 'y', 'k']) x = np.arange(0, 255, 0.1) hist, bins = skiexp.histogram(pixs, nbins=256) plt.figure() plt.subplot(211), plt.plot(bins, hist) ax = plt.axis()
def sparse_approximation(self): ''' Use a few manifolds to sparsely approximate the pareto front by graph-cut, see section 6.4. Output: labels: the optimized labels (manifold index) for each non-empty cell (the cells also contain the corresponding labeled sample), shape = (n_label,) approx_x: the labeled design samples, shape = (n_label, n_var) approx_y: the labeled performance values, shape = (n_label, n_obj) ''' # update patch ids, remove non-existing ids previously removed from buffer mapping = {} patch_id_count = 0 for cell_id in range(self.cell_num): if self.buffer_patch_id[cell_id] == []: continue curr_patches = self.buffer_patch_id[cell_id] for i in range(len(curr_patches)): if curr_patches[i] not in mapping: mapping[curr_patches[i]] = patch_id_count patch_id_count += 1 self.buffer_patch_id[cell_id][i] = mapping[curr_patches[i]] # construct unary and pairwise energy (cost) matrix for graph-cut # NOTE: delta_b should be set properly valid_cells = np.where([ self.buffer_dist[cell_id] != [] for cell_id in range(self.cell_num) ])[0] # non-empty cells n_node = len(valid_cells) n_label = patch_id_count unary_cost = self.C_inf * np.ones((n_node, n_label)) pairwise_cost = -self.C_inf * np.eye(n_label) for i, idx in enumerate(valid_cells): patches, distances = np.array(self.buffer_patch_id[idx]), np.array( self.buffer_dist[idx]) min_dist = np.min(distances) unary_cost[i, patches] = np.minimum( (distances - min_dist) / self.delta_b, self.C_inf) # get edge information (graph structure) edges = self._get_graph_edges(valid_cells) # NOTE: pygco only supports int32 as input, due to potential numerical error edges, unary_cost, pairwise_cost, label_cost = \ edges.astype(np.int32), unary_cost.astype(np.int32), pairwise_cost.astype(np.int32), np.int32(self.label_cost) # do graph-cut, optimize labels for each valid cell labels_opt = cut_from_graph(edges, unary_cost, pairwise_cost, label_cost) # find corresponding design and performance values of optimized labels for each valid cell approx_xs, approx_ys = [], [] labels = [ ] # for a certain cell, there could be no sample belongs to that label, probably due to the randomness of sampling or improper energy definition for idx, label in zip(valid_cells, labels_opt): for cell_patch_id, cell_x, cell_y in zip(self.buffer_patch_id[idx], self.buffer_x[idx], self.buffer_y[idx]): # since each buffer element array is sorted based on distance to origin if cell_patch_id == label: approx_xs.append(cell_x) approx_ys.append(cell_y) labels.append(label) break else: # TODO: check approx_xs.append(self.buffer_x[idx][0]) approx_ys.append(self.buffer_y[idx][0]) labels.append(label) approx_xs, approx_ys = np.array(approx_xs), np.array(approx_ys) # NOTE: uncomment code below to show visualization of graph cut # import matplotlib.pyplot as plt # from matplotlib import cm # cmap = cm.get_cmap('tab20', patch_id_count) # fig, axs = plt.subplots(1, 2, sharex=True, sharey=True) # buffer_ys = np.vstack([np.vstack(cell_y) for cell_y in self.buffer_y if cell_y != []]) # buffer_patch_ids = np.concatenate([cell_patch_id for cell_patch_id in np.array(self.buffer_patch_id)[valid_cells]]) # colors = [cmap(patch_id) for patch_id in buffer_patch_ids] # axs[0].scatter(*buffer_ys.T, s=10, c=colors) # axs[0].set_title('Before graph cut') # colors = [cmap(label) for label in labels] # axs[1].scatter(*approx_ys.T, s=10, c=colors) # axs[1].set_title('After graph cut') # fig.suptitle(f'Sparse approximation, # patches: {patch_id_count}, # families: {len(np.unique(labels))}') # plt.show() return labels, approx_xs, approx_ys
def run_mrf(data_o, params): # slice_idx = self.params['slice_idx'] alpha = params['alpha'] beta = params['beta'] # hypo_lab = params['hypo_label'] # hyper_lab = params['hyper_label'] # zooming the data print 'rescaling data ...', if params['zoom']: data = data_zoom(data_o.data, data_o.voxel_size, params['working_voxel_size_mm']) mask = data_zoom(data_o.mask, data_o.voxel_size, params['working_voxel_size_mm']) else: data = tools.resize3D(data_o.data, params['scale']) mask = np.round(tools.resize3D(data_o.mask, params['scale'])).astype(np.bool) print 'ok' # smoothing the data # data = tools.smoothing_tv(data, weight=5, output_as_uint8=False, sliceId=0) # data = tools.smoothing_median(data, radius=3, mask=mask, sliceId=0) # np.save('data.npy', data) # data = data.astype(np.uint8) # calculating intensity models if necesarry print 'estimating color models ...' if data_o.models is None: data_o.models = calculate_intensity_models(data, mask, params) print 'ok' else: print 'already done' # mask = tools.dilating3D(mask, selem=skimor.disk(1), slicewise=True, sliceId=0) # mask = tools.eroding3D(mask, selem=skimor.disk(5), slicewise=True, sliceId=0) print 'calculating unary potentials ...', # self.status_bar.showMessage('Calculating unary potentials...') # create unaries # # as we convert to int, we need to multipy to get sensible values # unaries = (1 * np.dstack([unaries, -unaries]).copy("C")).astype(np.int32) # data_o.models = get_fuzzy_models(data, mask, n_clusters=3) unaries = beta * get_unaries(data, mask, data_o.models, params) # mems, cntrs, fpc = fcm(data, mask, n_clusters=3) # unaries = np.dstack((mems[0,...].reshape(-1, 1), mems[1,...].reshape(-1, 1), mems[2,...].reshape(-1, 1))) # unaries = (beta * 100 * unaries).astype(np.int32) # unaries, mask = add_heal_border_to_unaries(unaries, mask) # np.save('unaries.npy', unaries) # Viewer_3D(unaries[:,:,0].reshape(data.shape)).show() n_labels = unaries.shape[2] print 'ok' print 'calculating pairwise potentials ...', # self.status_bar.showMessage('Calculating pairwise potentials...') # create potts pairwise pairwise = -alpha * np.eye(n_labels, dtype=np.int32) print 'ok' print 'deriving graph edges ...', # self.status_bar.showMessage('Deriving graph edges...') # use the gerneral graph algorithm # first, we construct the grid graph inds = np.arange(data.size).reshape(data.shape) if data.ndim == 2: horz = np.c_[inds[:, :-1].ravel(), inds[:, 1:].ravel()] vert = np.c_[inds[:-1, :].ravel(), inds[1:, :].ravel()] edges = np.vstack([horz, vert]).astype(np.int32) elif data.ndim == 3: horz = np.c_[inds[:, :, :-1].ravel(), inds[:, :, 1:].ravel()] vert = np.c_[inds[:, :-1, :].ravel(), inds[:, 1:, :].ravel()] dept = np.c_[inds[:-1, :, :].ravel(), inds[1:, :, :].ravel()] edges = np.vstack([horz, vert, dept]).astype(np.int32) # deleting edges with nodes outside the mask nodes_in = np.ravel_multi_index(np.nonzero(mask), data.shape) rows_inds = np.in1d(edges, nodes_in).reshape(edges.shape).sum(axis=1) == 2 edges = edges[rows_inds, :] print 'ok' # plt.show() # un = unaries[:, :, 0].reshape(data_o.shape) # un = unaries[:, :, 1].reshape(data_o.shape) # un = unaries[:, :, 2].reshape(data_o.shape) # py3DSeedEditor.py3DSeedEditor(un).show() print 'calculating graph cut ...', # self.status_bar.showMessage('Calculating graph cut...') result_graph = pygco.cut_from_graph(edges, unaries.reshape(-1, n_labels), pairwise) labels = result_graph.reshape(data.shape) + 1 # +1 to shift the first class to label number 1 # np.save('labels.npy', result_graph.reshape(data.shape)) labels = np.where(mask, labels, params['bgd_label']) # mask = tools.eroding3D(mask, selem=skimor.disk(2), slicewise=True, sliceId=0) # labels *= mask # zooming to the original size if params['zoom']: data_o.labels = zoom_to_shape(labels, data_o.orig_shape) else: data_o.labels = np.round(tools.resize3D(labels, shape=data_o.orig_shape)).astype(np.int64) print 'ok' # self.status_bar.showMessage('Done') # debug visualization # self.viewer = Viewer_3D.Viewer_3D(self.res, range=True) # self.viewer.show() print 'extracting objects ...', # self.status_bar.showMessage('Extracting objects ...'), labels_tmp = np.where(data_o.labels == params['healthy_label'], params['bgd_label'], data_o.labels) # because we can set only one label as bgd data_o.objects = skimea.label(labels_tmp, background=params['bgd_label']) data_o.lesions = Lesion.extract_lesions(data_o.objects, data_o.data, params['voxels2ml_k']) # self.status_bar.showMessage('Done') print 'ok'
def obtain_graph_cuts_segmentation(structure_posterior_energy, \ not_structure_posterior_energy): """Obtains the graph cuts segmentation for a structure given the posterior energies. Parameters ---------- structure_posterior_energy: A float array with shape (L, M, N) representing the posterior energies for the structure of interest. (source) not_structure_posterior_energy : A float array with shape (L, M, N) representing the posterior energies for not being the structure of interest. (sink) ... Returns ------- label_map : array, shape (L, M, N) Segmented image with labels adhering to CIP conventions """ length = np.shape(structure_posterior_energy)[0] width = np.shape(structure_posterior_energy)[1] if (np.size(np.shape(structure_posterior_energy)[1]) == 3): num_slices = np.shape(structure_posterior_energy)[2] else: num_slices = 1 numNodes = length * width segmented_image = np.zeros((length, width, num_slices), dtype=np.int32) for slice_num in range(0, num_slices): print("graph cut slice" + str(slice_num)) print(np.shape(structure_posterior_energy)) source_slice_temp = structure_posterior_energy[:, :].squeeze().astype( np.int32) # mode='c' sink_slice_temp = not_structure_posterior_energy[:, :].squeeze( ).astype(np.int32) m_shape = np.shape(source_slice_temp) #source_slice = np.memmap(source_slice_temp, dtype='int32', mode='c', shape=(m_shape[0],m_shape[1])) #sink_slice = np.memmap(sink_slice_temp, dtype='int32', mode='c', shape=(m_shape[0],m_shape[1])) source_slice = np.reshape(source_slice_temp, np.shape(source_slice_temp), order='C') sink_slice = np.reshape(sink_slice_temp, np.shape(sink_slice_temp), order='C') #source_slice = structure_posterior_energy[:,:].squeeze().astype(np.int32) # mode='c' #sink_slice = not_structure_posterior_energy[:,:].squeeze().astype(np.int32) #source_slice = structure_posterior_energy[:,:,slice_num: \ # (slice_num+1)].squeeze().astype(np.int32) #sink_slice = not_structure_posterior_energy[:,:,slice_num: \ # (slice_num+1)].squeeze().astype(np.int32) imageIndexArray = np.arange(numNodes).reshape(np.shape( \ source_slice)[0], np.shape(source_slice)[1]) #Adding neighbourhood terms inds = np.arange(imageIndexArray.size).reshape(imageIndexArray.shape) #goes from [[0,1,...numcols-1],[numcols, ...],..[.., num_elem-1]] horz = np.c_[inds[:, :-1].ravel(), inds[:, 1:].ravel()] #all rows, not last col make to 1d vert = np.c_[inds[:-1, :].ravel(), inds[1:, :].ravel()] #all rows, not first col, make to 1d edges = np.vstack([horz, vert]).astype(np.int32) #horz is first element, vert is theweights = np.ones( (np.shape(edges))).astype(np.int32) * 30 #*50#*150 ##*180 edges = np.hstack((edges, theweights))[:, 0:3].astype(np.int32) #stack the weight value hor next to edge indeces ## #3rd order neighbours, good for lung horz = np.c_[inds[:, :-2].ravel(), inds[:, 2:].ravel()] #all rows, not last col make to 1d vert = np.c_[inds[:-2, :].ravel(), inds[2:, :].ravel()] #all rows, not first col, make to 1d edges2 = np.vstack([horz, vert]).astype(np.int32) #horz is first element, vert is theweights2 = np.ones((np.shape(edges2))).astype(np.int32) * 5 #*30 edges2 = np.hstack((edges2, theweights2))[:, 0:3].astype(np.int32) edges_temp = np.vstack([edges, edges2]).astype(np.int32) edges = np.reshape(edges_temp, np.shape(edges_temp), order='C') pairwise_cost = np.array([[0, 125], [125, 0]], dtype=np.int32, order='C') energies_temp = np.dstack((np.array(source_slice).astype(np.int32).flatten(), \ np.array(sink_slice).astype(np.int32).flatten())).squeeze() energies = np.ascontiguousarray( np.reshape(energies_temp, np.shape(energies_temp), order='C')) segmented_slice = cut_from_graph(edges, energies, pairwise_cost, 3, \ 'expansion') segmented_image[:, :, slice_num] = segmented_slice.reshape(length, width) return segmented_image
def segment_edge_cut(self): # noinspection PyUnresolvedReferences from pygco import cut_from_graph height = self.image.shape[0] width = self.image.shape[1] # first, we construct the grid graph # inds is a matrix of cell indices inds = np.arange(height * width).reshape(height, width) # list of all horizontal and vertical edges horizontal_edges = np.c_[inds[:, :-1].ravel(), inds[:, 1:].ravel()] vertical_edges = np.c_[inds[:-1, :].ravel(), inds[1:, :].ravel()] # concatenate both lists edges = np.vstack([horizontal_edges, vertical_edges]).astype(np.int32) # the edge weight multiplies the logarithm of the probability, this is the same as potentiating the probability # and renormalizing def effective_probability(probability, weight): return probability**weight / (probability**weight + (1 - probability)**weight) depth = self.feature_images['depth'].reshape(-1) depth[depth == -1] = np.nan self.edge_depth_diff = np.abs(depth[edges[:, 0]] - depth[edges[:, 1]]) weights = np.ones([edges.shape[0], 1]) # weight is 1 for nan depth_diff_thres = 0.02 # in m # replace nans with threshold to prevent comparing to nan warnings self.edge_depth_diff[np.isnan(self.edge_depth_diff)] = depth_diff_thres smooth_depth_edges = self.edge_depth_diff < depth_diff_thres sharp_depth_edges = self.edge_depth_diff > depth_diff_thres weights[ smooth_depth_edges] = 2 # effective for 0.95 + weight 2 -> 0.9972375 weights[sharp_depth_edges] = 0 # add this for displaying the depth edges self.depth_edge_image = np.zeros(height * width) self.depth_edge_image[edges[smooth_depth_edges].reshape(-1)] = -1 self.depth_edge_image[edges[sharp_depth_edges].reshape(-1)] = 1 self.depth_edge_image = self.depth_edge_image.reshape(height, width) edges = np.hstack([edges, weights]) # compute potentials (log of probabilities) unaries = -np.log( np.array([ np.clip(self.posterior_images[o], a_min=0.01, a_max=1.0) for o in self.candidate_objects ])).transpose((1, 2, 0)) num_labels = unaries.shape[2] p_same_label = 0.95 pairwise = -np.log(1 - p_same_label) * ( 1 - np.eye(num_labels)) - np.log(p_same_label) * np.eye(num_labels) k = 10 # scaling factor for potentials to reduce aliasing because the potentials need to be converted to integers unaries_c = np.copy((k * unaries).astype('int32'), order='C').reshape(-1, num_labels) pairwise_c = np.copy((k * pairwise).astype('int32'), order='C') edges_c = edges.astype('int32') self.segmentation = cut_from_graph(edges_c, unaries_c, pairwise_c).reshape(height, width)
else: beta = 1 + np.linalg.norm( np.dot(normals[i_node, 0:3], normals[i_nei, 0:3])) edges = np.concatenate( (edges, np.array([ i_node, i_nei, -beta * math.log10(theta / np.pi) * phi ]).reshape(1, 3)), axis=0) edges = np.delete(edges, 0, 0) edges[:, 2] *= lambda_c * round_factor edges = edges.astype(np.int32) refine_labels = cut_from_graph(edges, unaries, pairwise) refine_labels = refine_labels.reshape([-1, 1]) # output refined result mesh2 = Easy_Mesh() mesh2.cells = mesh_d.cells mesh2.update_cell_ids_and_points() mesh2.cell_attributes['Label'] = refine_labels mesh2.to_vtp( os.path.join( output_path, '{}_d_predicted_refined_pygco.vtp'.format(i_sample[:-4]))) # upsampling print('\tUpsampling...') if mesh.cells.shape[0] > 100000:
def run(self, resize=True): #---- rescaling ---- if resize and self.scale != 0: self.img = tools.resize3D(self.img_orig, self.scale, sliceId=0) self.seeds = tools.resize3D(self.seeds_orig, self.scale, sliceId=0) self.mask = tools.resize3D(self.mask_orig, self.scale, sliceId=0) # for i, (im, seeds, mask) in enumerate(zip(self.img_orig, self.seeds_orig, self.mask_orig)): # self.img[i, :, :] = cv2.resize(im, (0,0), fx=self.scale, fy=self.scale, interpolation=cv2.INTER_NEAREST) # self.seeds[i, :, :] = cv2.resize(seeds, (0,0), fx=self.scale, fy=self.scale, interpolation=cv2.INTER_NEAREST) # self.mask[i, :, :] = cv2.resize(mask, (0,0), fx=self.scale, fy=self.scale, interpolation=cv2.INTER_NEAREST) # else: # self.img = self.img_orig # self.seeds = self.seeds_orig self.n_slices, self.n_rows, self.n_cols = self.img.shape #---- calculating intensity models ---- # if self.unaries is None: if self.models is None: self._debug('calculating intensity models ...', False) # self.models = self.calc_intensity_models() self.models = self.calc_models() self._debug('done', True) #---- creating unaries ---- if self.unaries is None: self._debug('calculating unary potentials ...', False) self.unaries = self.beta * self.get_unaries() self._debug('done', True) #---- create potts pairwise ---- if self.pairwise is None: self._debug('calculating pairwise potentials ...', False) # self.pairwise = - self.alpha * np.eye(self.n_objects, dtype=np.int32) self.set_pairwise() self._debug('done', True) #---- deriving graph edges ---- self._debug('deriving graph edges ...', False) # use the gerneral graph algorithm # first, we construct the grid graph # inds = np.arange(self.n_rows * self.n_cols).reshape(self.img.shape) # horz = np.c_[inds[:, :-1].ravel(), inds[:, 1:].ravel()] # vert = np.c_[inds[:-1, :].ravel(), inds[1:, :].ravel()] # self.edges = np.vstack([horz, vert]).astype(np.int32) inds = np.arange(self.img.size).reshape(self.img.shape) if self.img.ndim == 2: horz = np.c_[inds[:, :-1].ravel(), inds[:, 1:].ravel()] vert = np.c_[inds[:-1, :].ravel(), inds[1:, :].ravel()] self.edges = np.vstack([horz, vert]).astype(np.int32) elif self.img.ndim == 3: horz = np.c_[inds[:, :, :-1].ravel(), inds[:, :, 1:].ravel()] vert = np.c_[inds[:, :-1, :].ravel(), inds[:, 1:, :].ravel()] dept = np.c_[inds[:-1, :, :].ravel(), inds[1:, :, :].ravel()] self.edges = np.vstack([horz, vert, dept]).astype(np.int32) # deleting edges with nodes outside the mask nodes_in = np.ravel_multi_index(np.nonzero(self.mask), self.img.shape) rows_inds = np.in1d(self.edges, nodes_in).reshape( self.edges.shape).sum(axis=1) == 2 self.edges = self.edges[rows_inds, :] self._debug('done', True) #---- calculating graph cut ---- self._debug('calculating graph cut ...', False) # we flatten the unaries result_graph = pygco.cut_from_graph( self.edges, self.unaries.reshape(-1, self.n_objects), self.pairwise) self.labels = result_graph.reshape(self.img.shape) self._debug('done', True) #---- zooming to the original size ---- if resize and self.scale != 0: # self.labels_orig = cv2.resize(self.labels, (0,0), fx=1. / self.scale, fy= 1. / self.scale, interpolation=cv2.INTER_NEAREST) self.labels_orig = tools.resize3D(self.labels, 1. / self.scale, sliceId=0) else: self.labels_orig = self.labels self._debug('----------', True) self._debug('segmentation done', True) # self.show_slice(0) # plt.figure() # plt.subplot(221), plt.imshow(self.img_orig[0, :, :], 'gray', interpolation='nearest'), plt.title('input image') # plt.subplot(222), plt.imshow(self.seeds_orig[0, :, :], interpolation='nearest') # # plt.hold(True) # # seeds_v = np.nonzero(self.seeds) # # for i in range(len(seeds_v[0])): # # seed = (seeds_v[0][i], seeds_v[1][i]) # # if self.seeds[seed] # # # # plt.plot # plt.title('seeds') # plt.subplot(223), plt.imshow(self.labels, interpolation='nearest'), plt.title('segmentation') # plt.subplot(224), plt.imshow(skiseg.mark_boundaries(self.img_orig, self.labels), interpolation='nearest'), plt.title('segmentation') # plt.show() return self.labels_orig
def run(self): # slice_idx = self.params['slice_idx'] alpha = self.params['alpha'] beta = self.params['beta'] hypo_lab = self.params['hypo_label'] hyper_lab = self.params['hyper_label'] # if not fname: # _, self.data, self.mask = self.load_data(slice_idx) # else: # self.data, self.mask, self.voxel_size = self.load_pickle_data(self.fname, self.params, slice_idx) # self.data = self.data.astype(np.uint8) # TumorVisualiser.run(data, mask, params['healthy_label'], params['hypo_label'], params['hyper_label'], slice_axis=0, disp_smoothed=True) # print 'estimating number of clusters ...', # print '\tcurrently switched off' # d = scindiint.zoom(data_o, 0.5) # m = skitra.resize(mask, np.array(mask.shape) * 0.5).astype(np.bool) # ints = d[np.nonzero(m)] # ints = ints.reshape((ints.shape[0], 1)) # for i in range(2, 5): # kmeans_model = KMeans(n_clusters=i, n_init=1).fit(ints) # labels = kmeans_model.labels_ # # sc = metrics.silhouette_score(ints, labels, metric='euclidean') # print '\tn_clusters = %i, score = %1.3f (best score=1, worse score=-1)' % (i, sc) # data_o = cv2.imread('/home/tomas/Dropbox/images/medicine/hypodense_bad2.png', 0).astype(np.float) # data_s = skifil.gaussian_filter(data_o, sigma) # # #imd = np.absolute(im - ims) # data_d = data_o - data_s # # data_d = np.where(data_d < 0, 0, data_d) # zooming the data print 'rescaling data ...', if self.params['zoom']: self.actual_data.data = self.data_zoom(self.actual_data.data, self.actual_data.voxel_size, self.params['working_voxel_size_mm']) self.actual_data.mask = self.data_zoom(self.actual_data.mask, self.actual_data.voxel_size, self.params['working_voxel_size_mm']) else: data = tools.resize3D(self.actual_data.data, self.params['scale'], sliceId=0) mask = tools.resize3D(self.actual_data.mask, self.params['scale'], sliceId=0) print 'ok' # data = data.astype(np.uint8) # calculating intensity models if necesarry print 'estimating color models ...' if not self.models: self.models = self.calculate_intensity_models(data, mask) print 'ok' else: print 'already done' print 'calculating unary potentials ...', self.status_bar.showMessage('Calculating unary potentials...') # create unaries # unaries = data_d # # as we convert to int, we need to multipy to get sensible values # unaries = (1 * np.dstack([unaries, -unaries]).copy("C")).astype(np.int32) self.unaries = beta * self.get_unaries(data, mask, self.models, self.params) n_labels = self.unaries.shape[2] print 'ok' print 'calculating pairwise potentials ...', self.status_bar.showMessage('Calculating pairwise potentials...') # create potts pairwise self.pairwise = -alpha * np.eye(n_labels, dtype=np.int32) print 'ok' print 'deriving graph edges ...', self.status_bar.showMessage('Deriving graph edges...') # use the gerneral graph algorithm # first, we construct the grid graph inds = np.arange(data.size).reshape(data.shape) if data.ndim == 2: horz = np.c_[inds[:, :-1].ravel(), inds[:, 1:].ravel()] vert = np.c_[inds[:-1, :].ravel(), inds[1:, :].ravel()] self.edges = np.vstack([horz, vert]).astype(np.int32) elif data.ndim == 3: # horz = np.c_[inds[:, :-1].ravel(), inds[:, 1:].ravel()] # vert = np.c_[inds[:-1, :].ravel(), inds[1:, :].ravel()] horz = np.c_[inds[:, :, :-1].ravel(), inds[:, :, 1:].ravel()] vert = np.c_[inds[:, :-1, :].ravel(), inds[:, 1:, :].ravel()] dept = np.c_[inds[:-1, :, :].ravel(), inds[1:, :, :].ravel()] self.edges = np.vstack([horz, vert, dept]).astype(np.int32) # deleting edges with nodes outside the mask nodes_in = np.ravel_multi_index(np.nonzero(mask), data.shape) rows_inds = np.in1d(self.edges, nodes_in).reshape(self.edges.shape).sum(axis=1) == 2 self.edges = self.edges[rows_inds, :] print 'ok' # plt.show() # un = unaries[:, :, 0].reshape(data_o.shape) # un = unaries[:, :, 1].reshape(data_o.shape) # un = unaries[:, :, 2].reshape(data_o.shape) # py3DSeedEditor.py3DSeedEditor(un).show() print 'calculating graph cut ...', self.status_bar.showMessage('Calculating graph cut...') # we flatten the unaries # result_graph = pygco.cut_from_graph(edges, unaries.reshape(-1, 2), pairwise) # print 'tu: ', unaries.reshape(-1, n_labels).shape result_graph = pygco.cut_from_graph(self.edges, self.unaries.reshape(-1, n_labels), self.pairwise) labels = result_graph.reshape(data.shape) + 1 # +1 to shift the first class to label number 1 labels = np.where(mask, labels, self.params['bgd_label']) # zooming to the original size if self.params['zoom']: self.actual_data.labels = self.zoom_to_shape(labels, self.actual_data.orig_shape) else: # self.actual_data.labels = tools.resize3D(labels, scale=1. / self.params['scale'], sliceId=0) # self.actual_data.labels2 = skitra.resize(labels, self.actual_data.orig_shape, mode='nearest', preserve_range=True).astype(np.int64) self.actual_data.labels = tools.resize3D(labels, shape=self.actual_data.orig_shape, sliceId=0)#.astype(np.int64) print 'ok' self.status_bar.showMessage('Done') # debug visualization # self.viewer = Viewer_3D.Viewer_3D(self.res, range=True) # self.viewer.show() print 'extracting objects ...', self.status_bar.showMessage('Extracting objects ...'), labels_tmp = np.where(self.actual_data.labels == self.params['healthy_label'], self.params['bgd_label'], self.actual_data.labels) # because we can set only one label as bgd self.actual_data.objects = skimea.label(labels_tmp, background=self.params['bgd_label']) self.actual_data.lesions = Lesion.extract_lesions(self.actual_data.objects, self.actual_data.data) # areas = [x.area for x in self.actual_data.lesions] self.status_bar.showMessage('Done') print 'ok' print 'initial filtration ...', self.objects_filtration(area=(self.params['min_area'], self.params['max_area']), density=(self.params['min_density'], self.params['max_density']), compactness=self.params['min_compactness']) print 'ok' self.status_bar.showMessage('Done')
def obtain_graph_cuts_segmentation(structure_posterior_energy, \ not_structure_posterior_energy): """Obtains the graph cuts segmentation for a structure given the posterior energies. Parameters ---------- structure_posterior_energy: A float array with shape (L, M, N) representing the posterior energies for the structure of interest. (source) not_structure_posterior_energy : A float array with shape (L, M, N) representing the posterior energies for not being the structure of interest. (sink) ... Returns ------- label_map : array, shape (L, M, N) Segmented image with labels adhering to CIP conventions """ length = np.shape(structure_posterior_energy)[0]; width = np.shape(structure_posterior_energy)[1]; if (np.size(np.shape(structure_posterior_energy)[1]) == 3): num_slices = np.shape(structure_posterior_energy)[2]; else: num_slices = 1 numNodes = length * width segmented_image = np.zeros((length, width, num_slices), dtype = np.int32) for slice_num in range(0, num_slices): print("graph cut slice" +str(slice_num)) print(np.shape(structure_posterior_energy)) source_slice_temp = structure_posterior_energy[:,:].squeeze().astype(np.int32) # mode='c' sink_slice_temp = not_structure_posterior_energy[:,:].squeeze().astype(np.int32) m_shape = np.shape(source_slice_temp) #source_slice = np.memmap(source_slice_temp, dtype='int32', mode='c', shape=(m_shape[0],m_shape[1])) #sink_slice = np.memmap(sink_slice_temp, dtype='int32', mode='c', shape=(m_shape[0],m_shape[1])) source_slice = np.reshape(source_slice_temp, np.shape(source_slice_temp), order = 'C') sink_slice = np.reshape(sink_slice_temp, np.shape(sink_slice_temp),order = 'C') #source_slice = structure_posterior_energy[:,:].squeeze().astype(np.int32) # mode='c' #sink_slice = not_structure_posterior_energy[:,:].squeeze().astype(np.int32) #source_slice = structure_posterior_energy[:,:,slice_num: \ # (slice_num+1)].squeeze().astype(np.int32) #sink_slice = not_structure_posterior_energy[:,:,slice_num: \ # (slice_num+1)].squeeze().astype(np.int32) imageIndexArray = np.arange(numNodes).reshape(np.shape( \ source_slice)[0], np.shape(source_slice)[1]) #Adding neighbourhood terms inds = np.arange(imageIndexArray.size).reshape(imageIndexArray.shape) #goes from [[0,1,...numcols-1],[numcols, ...],..[.., num_elem-1]] horz = np.c_[inds[:, :-1].ravel(), inds[:, 1:].ravel()] #all rows, not last col make to 1d vert = np.c_[inds[:-1, :].ravel(), inds[1:, :].ravel()] #all rows, not first col, make to 1d edges = np.vstack([horz, vert]).astype(np.int32) #horz is first element, vert is theweights = np.ones((np.shape(edges))).astype(np.int32)*30#*50#*150 ##*180 edges = np.hstack((edges,theweights))[:,0:3].astype(np.int32) #stack the weight value hor next to edge indeces ## #3rd order neighbours, good for lung horz = np.c_[inds[:, :-2].ravel(), inds[:,2:].ravel()] #all rows, not last col make to 1d vert = np.c_[inds[:-2, :].ravel(), inds[2:, :].ravel()] #all rows, not first col, make to 1d edges2 = np.vstack([horz, vert]).astype(np.int32) #horz is first element, vert is theweights2 = np.ones((np.shape(edges2))).astype(np.int32)*5#*30 edges2 = np.hstack((edges2,theweights2))[:,0:3].astype(np.int32) edges_temp = np.vstack([edges,edges2]).astype(np.int32) edges = np.reshape(edges_temp, np.shape(edges_temp), order = 'C') pairwise_cost = np.array([[0, 125], [125, 0]], dtype = np.int32, order = 'C') energies_temp = np.dstack((np.array(source_slice).astype(np.int32).flatten(), \ np.array(sink_slice).astype(np.int32).flatten())).squeeze() energies = np.ascontiguousarray(np.reshape(energies_temp, np.shape(energies_temp), order = 'C')) segmented_slice = cut_from_graph(edges, energies, pairwise_cost, 3, \ 'expansion') segmented_image[:,:,slice_num] = segmented_slice.reshape(length,width) return segmented_image
def set_data(self, data, voxels1, voxels2, seeds=False, hard_constraints=True, area_weight=1): """ Setting of data. You need set seeds if you want use hard_constraints. """ # from PyQt4.QtCore import pyqtRemoveInputHook # pyqtRemoveInputHook() # import pdb; pdb.set_trace() # BREAKPOINT unariesalt = self.__create_tlinks(data, voxels1, voxels2, seeds, area_weight, hard_constraints) # některém testu organ semgmentation dosahují unaries -15. což je podiné # stačí vyhodit print před if a je to vidět logger.debug("unaries %.3g , %.3g" % ( np.max(unariesalt), np.min(unariesalt))) # create potts pairwise # pairwiseAlpha = -10 pairwise = -(np.eye(2) - 1) pairwise = (self.segparams['pairwise_alpha'] * pairwise ).astype(np.int32) # pairwise = np.array([[0,30],[30,0]]).astype(np.int32) # print pairwise self.iparams = {} if self.segparams['use_boundary_penalties']: sigma = self.segparams['boundary_penalties_sigma'] # set boundary penalties function # Default are penalties based on intensity differences boundary_penalties_fcn = lambda ax: \ self.boundary_penalties_array(axis=ax, sigma=sigma) else: boundary_penalties_fcn = None nlinks = self.__create_nlinks(data, boundary_penalties_fcn=boundary_penalties_fcn) # print 'data shape ', data.shape # print 'nlinks sh ', nlinks.shape # print 'tlinks sh ', unariesalt.shape # edges - seznam indexu hran, kteres spolu sousedi # we flatten the unaries # result_graph = cut_from_graph(nlinks, unaries.reshape(-1, 2), # pairwise) result_graph = pygco.cut_from_graph( nlinks, unariesalt.reshape(-1, 2), pairwise ) # probably not necessary # del nlinks # del unariesalt # print "unaries %.3g , %.3g" % (np.max(unariesalt), # np.min(unariesalt)) result_labeling = result_graph.reshape(data.shape) return result_labeling
def propagationSegment(lastSegmentImageAddress, nextOriginalImageAddress, nextSegmentAddress, algorithm="ffc", boundingLength=18, infiniteCost=100, KCost=3): """ the main function of propagation segmentation :param lastSegmentImageAddress: The address of the segment result of last image :param nextOriginalImageAddress: The address of the original image to be segmented in this layer :param nextSegmentAddress: The storage address of segmentation results :param algorithm: Algorithm category Fast-FineCut -- "ffc" Waggoner -- "wag" :param boundingLength: the length of bounding region, default 18 :param infiniteCost: Default 100, refers to infinity :param KCost: K value of binary term, default 3 :return: Return the segmentation result """ # read the image tempLastSegment = cv.imread(lastSegmentImageAddress) if tempLastSegment is None: return "The last image's path is wrong" tempNextOriginal = cv.imread(nextOriginalImageAddress) if tempNextOriginal is None: return "The path of this layer's image is wrong" # Gets the number of horizontal and vertical coordinates of the image rowNumber = tempLastSegment.shape[0] colNumber = tempLastSegment.shape[1] # Convert the last image to a grayscale image if it is a color image lastSegment = np.zeros((rowNumber, colNumber)) if tempLastSegment.ndim == 3: lastSegment = cv.cvtColor(tempLastSegment, cv.COLOR_BGR2GRAY) elif tempLastSegment.ndim == 2: lastSegment = tempLastSegment # Convert this layered image to a grayscale image if it is a color image nextOriginal = np.zeros((rowNumber, colNumber)) if tempNextOriginal.ndim == 3: nextOriginal = cv.cvtColor(tempNextOriginal, cv.COLOR_BGR2GRAY) elif tempNextOriginal.ndim == 2: nextOriginal = tempNextOriginal if nextOriginal.shape != lastSegment.shape: return "Error! The image of the previous layer and the image of the layer is different in dimension." # Label the last image uniqueNum = np.unique(lastSegment) lastNumber = 0 lastLabeled = np.zeros((rowNumber, colNumber)) if len(uniqueNum) == 2: # Binary image (lastLabeled, lastNumber) = label(lastSegment, background=255, neighbors=4, return_num=True) lastLabeled = reviseLabel(lastLabeled) elif len(uniqueNum) > 2: (lastLabeled, lastNumber) = label(lastSegment, neighbors=4, return_num=True) lastLabeled = lastLabeled.astype(np.int32) # Calculate the unary item unaryCostMatrix and bounding region unaryCostMatrix, boundingRegion = getUnaryCost( lastLabeled, lastSegment, return_boundingRegion=True, morphKernelNum=boundingLength, infiniteCost=infiniteCost) # Calculate the edgeImage required for the binary item blurredGaussian = cv.GaussianBlur(nextOriginal, (3, 3), 0) imgThreshMean = cv.adaptiveThreshold(blurredGaussian, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY_INV, 5, 4) imgThreshMean = denoiseByArea(imgThreshMean, 300, neighbors=8) tempNextEdge = morphology.skeletonize(imgThreshMean / 255) * 255 if algorithm == "ffc": # Fast-FineCut's binary term, use edgeImage binaryCostMatrix = getBinaryCostFromUnary( nextOriginal, lastSegment, lastLabeled, lastNumber, unaryCostMatrix, type="edgeImage", edgeOriginalImage=tempNextEdge, infiniteCost=infiniteCost, KCost=KCost) elif algorithm == "wag": # waggoner's binary term binaryCostMatrix = getBinaryCostByWaggoner( nextOriginal, lastSegment, lastLabeled, type="edgeImage", edgeOriginalImage=tempNextEdge, infiniteCost=infiniteCost) # calculate pairWiseMatrix pairWiseMatrix = getPairWiseMatrix(lastSegment, lastLabeled) # Graph-cut result_graph = cut_from_graph(binaryCostMatrix, unaryCostMatrix.reshape(-1, lastNumber), pairWiseMatrix, algorithm="swap") nextLabeled = result_graph.reshape(nextOriginal.shape) nextSegment = getEdgesFromLabel(nextLabeled) # Show the intermediate results # plt.subplot(231),plt.imshow(tempNextEdge,cmap="gray"),plt.title("nextEdges") # plt.subplot(232),plt.imshow(np.uint8(boundingRegion)),plt.title("boundingRegion") # #plt.subplot(232),plt.imshow(tempNextEdge,cmap="gray"),plt.title("nextEdges") # # plt.subplot(333),plt.imshow(unaryCost),plt.title("unaryCost") # plt.subplot(233),plt.imshow(addComparation(nextOriginal, binaryCostMatrix)),plt.title("binaryCostMatrix") # #plt.subplot(234),plt.imshow(ragShow),plt.title("rag") # plt.subplot(234),plt.imshow(nextOriginal,cmap="gray"),plt.title("Original") # plt.subplot(235),plt.imshow(nextLabeled),plt.title("nextLabeled") # plt.subplot(236),plt.imshow(nextSegment,cmap="gray"),plt.title("result") # plt.show() # Export image try: cv.imwrite(nextSegmentAddress, nextSegment) except (cv.error, Exception): return "Picture is saved incorrectly" return nextSegment