def graphcut_multi(unary1, unary2, pw_x, pw_y, alpha, beta, eta, n_labels=2): '''alpha-beta swap algorithm''' block_num = unary1.shape[0] large_val = 1000 * block_num ** 2 if n_labels == 2: prior= eta * np.array([-np.log(alpha + 1e-8), -np.log(1 - alpha + 1e-8)]) / block_num ** 2 elif n_labels == 3: prior= eta * np.array([-np.log(alpha**2 + 1e-8), -np.log(2 * alpha * (1-alpha) + 1e-8), -np.log((1 - alpha)**2 + 1e-8)]) / block_num ** 2 elif n_labels == 4: prior= eta * np.array([-np.log(alpha**3 + 1e-8), -np.log(3 * alpha **2 * (1-alpha) + 1e-8), -np.log(3 * alpha * (1-alpha) **2 + 1e-8), -np.log((1 - alpha)**3 + 1e-8)]) / block_num ** 2 unary_cost = (large_val * np.stack([(1-lam) * unary1 + lam * unary2 + prior[i] for i, lam in enumerate(np.linspace(0,1, n_labels))], axis=-1)).astype(np.int32) pairwise_cost = np.zeros(shape=[n_labels, n_labels], dtype=np.float32) for i in range(n_labels): for j in range(n_labels): pairwise_cost[i, j] = (i-j)**2 / (n_labels-1)**2 pw_x = (large_val * (pw_x + beta)).astype(np.int32) pw_y = (large_val * (pw_y + beta)).astype(np.int32) labels = 1.0 - gco.cut_grid_graph(unary_cost, pairwise_cost, pw_x, pw_y, algorithm='swap')/(n_labels-1) mask = labels.reshape(block_num, block_num) return mask
def splitlabel(lmap, mask, prev, slbls, ucost0, ewts, opt): """Split a new connected component that overlaps multiple components""" _ys, _xs = np.where(mask) _y1, _y2, _x1, _x2 = np.amin(_ys), np.amax(_ys), np.amin(_xs), np.amax(_xs) prev = prev[_y1:(_y2 + 1), _x1:(_x2 + 1)] ucost0 = ucost0[_y1:(_y2 + 1), _x1:(_x2 + 1)] ucost = np.zeros(np.shape(ucost0) + (len(slbls) + 1, ), np.int32) ucost[:, :, 0] = ucost0 ewts = [ ewts[0][_y1:_y2, _x1:(_x2 + 1)], ewts[1][_y1:(_y2 + 1), _x1:_x2], ewts[2][_y1:_y2, _x1:_x2], ewts[3][_y1:_y2, _x1:_x2] ] ucost[prev > 0, :] = ucost[prev > 0, :] + opt.zwt for i, lbl in enumerate(slbls): ucost[prev == lbl, i + 1] = 0 pwcost = 1 - np.eye(len(slbls) + 1, dtype=np.int32) mcut0 = gco.cut_grid_graph(ucost, pwcost, *ewts).reshape(ucost0.shape) mcut = np.zeros_like(lmap) mcut[_y1:(_y2 + 1), _x1:(_x2 + 1)] = mcut0 for i, lbl in enumerate(slbls): lmap[np.logical_and(mask, mcut == (i + 1))] = lbl
def graphcut_multi(cost, beta=1, algorithm='swap', n_label=0, add_idx=None): height, width, n_input = cost.shape unary = np.ascontiguousarray(cost) if add_idx is not None: add_idx = add_idx.astype(np.bool) pairwise = (np.ones(shape=(n_input, n_input), dtype=np.float32) - np.eye(n_input, dtype=np.float32)) if n_label == 2: pairwise[-1, :-1][add_idx] = 0.25 pairwise[:-1, -1][add_idx] = 0.25 elif n_label == 3: pairwise[-3:, :-3][:, add_idx] = np.array([[0.25, 0.25, 1], [0.25, 1, 0.25], [1, 0.25, 0.25]]) pairwise[:-3, -3:][add_idx, :] = np.array([[0.25, 0.25, 1], [0.25, 1, 0.25], [1, 0.25, 0.25]]) cost_v = beta * np.ones(shape=[height - 1, width], dtype=np.float32) cost_h = beta * np.ones(shape=[height, width - 1], dtype=np.float32) mask_idx = gco.cut_grid_graph(unary, pairwise, cost_v, cost_h, algorithm='swap') return mask_idx
def graphcut_multi_float(unary1, unary2, pw_x, pw_y, alpha, beta, eta, n_labels=2, label_cost='l2', beta_c=0.0): block_num = unary1.shape[-1] if n_labels == 2: prior = eta * np.array( [-np.log(alpha + 1e-8), -np.log(1 - alpha + 1e-8)]) / block_num**2 elif n_labels == 3: prior = eta * np.array([ -np.log(alpha**2 + 1e-8), -np.log(2 * alpha * (1 - alpha) + 1e-8), -np.log((1 - alpha)**2 + 1e-8) ]) / block_num**2 elif n_labels == 4: prior = eta * np.array([ -np.log(alpha**3 + 1e-8), -np.log(3 * alpha**2 * (1 - alpha) + 1e-8), -np.log(3 * alpha * (1 - alpha)**2 + 1e-8), -np.log((1 - alpha)**3 + 1e-8) ]) / block_num**2 unary_cost = np.stack( [(1 - lam) * unary1 + lam * unary2 + prior[i] for i, lam in enumerate(np.linspace(0, 1, n_labels))], axis=-1) pairwise_cost = np.zeros(shape=[n_labels, n_labels], dtype=np.float32) for i in range(n_labels): for j in range(n_labels): if label_cost == 'l1': pairwise_cost[i, j] = abs(i - j) / (n_labels - 1) elif label_cost == 'l2': pairwise_cost[i, j] = (i - j)**2 / (n_labels - 1)**2 elif laabel_cost == 'l4': pairwise_cost[i, j] = (i - j)**4 / (n_labels - 1)**4 else: raise AssertionError( "label cost should be one of ['l1', 'l2', 'l4']") pw_x = pw_x + beta pw_y = pw_y + beta labels = 1.0 - gco.cut_grid_graph( unary_cost, pairwise_cost, pw_x, pw_y, algorithm='swap') / (n_labels - 1) mask = labels.reshape(block_num, block_num) return mask
def label(img, prev, opt=_PLOPT): """Label all plants in an image, using previous labels as guide.""" # Do a binary segmentation first ucost = np.zeros([img.shape[0], img.shape[1], 2], np.int32) ucost0 = ((unary(img, opt) - 0.5) * opt.uwt).astype(np.int32) ucost[:, :, 0] = ucost0 pwcost = 1 - np.eye(2, dtype=np.int32) if prev is not None: ucost[prev > 0, 0] = ucost[prev > 0, 0] + opt.zwt ewts = pairwise(img, opt) ewts = [(f * opt.ewt).astype(np.int32) for f in ewts] binary = gco.cut_grid_graph(ucost, pwcost, *ewts).reshape(img.shape[:2]) # Then label individual plants plants = separateconnect(binary, prev, ucost0, ewts, opt) return plants
def graphcut_multi(unary1, unary2, pw_x, pw_y, beta, n_labels=2): block_num = unary1.shape[0] alpha = 1000 * block_num**2 unary_cost = np.stack([(1 - i) * alpha * unary1 + i * alpha * unary2 for i in np.linspace(0, 1, n_labels)], axis=-1).astype(np.int32) pairwise_cost = np.zeros(shape=[n_labels, n_labels], dtype=np.float32) for i in range(n_labels): for j in range(n_labels): pairwise_cost[i, j] = (1 - i / 2) * j / 2 + i / 2 * (1 - j / 2) pw_x = (alpha * (pw_x + beta)).astype(np.int32) pw_y = (alpha * (pw_y + beta)).astype(np.int32) labels = 1.0 - gco.cut_grid_graph( unary_cost, pairwise_cost, pw_x, pw_y, algorithm='swap') / (n_labels - 1) mask = labels.reshape(block_num, block_num) return mask
def graphcut_multi(cost, beta=1, algorithm='swap', n_label=0, add_idx=None): '''find optimal labeling using Graph-Cut algorithm''' s = time.time() height, width, n_input = cost.shape unary = np.ascontiguousarray(cost) pairwise = (np.ones(shape=(n_input,n_input), dtype=np.float32) - np.eye(n_input, dtype=np.float32)) if n_label == 2: pairwise[-1, :-1][add_idx] = 0.25 pairwise[:-1, -1][add_idx] = 0.25 elif n_label == 3: pairwise[-3:, :-3][:, add_idx] = np.array([[0.25, 0.25, 1], [0.25, 1, 0.25], [1, 0.25, 0.25]]) pairwise[:-3, -3:][add_idx, :] = np.array([[0.25, 0.25, 1], [0.25, 1, 0.25], [1, 0.25, 0.25]]) cost_v = beta * np.ones(shape=[height-1, width], dtype=np.float32) cost_h = beta * np.ones(shape=[height, width-1], dtype=np.float32) #print("forward- mixup- mask_onehot- gc_pre: {:.4f}".format(time.time()-s)) s = time.time() mask_idx = gco.cut_grid_graph(unary, pairwise, cost_v, cost_h, algorithm=algorithm) #print("forward- mixup- mask_onehot- gc_solve: {:.4f}".format(time.time()-s)) return mask_idx
def joincc(lmap, prev, ucost0, ewts, opt): """Create joins to ensure each plant is one connected component.""" pwcost = 1 - np.eye(2, dtype=np.int32) for lbl in range(1, np.amax(lmap) + 1): ncc = ndi.label(lmap == lbl)[1] if ncc <= 1: continue # Crop out portions just including that component _y, _x = np.where(lmap == lbl) _y1, _y2 = np.amin(_y), np.amax(_y) + 1 _x1, _x2 = np.amin(_x), np.amax(_x) + 1 lmxy = lmap[_y1:_y2, _x1:_x2] uc0 = (ucost0[_y1:_y2, _x1:_x2]).copy() if prev is not None: uc0[prev[_y1:_y2, _x1:_x2] == lbl] = \ uc0[prev[_y1:_y2, _x1:_x2] == lbl] + opt.zwt chull = np.logical_and(chi(lmxy == lbl), lmxy == 0) ucost = np.zeros([lmxy.shape[0], lmxy.shape[1], 2], np.int32) ucost[:, :, 0] = -opt.uwt ucost[lmxy == lbl, 0] = opt.uwt ucost[chull, 0] = uc0[chull] ew0 = [ ewts[0][_y1:(_y2 - 1), _x1:_x2], ewts[1][_y1:_y2, _x1:(_x2 - 1)], ewts[2][_y1:(_y2 - 1), _x1:(_x2 - 1)], ewts[3][_y1:(_y2 - 1), _x1:(_x2 - 1)] ] joined = False for _ in range(opt.joinit): # Do a graph cut after biasing the background ucost[chull, 0] = ucost[chull, 0] + opt.joininc lmxy2 = gco.cut_grid_graph(ucost, pwcost, *ew0).reshape(lmxy.shape) if ndi.label(lmxy2 == 1)[1] == 1: # Now, see if we can remove some of the added components newcomps, nnc = ndi.label(np.logical_and( lmxy2 == 1, lmxy == 0)) if nnc > 1: scores = np.bincount(newcomps.flatten(), uc0.flatten()) cidx = np.argsort(scores[1:]) + 1 for ncidx in cidx: lmxy2b = lmxy2.copy() lmxy2b[newcomps == ncidx] = 0 if ndi.label(lmxy2b)[1] == 1: lmxy2 = lmxy2b # Patch things back in lmxy[lmxy2 == 1] = lbl lmap[_y1:_y2, _x1:_x2] = lmxy joined = True break if not joined: ccxy = ndi.label(lmxy == lbl)[0] ccount = np.bincount(ccxy.flatten()) ccsort = np.argsort(-ccount[1:]) for idx in range(1, len(ccsort)): lmxy[ccxy == (ccsort[idx] + 1)] = 0 lmap[_y1:_y2, _x1:_x2] = lmxy return lmap