Download this file

198 lines (155 with data), 7.2 kB

  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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
% Calculate the Neighboring Gray-Tone Difference Matrix (NGTDM)
%
% See:
% Moses Amadasun and Robert T. King, "Textural Features Corresponding to
% Texural Properties," IEEE Transactions on Systems, Man, and
% Cybernetics. Vol. 19, No. 5, September/October 1989, pp. 1264-1274.
%
% This version is for 2D and 3D.
%
% NGTDM stands for "Neighborhood Gray-Tone Difference Matrix.
%
% g_nd is the input gray-scale image in two or three dimensions.
% s_nd is the input binary-valued segmentation image in two or three
% dimensions.
%
% d is the neighborhood size. I.e., if d=1 then the neighborhood is a
% region surrounding a pixel of size (2d+1) x (2d+1) = 3 x 3 or
% (2d+1) x (2d+1) x (2d+1) = 3 x 3 x 3.
% If d=2 then the neighborhod is of size 5 x 5 or 5 x 5 x 5.
function [ak_coarseness, ak_contrast, ak_busyness, ak_complexity, ...
ak_texture_strength] = ngtdm(g_nd, s_nd, d)
num_dim = length(size(s_nd)) ;
if (num_dim == 2)
disp(' Calculating NGTDM from Amadasun and King ...') ;
g_min = min(min(g_nd)) ;
g_max = max(max(g_nd)) ;
g_2d = (g_nd - g_min) + 1 ;
s = zeros(g_max - g_min + 1, 1) ;
p = zeros(size(s)) ;
num_this_gray = zeros(size(s)) ;
sqrt_W = (2 * d) + 1 ;
W = sqrt_W^2 ;
Wm1 = W - 1 ;
% Create a (row, col) list of pixels that are inside the binary object
% and that have a "guard band" sufficiently big so that they can be
% included in the calulations of the NGTDM.
[iii_list, jjj_list] = ind2sub(size(s_nd), find(s_nd > 0)) ;
iii_list_pruned = zeros(size(iii_list)) ;
jjj_list_pruned = zeros(size(jjj_list)) ;
count = 0 ;
for m = 1:length(iii_list)
if (sum(sum(s_nd(iii_list(m)-d:iii_list(m)+d, ...
jjj_list(m)-d:jjj_list(m)+d))) == W)
count = count + 1 ;
iii_list_pruned(count) = iii_list(m) ;
jjj_list_pruned(count) = jjj_list(m) ;
end
end
iii_list_pruned = iii_list_pruned(1:count) ;
jjj_list_pruned = jjj_list_pruned(1:count) ;
% Now loop through all of the included voxels and calculate tne NGTDM.
for m = 1:length(iii_list_pruned)
i = iii_list_pruned(m) ;
j = jjj_list_pruned(m) ;
index = g_2d(i, j) ;
A = (sum(sum(g_2d(i-d:i+d,j-d:j+d))) - g_2d(i,j)) / Wm1 ;
s(index) = s(index) + abs(index - A) ;
num_this_gray(index) = num_this_gray(index) + 1 ;
end
p = num_this_gray / sum(num_this_gray) ;
disp(' Finished calculating NGTDM from Amadasun and King.') ;
elseif (num_dim == 3)
disp(' Calculating NGTDM from Amadasun and King ...') ;
g_min = min(min(min(g_nd))) ;
g_max = max(max(max(g_nd))) ;
g_3d = (g_nd - g_min) + 1 ;
s = zeros(g_max - g_min + 1, 1) ;
p = zeros(size(s)) ;
num_this_gray = zeros(size(s)) ;
cube_root_W = (2 * d) + 1 ;
W = cube_root_W^3 ;
Wm1 = W - 1 ;
% Create a (row, col, plane) list of pixels that are inside the binary
% object and that have a "guard band" sufficiently big so that they can
% be included in the calculations of the NGTDM.
[iii_list, jjj_list, kkk_list] = ind2sub(size(s_nd), find(s_nd > 0)) ;
iii_list_pruned = zeros(size(iii_list)) ;
jjj_list_pruned = zeros(size(jjj_list)) ;
kkk_list_pruned = zeros(size(kkk_list)) ;
count = 0 ;
for m = 1:length(iii_list)
if (sum(sum(sum(s_nd(iii_list(m)-d:iii_list(m)+d, ...
jjj_list(m)-d:jjj_list(m)+d, ...
kkk_list(m)-d:kkk_list(m)+d)))) == W)
count = count + 1 ;
iii_list_pruned(count) = iii_list(m) ;
jjj_list_pruned(count) = jjj_list(m) ;
kkk_list_pruned(count) = kkk_list(m) ;
end
end
iii_list_pruned = iii_list_pruned(1:count) ;
jjj_list_pruned = jjj_list_pruned(1:count) ;
kkk_list_pruned = kkk_list_pruned(1:count) ;
% Now loop through all of the included voxels and calculate the NGTDM.
for m = 1:length(iii_list_pruned)
i = iii_list_pruned(m) ;
j = jjj_list_pruned(m) ;
k = kkk_list_pruned(m) ;
index = g_3d(i, j, k) ;
A = (sum(sum(sum(g_3d(i-d:i+d,j-d:j+d,k-d:k+d)))) - g_3d(i,j,k)) / Wm1 ;
s(index) = s(index) + abs(index - A) ;
num_this_gray(index) = num_this_gray(index) + 1 ;
end
p = num_this_gray / sum(num_this_gray) ;
disp(' Finished calculating NGTDM from Amadasun and King.') ;
else
disp('ERROR: The binary segmentation image is neither 2D nor 3D') ;
exit ;
end
% Next, we'll compute the 5 texture measures, but first we'll compute
% some variables that are common to more than 1 of the measures.
epsilon = 10^(-7) ; % This was Amadasun and King's choice
i_vec_pruned = find(p > 0) ;
p_pruned = p(i_vec_pruned) ;
s_pruned = s(i_vec_pruned) ;
num_pix_or_vox = length(iii_list_pruned) ;
N_g = length(i_vec_pruned) ;
i_mat = meshgrid(i_vec_pruned) ;
j_mat = i_mat' ;
pi_mat = meshgrid(p_pruned) ;
pj_mat = pi_mat' ;
% Now compute the first texture metric, coarseness.
disp(' Computing coarseness (Amadasun and King, 1989) ...') ;
ak_coarseness = 1 / (epsilon + sum(p_pruned .* s_pruned)) ;
disp(' Finished computing coarseness.') ;
% Now compute the second texture metric, contrast.
disp(' Computing contrast (Amadasun and King, 1989) ...') ;
factor_1 = 1 / (N_g * (N_g - 1)) ;
% factor_2 = sum(sum(p_pruned * p_pruned' * toeplitz((i_vec_pruned - 1).^2))) ;
factor_2 = sum(sum(pi_mat .* pj_mat .* ((i_mat - j_mat).^2))) ;
factor_3 = sum(s_pruned) / num_pix_or_vox ;
ak_contrast = factor_1 * factor_2 * factor_3 ;
disp(' Finished computing contrast.') ;
% Now compute the third texture metric, busyness.
disp(' Computing busyness (Amadasun and King, 1989) ...') ;
numer = sum(p_pruned .* s_pruned) ;
ip_mat = meshgrid(i_vec_pruned .* p_pruned) ;
jp_mat = ip_mat' ;
denom = sum(sum(abs(ip_mat - jp_mat))) ;
ak_busyness = numer / denom ;
disp(' Finished computing busyness.') ;
% Now compute the fourth texture metric, complexity.
disp(' Computing complexity (Amadasun and King, 1989) ...') ;
psi_mat = meshgrid(p_pruned .* s_pruned) ;
psj_mat = psi_mat' ;
ak_complexity = sum(sum((abs(i_mat - j_mat) ./ (pi_mat + pj_mat)) ...
.* (psi_mat + psj_mat))) / num_pix_or_vox ;
disp(' Finished computing complexity.') ;
% Now compute the fifth texture metric, texture_strength.
disp(' Computing texture strength (Amadasun and King, 1989) ...') ;
numer = sum(sum((pi_mat + pj_mat) .* ((i_mat - j_mat).^2))) ;
denom = epsilon + sum(s_pruned) ;
ak_texture_strength = numer / denom ;
disp(' Finished computing texture strength.') ;
end