-
Notifications
You must be signed in to change notification settings - Fork 2
/
FastFCMeans.py
153 lines (104 loc) · 4.01 KB
/
FastFCMeans.py
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
# Segment N-dimensional grayscale image into c classes using a memory
# efficient implementation of the fuzzy c-means (FCM) clustering algorithm.
# The computational efficiency is achieved by using the histogram of the
# image intensities during the clustering process instead of the raw image
# data.
#
# INPUT ARGUMENTS:
# - im : N-dimensional grayscale image in integer format.
# - c : positive interger greater than 1 specifying the number of
# clusters. c=2 is the default setting. Alternatively, c can be
# specified as a k-by-1 array of initial cluster (aka prototype)
# centroids.
# - q : fuzzy weighting exponent. q must be a real number greater than
# 1.1. q=2 is the default setting. Increasing q leads to an
# increased amount of fuzzification, while reducing q leads to
# crispier class memberships.
#
# OUTPUT :
# - L : label image of the same size as the input image. For example,
# L==i represents the region associated with prototype C(i),
# where i=[1,k] (k = number of clusters).
# - C : 1-by-k array of cluster centroids.
# - U : L-by-k array of fuzzy class memberships, where k is the number
# of classes and L is the intensity range of the input image,
# such that L=numel(min(im(:)):max(im(:))).
# - LUT : L-by-1 array that specifies the defuzzified intensity-class
# relations, where L is the dynamic intensity range of the input
# image. Specifically, LUT(1) corresponds to class assigned to
# min(im(:)) and LUT(L) corresponds to the class assigned to
# max(im(:)). See 'apply_LUT' function for more info.
# - H : image histogram. If I=min(im(:)):max(im(:)) are the intensities
# present in the input image, then H(i) is the number of image
# pixels/voxels that have intensity I(i).
#
import numpy as np
import matplotlib.pyplot as plt
import tifwork as tw
import scipy.misc
import LUT2label as label
import FastCMeans as fc
def FastFCMeans(im, c, q):
#intensity range
Imin = float(np.min(im[:]))
Imax = float(np.max(im[:]))
I = np.transpose(np.array(np.arange(Imin,Imax+1)))
I = I[:, np.newaxis]
#print 'I size ', I.shape
#print Imin, Imax
# Compute intensity histogram
H = np.histogram(im.flatten(),I.flatten())
(H1, H2) = H
#H1 = H1.flatten()
#H2 = H2.flatten()
H1 = H1[:, np.newaxis]
H2 = H2[:, np.newaxis]
#print 'H1 and H2 Size: ', H1.shape, H2.shape
H = np.copy(np.append(H1,[1]))
H = H[:, np.newaxis]
#print H.shape
#plt.show()
#print H
#Initialize Cluster Centroids
if np.size(c) > 1:
C = c
c = np.size(c)
else:
(l,C,lut) = fc.FastCMeans(im,c)
#Update Fuzzy Memberships and cluster centroids
#I = repmat(I,[1 c])
I = np.tile(I,np.array([1,c]))
#print ' I shape ', I.shape
dC = np.inf
eps = np.finfo(float).eps
#print 'Epsilon is ', eps
while (dC > 1E-6):
C0 = np.copy(C)
#Distance to the centroids
D = np.abs(I-C)
D = D**(2/(q-1)) + eps
#compute fuzzy memberships
recipSum = np.sum(1/D,1)
recipSum = recipSum[:, np.newaxis]
U = D * recipSum
U = 1/(U+ eps)
#update the centroids
UH = (U**q) * H
s1 = np.sum(UH * I,0)
s1 = s1[:,np.newaxis]
s2 = np.sum(UH,0).astype(float)
s2 = s2[:, np.newaxis]
s1 = np.transpose(s1)
s2 = np.transpose(s2)
C = s1 /s2
C = np.sort(C)
#Change in centroids
dC = np.max(np.abs(C-C0))
#Defuzzify and create a label image
Umax = np.max(U,1)
#Umax = Umax[:,np.newaxis]
#print Umax
LUT = np.argmax(U,1)
#print LUT2label
L = label.LUT2label(im,LUT)
return (L,C,U,LUT,H)