def graph_from_voxels(fg_markers,
                        bg_markers,
                        regional_term = False,
                        boundary_term = False,
                        regional_term_args = False,
                        boundary_term_args = False):
    """
    Create a graph-cut ready graph to segment a nD image using the voxel neighbourhood.
    
    Create a `~medpy.graphcut.maxflow.GraphDouble` object for all voxels of an image with a
    :math:`ndim * 2` neighbourhood.
    
    Every voxel of the image is regarded as a node. They are connected to their immediate
    neighbours via arcs. If to voxels are neighbours is determined using
    :math:`ndim*2`-connectedness (e.g. :math:`3*2=6` for 3D). In the next step the arcs weights
    (n-weights) are computed using the supplied ``boundary_term`` function
    (see :mod:`~medpy.graphcut.energy_voxel` for a selection).
    
    Implicitly the graph holds two additional nodes: the source and the sink, so called
    terminal nodes. These are connected with all other nodes through arcs of an initial
    weight (t-weight) of zero.
    All voxels that are under the foreground markers are considered to be tightly bound
    to the source: The t-weight of the arc from source to these nodes is set to a maximum
    value. The same goes for the background markers: The covered voxels receive a maximum
    (`~medpy.graphcut.graph.GCGraph.MAX`) t-weight for their arc towards the sink.
    
    All other t-weights are set using the supplied ``regional_term`` function
    (see :mod:`~medpy.graphcut.energy_voxel` for a selection).
    
    Parameters
    ----------
    fg_markers : ndarray
        The foreground markers as binary array of the same shape as the original image.
    bg_markers : ndarray
        The background markers as binary array of the same shape as the original image.
    regional_term : function
        This can be either `False`, in which case all t-weights are set to 0, except for
        the nodes that are directly connected to the source or sink; or a function, in
        which case the supplied function is used to compute the t_edges. It has to
        have the following signature *regional_term(graph, regional_term_args)*, and is
        supposed to compute (source_t_weight, sink_t_weight) for all voxels of the image
        and add these to the passed `~medpy.graphcut.graph.GCGraph` object. The weights
        have only to be computed for nodes where they do not equal zero. Additional
        parameters can be passed to the function via the ``regional_term_args`` parameter.
    boundary_term : function
        This can be either `False`, in which case all n-edges, i.e. between all nodes
        that are not source or sink, are set to 0; or a function, in which case the
        supplied function is used to compute the edge weights. It has to have the
        following signature *boundary_term(graph, boundary_term_args)*, and is supposed
        to compute the edges between the graphs nodes and to add them to the supplied
        `~medpy.graphcut.graph.GCGraph` object. Additional parameters can be passed to
        the function via the ``boundary_term_args`` parameter.
    regional_term_args : tuple
        Use this to pass some additional parameters to the ``regional_term`` function.
    boundary_term_args : tuple    
        Use this to pass some additional parameters to the ``boundary_term`` function.
    
    Returns
    -------
    graph : `~medpy.graphcut.maxflow.GraphDouble`
        The created graph, ready to execute the graph-cut.
    
    Raises
    ------
    AttributeError
        If an argument is malformed.
    FunctionError
        If one of the supplied functions returns unexpected results.
    
    Notes
    -----
    If a voxel is marked as both, foreground and background, the background marker
    is given higher priority.
     
    All arcs whose weight is not explicitly set are assumed to carry a weight of zero.
    """
    # prepare logger
    logger = Logger.getInstance()
    
    # prepare result graph
    logger.debug('Assuming {} nodes and {} edges for image of shape {}'.format(fg_markers.size, __voxel_4conectedness(fg_markers.shape), fg_markers.shape)) 
    graph = GCGraph(fg_markers.size, __voxel_4conectedness(fg_markers.shape))
    
    logger.info('Performing attribute tests...')
    
    # check, set and convert all supplied parameters
    fg_markers = scipy.asarray(fg_markers, dtype=scipy.bool_)
    bg_markers = scipy.asarray(bg_markers, dtype=scipy.bool_)
    
    # set dummy functions if not supplied
    if not regional_term: regional_term = __regional_term_voxel
    if not boundary_term: boundary_term = __boundary_term_voxel
    
    # check supplied functions and their signature
    if not hasattr(regional_term, '__call__') or not 2 == len(inspect.getargspec(regional_term)[0]):
        raise AttributeError('regional_term has to be a callable object which takes two parameter.')
    if not hasattr(boundary_term, '__call__') or not 2 == len(inspect.getargspec(boundary_term)[0]):
        raise AttributeError('boundary_term has to be a callable object which takes two parameters.')

    logger.debug('#nodes={}, #hardwired-nodes source/sink={}/{}'.format(fg_markers.size,
                                                                        len(fg_markers.ravel().nonzero()[0]),
                                                                        len(bg_markers.ravel().nonzero()[0])))
    
    # compute the weights of all edges from the source and to the sink i.e.
    # compute the weights of the t_edges Wt
    logger.info('Computing and adding terminal edge weights...')
    regional_term(graph, regional_term_args)

    # compute the weights of the edges between the neighbouring nodes i.e.
    # compute the weights of the n_edges Wr
    logger.info('Computing and adding inter-node edge weights...')
    boundary_term(graph, boundary_term_args)
    
    # collect all voxels that are under the foreground resp. background markers i.e.
    # collect all nodes that are connected to the source resp. sink
    logger.info('Setting terminal weights for the markers...')
    if not 0 == scipy.count_nonzero(fg_markers):
        graph.set_source_nodes(fg_markers.ravel().nonzero()[0])
    if not 0 == scipy.count_nonzero(bg_markers):
        graph.set_sink_nodes(bg_markers.ravel().nonzero()[0])    
    
    return graph.get_graph()
