def lifted_multicut_kernighan_lin(graph, costs, lifted_uv_ids, lifted_costs,
                                  warmstart=True, time_limit=None, n_threads=1):
    objective = nlmc.liftedMulticutObjective(graph)
    objective.setGraphEdgesCosts(costs)
    objective.setCosts(lifted_uv_ids, lifted_costs)
    solver_kl = objective.liftedMulticutKernighanLinFactory().create(objective)
    if time_limit is None:
        if warmstart:
            solver_gaec = objective.liftedMulticutGreedyAdditiveFactory().create(objective)
            res = solver_gaec.optimize()
            return solver_kl.optimize(nodeLabels=res)
        else:
            return solver_kl.optimize()
    else:
        if warmstart:
            solver_gaec = objective.liftedMulticutGreedyAdditiveFactory().create(objective)
            visitor1 = objective.verboseVisitor(visitNth=1000000,
                                                timeLimitTotal=time_limit)
            t0 = time.time()
            res = solver_gaec.optimize(visitor=visitor1)
            t0 = time.time() - t0
            # time limit is not hard, so t0 might actually be bigger than
            # our time limit already
            if t0 > time_limit:
                return res
            visitor2 = objective.verboseVisitor(visitNth=1000000,
                                                timeLimitTotal=time_limit - t0)
            return solver_kl.optimize(nodeLabels=res,
                                      visitor=visitor2)

        else:
            visitor = objective.verboseVisitor(visitNth=1000000,
                                               timeLimitTotal=time_limit)
            return solver_kl.optimize(visitor=visitor)
예제 #2
0
    def compute_nh(self, graph_depth):
        # load the graph
        graph_path = os.path.join(self.tmp_folder, 'graph.n5', 'graph')
        graph = ndist.loadAsUndirectedGraph(graph_path)

        # load the node labels
        node_label_path = os.path.join(self.tmp_folder, 'node_labels.n5')
        node_label_key = 'node_labels'
        node_labels = z5py.File(node_label_path)[node_label_key][:]
        self.assertEqual(len(node_labels), graph.numberOfNodes)

        # run bfs up to depth 4 to get complete lifted nh
        lifted_graph = nlmc.liftedMulticutObjective(graph)
        lifted_graph.insertLiftedEdgesBfs(graph_depth)
        nh = lifted_graph.liftedUvIds()

        # filter by nodes which have a node labeling
        node_ids = np.arange(len(node_labels))
        nodes_with_label = node_ids[node_labels != 0]
        nh_mask = np.in1d(nh, nodes_with_label).reshape(nh.shape)
        nh_mask = nh_mask.all(axis=1)
        nh = nh[nh_mask]
        # need to lexsort - awkward in numpy ...
        nh = nh[np.lexsort(np.rot90(nh))]
        return nh
예제 #3
0
def _to_objective(graph, costs, lifted_uv_ids, lifted_costs):
    if isinstance(graph, nifty.graph.UndirectedGraph):
        graph_ = graph
    else:
        graph_ = nifty.graph.undirectedGraph(graph.numberOfNodes)
        graph_.insertEdges(graph.uvIds())
    objective = nlmc.liftedMulticutObjective(graph_)
    objective.setGraphEdgesCosts(costs)
    objective.setCosts(lifted_uv_ids, lifted_costs)
    return objective
