| Bsoft 1.9 Bernard's software package

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
img_graphseg.cpp
Go to the documentation of this file.
1
9 #include "Bimage.h"
10 #include "img_graphseg.h"
11 #include "utilities.h"
12
13 // Declaration of global variables
14 extern int verbose; // Level of output to the screen
15
16 int QsortSmallToLargeEdge(const void *x, const void *y)
17 {
18 Edge* r1 = (Edge*) x;
19 Edge* r2 = (Edge*) y;
20 if( r1->w < r2->w ) return -1;
21 else return 1;
22 }
23
24 size_t region_find(Region* region, size_t i)
25 {
26 size_t j(i);
27 while ( j != region[j].p ) j = region[j].p;
28 region[i].p = j;
29 return j;
30 }
31
32 int region_join(Region* region, size_t i, size_t j)
33 {
34 if ( i == j ) return 0;
35
36 int s(region[i].s + region[j].s);
37 double a((region[i].s*region[i].a + region[j].s*region[j].a)/s);
38
39 if ( region[i].r > region[j].r ) {
40 region[j].p = i;
41 region[i].s += region[j].s;
42 region[i].a = a;
43 } else {
44 region[i].p = j;
45 region[j].s += region[i].s;
46 region[j].a = a;
47 if ( region[i].r == region[j].r ) region[j].r++;
48 }
49
50 return 1;
51 }
52
53 /*
54 Sets up every voxel as a region with the voxel value.
55 */
56 Region* img_region_setup(Bimage* p, Bimage* pmask)
57 {
58 size_t i, imagesize(p->sizeX()*p->sizeY()*p->sizeZ());
59
60 Region* region = new Region[imagesize];
61
62 if ( pmask ) pmask->to_mask();
63
64 for ( i=0; i<imagesize; i++ ) {
65 region[i].p = i;
66 region[i].r = 0;
67 region[i].s = 1;
68 if ( !pmask || ( pmask && (*pmask)[i] ) ) region[i].a = (*p)[i];
69 else region[i].a = 0;
70 }
71
72 return region;
73 }
74
75 /*
76 Sets up each forward edge
77 */
78 Edge* img_edge_setup(Bimage* p, Bimage* pmask, int connect_type, size_t& me, size_t& ne)
79 {
80 size_t i, x, y, z, x1, y1, z1;
81 size_t imagesize = p->sizeX()*p->sizeY()*p->sizeZ();
82 size_t dim = (p->sizeZ() > 1)? 3: 2;
83 size_t n(imagesize);
84
85 if ( pmask ) {
86 pmask->to_mask();
87 for ( n=i=0; i<imagesize; i++ ) if ( (*pmask)[i] ) n++;
88 }
89
90 if ( connect_type < 1 ) me = dim*n;
91 else me = (p->sizeZ() > 1)? 13*n: 4*n;
92
93 Edge* edge = new Edge[me];
94
95 for ( ne=i=z=0; z<p->sizeZ(); z++ ) {
96 for ( y=0; y<p->sizeY(); y++ ) {
97 for ( x=0; x<p->sizeX(); x++, i++ ) if ( !pmask || ( pmask && (*pmask)[i] ) ) {
98 if ( x < p->sizeX() - 1 ) {
99 x1 = x + 1;
100 if ( connect_type ) {
101 for ( z1=(z>0)?z-1:z; z1<z+1 && z1<p->sizeZ(); z1++ ) {
102 for ( y1=(y>0)?y-1:y; y1<y+1 && y1<p->sizeY(); y1++ ) {
103 edge[ne].u = i;
104 edge[ne++].v = (z1*p->sizeY() + y1)*p->sizeX() + x1;
105 }
106 }
107 } else {
108 edge[ne].u = i;
109 edge[ne++].v = (z*p->sizeY() + y)*p->sizeX() + x1;
110 }
111 }
112 if ( y < p->sizeY() - 1 ) {
113 y1 = y + 1;
114 if ( connect_type ) {
115 for ( z1=(z>0)?z-1:z; z1<z+1 && z1<p->sizeZ(); z1++ ) {
116 edge[ne].u = i;
117 edge[ne++].v = (z1*p->sizeY() + y1)*p->sizeX() + x;
118 }
119 } else {
120 edge[ne].u = i;
121 edge[ne++].v = (z*p->sizeY() + y1)*p->sizeX() + x;
122 }
123 }
124 if ( z < p->sizeZ() - 1 ) {
125 z1 = z + 1;
126 edge[ne].u = i;
127 edge[ne++].v = (z1*p->sizeY() + y)*p->sizeX() + x;
128 }
129 }
130 }
131 }
132
133 for ( i=0; i<ne; i++ ) edge[i].w = fabs((*p)[edge[i].u] - (*p)[edge[i].v]);
134
135 return edge;
136 }
137
138 /*
139 The starting threshold is taken to be the standard deviation divided by the complexity value
140 */
141 size_t region_merging(Region* region, Edge* edge, size_t nrc, size_t ne, float threshold)
142 {
143 size_t i, u, v;
144 Edge e;
145 for ( i=0; i<ne; i++ ) {
146 e = edge[i];
147 u = region_find(region, e.u);
148 v = region_find(region, e.v);
149 if ( u != v ) {
150 if ( e.w <= region[u].a && e.w <= region[v].a ) {
151 nrc -= region_join(region, u, v);
152 u = region_find(region, u);
153 region[u].a = e.w + threshold/region[u].s;
154 }
155 }
156 }
157
158 return nrc;
159 }
160
161 /*
162 fac = g*g/Q, g is taken to be the standard deviation and Q a complexity value
163 */
164 size_t statistical_region_merging(Region* region, Edge* edge, size_t nr, size_t ne, double fac)
165 {
166 // Find segment memberships
167 double d2, ln1, ln2, s1, s2;
168 double lnd(2*log(6*nr));
169 size_t i, u, v, nrc(nr);
170 Edge e;
171
172 for ( i=0; i<ne; i++ ) {
173 e = edge[i];
174 u = region_find(region, e.u);
175 v = region_find(region, e.v);
176 if ( u != v ) {
177 d2 = region[u].a - region[v].a; d2 *= d2;
178 s1 = region[u].s; s2 = region[v].s;
179 // ln1 = lnd + log(1.0 + s1) * ((g < s1)? g: s1);
180 // ln2 = lnd + log(1.0 + s2) * ((g < s2)? g: s2);
181 ln1 = lnd + log(1.0 + s1);
182 ln2 = lnd + log(1.0 + s2);
183 if ( d2 < fac * (ln1/s1 + ln2/s2) )
184 nrc -= region_join(region, u, v);
185 }
186 }
187
188 return nrc;
189 }
190
191 size_t region_merge_small(Region* region, Edge* edge, size_t nrc, size_t ne, int min_size)
192 {
193 if ( min_size < 1 ) return nrc;
194
195 // Merge small regions
196 size_t i, u, v;
197 Edge e;
198
199 for ( i=0; i<ne; i++ ) {
200 e = edge[i];
201 u = region_find(region, e.u);
202 v = region_find(region, e.v);
203 if ( ( u != v ) && ( region[u].s < min_size || region[v].s < min_size ) ) {
204 nrc -= region_join(region, u, v);
205 }
206 }
207
208 return nrc;
209 }
210
233 size_t img_graph_segment(int type, Bimage* p, Bimage* pmask, int connect_type, double complexity, int min_size)
234 {
235 p->color_to_simple();
236 p->change_type(Float);
237
238 size_t i, j, ne;
239 size_t slicesize(p->sizeX()*p->sizeY());
240 size_t imagesize(slicesize*p->sizeZ());
241 size_t dim = (p->sizeZ() > 1)? 3: 2;
242 size_t max_edges;
243 double threshold(p->standard_deviation()/complexity);
244
245 if ( pmask ) pmask->to_mask();
246
247 if ( verbose ) {
248 cout << "Segmenting image:" << endl;
249 cout << "Algorithm: ";
250 if ( type == 1 ) {
251 cout << "Simple" << endl;
252 cout << "Threshold: " << threshold << endl;
253 } else {
254 cout << "Statistical region merging" << endl;
255 cout << "Complexity: " << complexity << endl;
256 }
257 cout << "Connectivity: ";
258 if ( connect_type < 1 ) cout << 2*dim << endl;
259 else if ( dim < 3 ) cout << 8 << endl;
260 else cout << 26 << endl;
261 cout << "Minimum size: " << min_size << endl;
262 }
263
264 Region* region = img_region_setup(p, pmask);
265
266 Edge* edge = img_edge_setup(p, pmask, connect_type, max_edges, ne);
267
268 qsort((void *) edge, ne, sizeof(Edge),
269 (int (*)(const void *, const void *)) QsortSmallToLargeEdge);
270
271 if ( verbose )
272 cout << "Number of edges: " << ne << endl;
273
274 size_t nr = imagesize, nrc = imagesize;
275
276 p->data_delete();
277
278 // Find segment memberships
279 if ( type == 1 ) {
280 for ( i=0; i<imagesize; i++ ) region[i].a = threshold;
281 nrc = region_merging(region, edge, nr, ne, threshold);
282 } else {
283 nrc = statistical_region_merging(region, edge, imagesize, ne, threshold*threshold);
284 }
285
286 // Merge small regions
287 if ( min_size > 0 ) {
288 if ( verbose )
289 cout << "Regions before merging: " << nrc << endl;
290 nrc = region_merge_small(region, edge, nrc, ne, min_size);
291 }
292
293 delete[] edge;
294
295 if ( verbose )
296 cout << "Number of regions: " << nrc << endl << endl;
297
298 int* seg = new int[imagesize];
299
300 for ( nrc=i=0; i<imagesize; i++ )
301 if ( region[i].p == i ) region[i].r = ++nrc;
302
303 for ( i=0; i<imagesize; i++ ) {
304 j = region_find(region, i);
305 seg[i] = region[j].r;
306 }
307
308 delete[] region;
309
310 p->compound_type(TSimple);
311 p->data_type(Integer);
312 p->channels(1);
313
314 p->data_assign((unsigned char *) seg);
315
316 p->statistics();
317
318 return nrc;
319 }
320
Bimage::change_type
void change_type(char letter)
Get the data type indicated by a single letter code.
Definition: Bimage.cpp:1544
statistical_region_merging
size_t statistical_region_merging(Region *region, Edge *edge, size_t nr, size_t ne, double fac)
Definition: img_graphseg.cpp:164
Edge::w
float w
Definition: img_graphseg.h:13
Bimage::sizeZ
void sizeZ(size_t nz)
Definition: Bimage.h:313
QsortSmallToLargeEdge
int QsortSmallToLargeEdge(const void *x, const void *y)
Definition: img_graphseg.cpp:16
Bimage.h
Header file for image class.
region_find
size_t region_find(Region *region, size_t i)
Definition: img_graphseg.cpp:24
region_merging
size_t region_merging(Region *region, Edge *edge, size_t nrc, size_t ne, float threshold)
Definition: img_graphseg.cpp:141
utilities.h
Header file for general utilities.
Bimage::compound_type
CompoundType compound_type()
Definition: Bimage.h:288
region_join
int region_join(Region *region, size_t i, size_t j)
Definition: img_graphseg.cpp:32
Integer
Definition: utilities.h:147
Region::a
float a
Definition: img_graphseg.h:20
Region::p
long p
Definition: img_graphseg.h:17
Bimage::data_delete
void data_delete()
Deallocates the image data.
Definition: Bimage.cpp:645
Bimage::statistics
size_t statistics()
Calculates the statistics for an image.
Definition: Bimage_stats.cpp:22
img_graph_segment
size_t img_graph_segment(int type, Bimage *p, Bimage *pmask, int connect_type, double complexity, int min_size)
Graph-based segmentation of an image.
Definition: img_graphseg.cpp:233
TSimple
Definition: Bimage.h:51
Float
Definition: utilities.h:150
Bimage
General image parameter class.
Definition: Bimage.h:133
Region::s
int s
Definition: img_graphseg.h:19
img_region_setup
Region * img_region_setup(Bimage *p, Bimage *pmask)
Definition: img_graphseg.cpp:56
Bimage::channels
size_t channels()
Definition: Bimage.h:306
Bimage::data_assign
unsigned char * data_assign(unsigned char *nudata)
Assign image data.
Definition: Bimage.cpp:623
Edge::v
size_t v
Definition: img_graphseg.h:12
Region::r
int r
Definition: img_graphseg.h:18
Region
Definition: img_graphseg.h:16
Bimage::standard_deviation
double standard_deviation()
Definition: Bimage.h:446
Edge::u
size_t u
Definition: img_graphseg.h:12
img_edge_setup
Edge * img_edge_setup(Bimage *p, Bimage *pmask, int connect_type, size_t &me, size_t &ne)
Definition: img_graphseg.cpp:78
Bimage::sizeX
void sizeX(size_t nx)
Definition: Bimage.h:311
img_graphseg.h
Header file for segmenting images into density regions using a nondirected graph. ...
Bimage::sizeY
void sizeY(size_t ny)
Definition: Bimage.h:312
verbose
int verbose
region_merge_small
size_t region_merge_small(Region *region, Edge *edge, size_t nrc, size_t ne, int min_size)
Definition: img_graphseg.cpp:191
Bimage::color_to_simple
void color_to_simple()
A color image is converted to a simple image.
Definition: Bimage_color.cpp:94
Edge
Definition: img_graphseg.h:11
Bimage::to_mask
size_t to_mask()
Definition: Bimage.h:956
Bimage::data_type
DataType data_type()
Definition: Bimage.h:286