File size: 6,036 Bytes
82813c6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
"""
====================
Morphological Snakes
====================

*Morphological Snakes* [1]_ are a family of methods for image segmentation.
Their behavior is similar to that of active contours (for example, *Geodesic
Active Contours* [2]_ or *Active Contours without Edges* [3]_). However,
*Morphological Snakes* use morphological operators (such as dilation or
erosion) over a binary array instead of solving PDEs over a floating point
array, which is the standard approach for active contours. This makes
*Morphological Snakes* faster and numerically more stable than their
traditional counterpart.

There are two *Morphological Snakes* methods available in this implementation:
*Morphological Geodesic Active Contours* (**MorphGAC**, implemented in the
function ``morphological_geodesic_active_contour``) and *Morphological Active
Contours without Edges* (**MorphACWE**, implemented in the function
``morphological_chan_vese``).

**MorphGAC** is suitable for images with visible contours, even when these
contours might be noisy, cluttered, or partially unclear. It requires, however,
that the image is preprocessed to highlight the contours. This can be done
using the function ``inverse_gaussian_gradient``, although the user might want
to define their own version. The quality of the **MorphGAC** segmentation
depends greatly on this preprocessing step.

On the contrary, **MorphACWE** works well when the pixel values of the inside
and the outside regions of the object to segment have different averages.
Unlike **MorphGAC**, **MorphACWE** does not require that the contours of the
object are well defined, and it works over the original image without any
preceding processing. This makes **MorphACWE** easier to use and tune than
**MorphGAC**.

References
----------

.. [1] A Morphological Approach to Curvature-based Evolution of Curves and
       Surfaces, Pablo Márquez-Neila, Luis Baumela and Luis Álvarez. In IEEE
       Transactions on Pattern Analysis and Machine Intelligence (PAMI),
       2014, :DOI:`10.1109/TPAMI.2013.106`
.. [2] Geodesic Active Contours, Vicent Caselles, Ron Kimmel and Guillermo
       Sapiro. In International Journal of Computer Vision (IJCV), 1997,
       :DOI:`10.1023/A:1007979827043`
.. [3] Active Contours without Edges, Tony Chan and Luminita Vese. In IEEE
       Transactions on Image Processing, 2001, :DOI:`10.1109/83.902291`

"""
import os

import numpy as np
import matplotlib.pyplot as plt
from skimage import data, img_as_float
from skimage.segmentation import (morphological_chan_vese,
                                  morphological_geodesic_active_contour,
                                  inverse_gaussian_gradient,
                                  checkerboard_level_set)
from cv2 import imread
from cv2 import imshow
from cv2 import waitKey
import cv2
def store_evolution_in(lst):
    """Returns a callback function to store the evolution of the level sets in
    the given list.
    """

    def _store(x):
        lst.append(np.copy(x))

    return _store

images = sorted(os.listdir('./mini/'))
# print(images)
for k, img in enumerate(images):
# Morphological ACWE
    image1 = imread(f'./mini/{img}', 0)
    image = image1.copy()
    # Initial level set
    init_ls = checkerboard_level_set(image.shape, 6)
    # List with intermediate results for plotting the evolution
    evolution = []
    callback = store_evolution_in(evolution)
    ls = morphological_chan_vese(image, num_iter=35, init_level_set=init_ls,
                                 smoothing=3, iter_callback=callback)

    fig, axes = plt.subplots(2, 2, figsize=(8, 8))
    ax = axes.flatten()

    ax[0].imshow(image, cmap="gray")
    ax[0].set_axis_off()
    ax[0].contour(ls, [0.5], colors='r')
    ax[0].set_title("Morphological ACWE segmentation", fontsize=12)
    withe = np.ones_like(image, dtype='uint8') * 255

    ret1,thresh1 = cv2.threshold(withe,70,255,0)
    ret,thresh = cv2.threshold(image1,70,255,0)

    new = np.bitwise_and(cv2.bitwise_not(ls),thresh)[140:420,70:420]

    for i in range(new.shape[0]):
        for j in range(new.shape[1]):
            if new[i][j] > 0:
                new[i][j] -= 130


    cv2.imwrite(f'./output/{img}', new)


# ax[1].imshow(ls, cmap="gray")
# ax[1].set_axis_off()
# contour = ax[1].contour(evolution[2], [0.5], colors='g')
# contour.collections[0].set_label("Iteration 2")
# contour = ax[1].contour(evolution[7], [0.5], colors='y')
# contour.collections[0].set_label("Iteration 7")
# contour = ax[1].contour(evolution[-1], [0.5], colors='r')
# contour.collections[0].set_label("Iteration 35")
# ax[1].legend(loc="upper right")
# title = "Morphological ACWE evolution"
# ax[1].set_title(title, fontsize=12)


# Morphological GAC
# image = img_as_float(data.coins())
#gimage = inverse_gaussian_gradient(image)

# Initial level set
#init_ls = np.zeros(image.shape, dtype=np.int8)
#init_ls[10:-10, 10:-10] = 1
# List with intermediate results for plotting the evolution
#evolution = []
#callback = store_evolution_in(evolution)
#ls = morphological_geodesic_active_contour(gimage, num_iter=230,
 #                                          init_level_set=init_ls,
#                                           smoothing=1, balloon=-1,
#                                           threshold=0.69,
#                                           iter_callback=callback)

# ax[2].imshow(new, cmap="gray")
# ax[2].set_axis_off()
#ax[2].contour(ls, [0.5], colors='r')
#ax[2].set_title("Morphological GAC segmentation", fontsize=12)

#ax[3].imshow(ls, cmap="gray")
#ax[3].set_axis_off()
#contour = ax[3].contour(evolution[0], [0.5], colors='g')
#contour.collections[0].set_label("Iteration 0")
#contour = ax[3].contour(evolution[100], [0.5], colors='y')
#contour.collections[0].set_label("Iteration 100")
#contour = ax[3].contour(evolution[-1], [0.5], colors='r')
#contour.collections[0].set_label("Iteration 230")
#ax[3].legend(loc="upper right")
#title = "Morphological GAC evolution"
#ax[3].set_title(title, fontsize=12)

# fig.tight_layout()
# plt.show()