예제 #4
0
def set_up_problem():
    path = './exp_data/exp_data.n5'

    # load the graph and edge probs
    f = z5py.File(path)
    ds = f['features']
    probs = ds[:, 0]
    g = ndist.Graph(os.path.join(path, 's0/graph'))
    graph = nifty.graph.UndirectedGraph(g.numberOfNodes + 1)
    graph.insertEdges(g.uvIds())

    # add lifted edges up to nhood 3
    nhood = 2
    obj = nlmc.liftedMulticutObjective(graph)
    obj.insertLiftedEdgesBfs(nhood)
    lifted_uvs = obj.liftedUvIds()
    print("Number of lifted edges:")
    print(len(lifted_uvs))

    chunks = (int(1e6), 2)
    f.create_dataset('s0/lifted_nh',
                     data=lifted_uvs,
                     chunks=chunks,
                     compression='gzip')

    # set the lifted costs according to the mean prob. of the shortest path
    print("Calculating costs ...")

    def find_costs_from_sp(lifted_id):
        print(lifted_id, "/", len(lifted_uvs))
        sp = nifty.graph.ShortestPathDijkstra(graph)
        u, v = lifted_uvs[lifted_id]
        edge_path = sp.runSingleSourceSingleTarget(probs, u, v, False)
        max_prob = np.max(probs[edge_path])
        return max_prob

    # p = find_costs_from_sp(0)
    # print(p)
    # return

    #
    n_threads = 8
    with futures.ThreadPoolExecutor(n_threads) as tp:
        tasks = [
            tp.submit(find_costs_from_sp, i) for i in range(len(lifted_uvs))
        ]
        costs = np.array([t.result() for t in tasks])
    assert len(costs) == len(lifted_uvs)
    costs = probs_to_costs(costs)
    chunks = (int(1e6), )
    f.create_dataset('s0/lifted_costs',
                     data=costs,
                     chunks=chunks,
                     compression='gzip')
def lifted_multicut_fusion_moves(graph, costs, lifted_uv_ids, lifted_costs,
                                 time_limit=None, n_threads=1, solver='kernighan-lin'):
    assert solver in ('kernighan-lin', 'greedy-additive')
    objective = nlmc.liftedMulticutObjective(graph)
    objective.setGraphEdgesCosts(costs)
    objective.setCosts(lifted_uv_ids, lifted_costs)
    if time_limit is None:
        return solver.optimize()
    else:
        visitor = objective.verboseVisitor(visitNth=1000000,
                                           timeLimitTotal=time_limit)
        return solver.optimize(visitor=visitor)
def lifted_multicut_gaec(graph, costs, lifted_uv_ids, lifted_costs,
                         time_limit=None, n_threads=1):
    objective = nlmc.liftedMulticutObjective(graph)
    objective.setGraphEdgesCosts(costs)
    objective.setCosts(lifted_uv_ids, lifted_costs)
    solver = objective.liftedMulticutGreedyAdditiveFactory().create(objective)
    if time_limit is None:
        return solver.optimize()
    else:
        visitor = objective.verboseVisitor(visitNth=1000000,
                                           timeLimitTotal=time_limit)
        return solver.optimize(visitor=visitor)
def make_filtered_lifted_nh(rag, n_labels, uv_ids, lifted_nh):
    # we can't build the full lifted nh, because the extended fragments
    # connect short-cut lifted edges.
    # Hence, we only create the nhood of small - to - snall fragments WITHOUT extended fragments,
    # small - to - extended and extended to extended

    # find the extended nodes
    extended_node_list = np.array(nrag.findZExtendedNodes(rag), dtype='uint32')
    # filter the initial uv ids to exclude extended nodes
    edge_mask = np.in1d(uv_ids, extended_node_list).reshape(uv_ids.shape)
    edge_mask = (edge_mask == 0).all(axis=1)
    filtered_uv_ids = uv_ids[edge_mask]

    # get the corresponding lifted nh
    graph = nifty.graph.undirectedGraph(n_labels)
    graph.insertEdges(filtered_uv_ids)
    lifted_objective = nlmc.liftedMulticutObjective(graph)
    lifted_objective.insertLiftedEdgesBfs(lifted_nh)
    lifted_uv_ids = lifted_objective.liftedUvIds()

    # next, get the full lifted nh and post filter it for
    # small - to - small fragment connections
    graph = nifty.graph.undirectedGraph(n_labels)
    graph.insertEdges(uv_ids)
    lifted_objective = nlmc.liftedMulticutObjective(graph)
    lifted_objective.insertLiftedEdgesBfs(lifted_nh)
    additional_lifted_uv_ids = lifted_objective.liftedUvIds()
    full_lifted = len(additional_lifted_uv_ids)

    # filter edges that connect to small fragments
    edge_mask = np.in1d(additional_lifted_uv_ids, extended_node_list).reshape(
        additional_lifted_uv_ids.shape)
    edge_mask = np.sum(edge_mask, axis=1) > 1
    additional_lifted_uv_ids = additional_lifted_uv_ids[edge_mask]
    if additional_lifted_uv_ids.size:
        lifted_uv_ids = np.concatenate(
            [lifted_uv_ids, additional_lifted_uv_ids], axis=0)
    print("Filtered number of lifted edges from", len(lifted_uv_ids), "to",
          full_lifted)
    return lifted_uv_ids
