Maxflow - Segmentation: 1 Image Restoration / Segmentation Project
Maxflow - Segmentation: 1 Image Restoration / Segmentation Project
import maxflow
# Add two (non-terminal) nodes. Get the index to the first one.
nodes = g.add_nodes(2)
# Create two edges (forwards and backwards) with the given capacities.
# The indices of the nodes are always consecutive.
g.add_edge(nodes[0], nodes[1], 1, 2)
# Set the capacities of the terminal edges...
# ...for the first node.
g.add_tedge(nodes[0], 2, 5)
# ...for the second node.
g.add_tedge(nodes[1], 9, 4)
flow = g.maxflow()
print("Maximum flow:", flow)
Maximum flow: 8
1
In [19]: print("Segment of the node 0:", g.get_segment(nodes[0]))
print("Segment of the node 1:", g.get_segment(nodes[1]))
1.2.1 interpretation
The result can be interpreted in the following way:
img = imread("a2.png")
/usr/local/Cellar/ipython/7.3.0/libexec/vendor/lib/python3.7/site-packages/ipykernel_launcher.py
`imread` is deprecated in SciPy 1.0.0, and will be removed in 1.2.0.
Use ``imageio.imread`` instead.
E(x) = ∑ Di ( x i ) + λ ∑ | xi − x j |
i (i,j)∈C
,
where x ∈ {0, 1} N are the values of the restored image, N is the number of pixels. The unary
term Di (0) (resp Di (1)) is the penalty for assigning the value 0 (resp 1) to the i-th pixel. Each Di
depends on the values of the noisy image, which are denoted as pi :
Di ( xi ) = \begin{cases} p_i & if x_i=0\ 255-p_i & if x_i=1 \end{cases}.
Thus, Di is low when assigning the label 0 to dark pixels or the label 1 to bright pixels, and high
otherwise. The value λ is the regularization strength. The larger λ the smoother the restoration.
We set it to 50. This λ does not need to be a fixed constant for every pixel, but in this case it is. It
may not depend on x.
The maximum flow algorithm is widely used to minimize energy functions of this type. We
build a graph which represents the above energy. This graph has as many non-terminal nodes
as pixels in the image. The nodes are connected in a grid arrangement, so that the nodes corre-
sponding to neighbor pixels are connected by a forward and a backward edge. The capacities of
2
all non-terminal edges is λ. The capacities of the edges from the source node are set to Di (0), and
the capacities of the edges to the sink node are Di (1).
We could build this graph as in the first example. First, we would add all the nodes. Then,
we would iterate over the nodes adding the edges properly. However, this is extremely slow
in Python, especially when dealing with large images or stacks of images. PyMaxflow pro-
vides methods for building some complex graphs with a few calls. In this example we re-
view add_grid_nodes, add_grid_edges, which add edges with a fixed capacity to the grid, and
add_grid_tedges, which sets the capacities of the terminal edges for multiple nodes:
The method get_grid_segments returns an array with the same shape than nodeids. It is almost
equivalent to calling get_segment once for each node in nodeids, but much faster. For the i-th cell,
the array stores False if the i-th node belongs to the source segment (i.e., the corresponding pixel
has the label 1) and True if the node belongs to the sink segment (i.e., the corresponding pixel has
the label 0). We now get the labels for each pixel:
plt.figure(figsize=(2,2))
plt.imshow(img)
plt.figure(figsize=(2,2))
plt.imshow(img2)
plt.show()
<IPython.core.display.Javascript object>
<IPython.core.display.HTML object>
3
<IPython.core.display.Javascript object>
<IPython.core.display.HTML object>