Create a graph-cut ready graph to segment a nD image using the voxel neighbourhood.
    
    Create a `~medpy.graphcut.maxflow.GraphDouble` object for all voxels of an image with a
    :math:`ndim * 2` neighbourhood.
    
    Every voxel of the image is regarded as a node. They are connected to their immediate
    neighbours via arcs. If to voxels are neighbours is determined using
    :math:`ndim*2`-connectedness (e.g. :math:`3*2=6` for 3D). In the next step the arcs weights
    (n-weights) are computed using the supplied ``boundary_term`` function
    (see :mod:`~medpy.graphcut.energy_voxel` for a selection).
    
    Implicitly the graph holds two additional nodes: the source and the sink, so called
    terminal nodes. These are connected with all other nodes through arcs of an initial
    weight (t-weight) of zero.
    All voxels that are under the foreground markers are considered to be tightly bound
    to the source: The t-weight of the arc from source to these nodes is set to a maximum
    value. The same goes for the background markers: The covered voxels receive a maximum
    (`~medpy.graphcut.graph.GCGraph.MAX`) t-weight for their arc towards the sink.
    
    All other t-weights are set using the supplied ``regional_term`` function
    (see :mod:`~medpy.graphcut.energy_voxel` for a selection).
    
    Parameters
    ----------
    fg_markers : ndarray
        The foreground markers as binary array of the same shape as the original image.
    bg_markers : ndarray
        The background markers as binary array of the same shape as the original image.
    regional_term : function
        This can be either `False`, in which case all t-weights are set to 0, except for
        the nodes that are directly connected to the source or sink; or a function, in
        which case the supplied function is used to compute the t_edges. It has to
        have the following signature *regional_term(graph, regional_term_args)*, and is
        supposed to compute (source_t_weight, sink_t_weight) for all voxels of the image
        and add these to the passed `~medpy.graphcut.graph.GCGraph` object. The weights
        have only to be computed for nodes where they do not equal zero. Additional
        parameters can be passed to the function via the ``regional_term_args`` parameter.
    boundary_term : function
        This can be either `False`, in which case all n-edges, i.e. between all nodes
        that are not source or sink, are set to 0; or a function, in which case the
        supplied function is used to compute the edge weights. It has to have the
        following signature *boundary_term(graph, boundary_term_args)*, and is supposed
        to compute the edges between the graphs nodes and to add them to the supplied
        `~medpy.graphcut.graph.GCGraph` object. Additional parameters can be passed to
        the function via the ``boundary_term_args`` parameter.
    regional_term_args : tuple
        Use this to pass some additional parameters to the ``regional_term`` function.
    boundary_term_args : tuple    
        Use this to pass some additional parameters to the ``boundary_term`` function.
    
    Returns
    -------
    graph : `~medpy.graphcut.maxflow.GraphDouble`
        The created graph, ready to execute the graph-cut.
    
    Raises
    ------
    AttributeError
        If an argument is malformed.
    FunctionError
        If one of the supplied functions returns unexpected results.
    
    Notes
    -----
    If a voxel is marked as both, foreground and background, the background marker
    is given higher priority.
     
    All arcs whose weight is not explicitly set are assumed to carry a weight of zero.