예제 #8
0
def run_lmc(graph,
            local_uv_ids,
            lifted_uv_ids,
            local_probs,
            lifted_probs,
            local_sizes=None,
            lifted_sizes=None,
            weighting_exponent=1.,
            with_ignore_edges=True):

    if with_ignore_edges:
        # set the size of ignore edges to 1, to not mess up the weighting
        ignore_edges = (local_uv_ids == 0).any(axis=1)
        lifted_ignore_edges = (lifted_uv_ids == 0).any(axis=1)
        if local_sizes is not None:
            local_sizes[ignore_edges] = 1
        if lifted_sizes is not None:
            lifted_sizes[lifted_ignore_edges] = 1

    # turn probabilities into costs
    local_costs = cseg.transform_probabilities_to_costs(
        local_probs,
        edge_sizes=local_sizes,
        weighting_exponent=weighting_exponent)
    lifted_costs = cseg.transform_probabilities_to_costs(
        lifted_probs,
        edge_sizes=lifted_sizes,
        weighting_exponent=weighting_exponent)

    if with_ignore_edges:
        # set ignore labels (connecting to node id 0) to be maximally repulsive
        local_costs[ignore_edges] = -100
        lifted_costs[lifted_ignore_edges] = -100

    # build the lmc objective
    lifted_objective = nlmc.liftedMulticutObjective(graph)
    lifted_objective.setCosts(local_uv_ids, local_costs)
    lifted_objective.setCosts(lifted_uv_ids, lifted_costs)

    # compute lifted multicut
    solver_ga = lifted_objective.liftedMulticutGreedyAdditiveFactory().create(
        lifted_objective)
    node_labels = solver_ga.optimize()
    solver_kl = lifted_objective.liftedMulticutKernighanLinFactory().create(
        lifted_objective)
    node_labels = solver_kl.optimize(node_labels)

    # get indicators for merge !
    # and return uv-ids, edge indicators and edge sizes
    merge_indicator = (node_labels[local_uv_ids[:, 0]] == node_labels[
        local_uv_ids[:, 1]]).astype('uint8')
    return node_labels, merge_indicator
예제 #9
0
def lifted_multicut(n_nodes, local_uvs, local_costs, lifted_uvs, lifted_costs, time_limit=None):
    graph = nifty.graph.UndirectedGraph(n_nodes)
    graph.insertEdges(local_uvs)


    lifted_obj = nlmc.liftedMulticutObjective(graph)
    lifted_obj.setCosts(local_uvs, local_costs)
    lifted_obj.setCosts(lifted_uvs, lifted_costs)
    # visitor = lifted_obj.verboseVisitor(100)
    solver_ehc = lifted_obj.liftedMulticutGreedyAdditiveFactory().create(lifted_obj)
    node_labels = solver_ehc.optimize()
    solver_kl = lifted_obj.liftedMulticutKernighanLinFactory().create(lifted_obj)
    node_labels = solver_kl.optimize(node_labels)
    return node_labels
예제 #10
0
def lifted_multicut_kernighan_lin(graph, costs, lifted_uv_ids, lifted_costs,
                                  time_limit=None, warmstart=True,
                                  **kwargs):
    """ Solve lifted multicut problem with kernighan lin solver.

    Introduced in "Efficient decomposition of image and mesh graphs by lifted multicuts":
    http://openaccess.thecvf.com/content_iccv_2015/papers/Keuper_Efficient_Decomposition_of_ICCV_2015_paper.pdf

    Arguments:
        graph [nifty.graph] - graph of lifted multicut problem
        costs [np.ndarray] - edge costs of lifted multicut problem
        lifted_uv_ids [np.ndarray] - lifted edges
        lifted_costs [np.ndarray] - lifted edge costs
        time_limit [float] - time limit for inference (default: None)
        warmstart [bool] - whether to warmstart with gaec solution (default: True)
    """
    objective = nlmc.liftedMulticutObjective(graph)
    objective.setGraphEdgesCosts(costs)
    objective.setCosts(lifted_uv_ids, lifted_costs)
    solver_kl = objective.liftedMulticutKernighanLinFactory().create(objective)
    if time_limit is None:
        if warmstart:
            solver_gaec = objective.liftedMulticutGreedyAdditiveFactory().create(objective)
            res = solver_gaec.optimize()
            return solver_kl.optimize(nodeLabels=res)
        else:
            return solver_kl.optimize()
    else:
        if warmstart:
            solver_gaec = objective.liftedMulticutGreedyAdditiveFactory().create(objective)
            visitor1 = objective.verboseVisitor(visitNth=1000000,
                                                timeLimitTotal=time_limit)
            t0 = time.time()
            res = solver_gaec.optimize(visitor=visitor1)
            t0 = time.time() - t0
            # time limit is not hard, so t0 might actually be bigger than
            # our time limit already
            if t0 > time_limit:
                return res
            visitor2 = objective.verboseVisitor(visitNth=1000000,
                                                timeLimitTotal=time_limit - t0)
            return solver_kl.optimize(nodeLabels=res,
                                      visitor=visitor2)

        else:
            visitor = objective.verboseVisitor(visitNth=1000000,
                                               timeLimitTotal=time_limit)
            return solver_kl.optimize(visitor=visitor)
예제 #11
0
def lifted_multicut_fusion_moves(graph, costs, lifted_uv_ids, lifted_costs,
                                 time_limit=None, warmstart_gaec=True, warmstart_kl=True,
                                 **kwargs):
    """ Solve lifted multicut problem with greedy additive edge contraction solver.

    Introduced in "An efficient fusion move algorithm for the minimum cost lifted multicut problem":
    https://hci.iwr.uni-heidelberg.de/sites/default/files/publications/files/1939997197/beier_16_efficient.pdf

    Arguments:
        graph [nifty.graph] - graph of lifted multicut problem
        costs [np.ndarray] - edge costs of lifted multicut problem
        lifted_uv_ids [np.ndarray] - lifted edges
        lifted_costs [np.ndarray] - lifted edge costs
        time_limit [float] - time limit for inference (default: None)
        warmstart_gaec [bool] - whether to warmstart with gaec solution (default: True)
        warmstart_kl [bool] - whether to warmstart with kl solution (default: True)
    """
    objective = nlmc.liftedMulticutObjective(graph)
    objective.setGraphEdgesCosts(costs)
    objective.setCosts(lifted_uv_ids, lifted_costs)

    # TODO keep track of time limits when warmstarting
    # perform warmstarts
    node_labels = None
    if warmstart_gaec:
        solver_gaec = objective.liftedMulticutGreedyAdditiveFactory().create(objective)
        node_labels = solver_gaec.optimize()
    if warmstart_kl:
        solver_kl = objective.liftedMulticutKernighanLinFactory().create(objective)
        node_labels = solver_kl.optimize(node_labels)

    # nifty only supports numberOfThreads=1
    # why doesn't nifty expose the internal solver here ?
    solver = objective.fusionMoveBasedFactory(numberOfThreads=1).create(objective)
    if time_limit is None:
        return solver.optimize() if node_labels is None else solver.optimize(node_labels)
    else:
        visitor = objective.verboseVisitor(visitNth=1000000,
                                           timeLimitTotal=time_limit)
        return solver.optimize(visitor=visitor) if node_labels is None else\
            solver.optimize(nodeLabels=node_labels, visitor=visitor)
예제 #12
0
def compute_energy(name):
    exp_path = './exp_data/%s.n5' % name
    f = z5py.File(exp_path)

    g = ndist.Graph(os.path.join(exp_path, 's0', 'graph'))
    graph = nifty.graph.undirectedGraph(g.numberOfNodes + 1)
    graph.insertEdges(g.uvIds())

    costs = f['s0/costs'][:]
    lifted_costs = f['s0/lifted_costs_%s' % name][:]
    lifted_uvs = f['s0/lifted_nh_%s' % name][:]

    obj = nlmc.liftedMulticutObjective(graph)
    obj.setGraphEdgesCosts(costs)
    obj.setCosts(lifted_uvs, lifted_costs)

    path = '/g/kreshuk/data/FIB25/cutout.n5'
    res_key = 'node_labels/%s' % name
    with z5py.File(path) as f:
        node_labels = f[res_key][:]

    e = obj.evalNodeLabels(node_labels)
    return e
예제 #13
0
def lifted_multicut_gaec(graph, costs, lifted_uv_ids, lifted_costs,
                         time_limit=None, **kwargs):
    """ Solve lifted multicut problem with greedy additive edge contraction solver.

    Introduced in "An efficient fusion move algorithm for the minimum cost lifted multicut problem":
    https://hci.iwr.uni-heidelberg.de/sites/default/files/publications/files/1939997197/beier_16_efficient.pdf

    Arguments:
        graph [nifty.graph] - graph of lifted multicut problem
        costs [np.ndarray] - edge costs of lifted multicut problem
        lifted_uv_ids [np.ndarray] - lifted edges
        lifted_costs [np.ndarray] - lifted edge costs
        time_limit [float] - time limit for inference (default: None)
    """
    objective = nlmc.liftedMulticutObjective(graph)
    objective.setGraphEdgesCosts(costs)
    objective.setCosts(lifted_uv_ids, lifted_costs)
    solver = objective.liftedMulticutGreedyAdditiveFactory().create(objective)
    if time_limit is None:
        return solver.optimize()
    else:
        visitor = objective.verboseVisitor(visitNth=1000000,
                                           timeLimitTotal=time_limit)
        return solver.optimize(visitor=visitor)
예제 #14
0
    def __call__(self,
                 local_uvs,
                 lifted_uvs,
                 local_costs,
                 lifted_costs,
                 time_limit=None,
                 **kwargs):
        n_nodes = int(local_uvs.max()) + 1
        graph = nifty.graph.undirectedGraph(n_nodes)
        graph.insertEdges(local_uvs)
        objective = nlmc.liftedMulticutObjective(graph)

        # TODO local vs. lifted weighting ?!

        objective.setCosts(local_uvs, local_costs)
        objective.setCosts(lifted_uvs, lifted_costs)

        # TODO visitors and time limit!
        # TODO would be nice to have solver chaining in nifty for lmc too
        solver_ga = objective.liftedMulticutGreedyAdditiveFactory().create(
            objective)
        # first solve greedy-agglomerative
        node_labels = solver_ga.optimize()
        if self.solver == 'greedy-additive':
            return node_labels
        else:
            solver_kl = objective.liftedMulticutKernighanLinFactory().create(
                objective)
            node_labels = solver_kl.optimize(node_labels)
            if self.solver == 'kernighan-lin':
                return node_labels
            elif self.solver == 'fusion-moves':
                solver_fm = self._get_fusion_moves(objective)
                node_labels = solver_fm.optimize(node_labels)

        return node_labels