| 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_mask.cpp
Go to the documentation of this file.
1
9 #include "img_mask.h"
10 #include "img_filter.h"
11 #include "img_combine.h"
12 #include "Complex.h"
13 #include "trigonometry.h"
14 #include "utilities.h"
15
16 // Declaration of global variables
17 extern int verbose; // Level of output to the screen
18
19
31 int img_plane_mask(Bimage* p, Vector3<float> origin, Vector3<float> normal, int operation)
32 {
33 normal.normalize();
34
35 unsigned long i, n, x, y, z, total = 0;
36 unsigned long datasize = p->sizeX()*p->sizeY()*p->sizeZ()*p->images();
37 Vector3<float> point;
38 Bimage* pmask = p->copy_header();
39 pmask->data_type(UCharacter);
40 unsigned char* mask = pmask->data_alloc(datasize);
41
42 if ( verbose & VERB_PROCESS ) {
43 cout << "Generating a planar mask:" << endl;
44 cout << "Normal: " << normal << endl;
45 cout << "Point on plane: " << origin << endl;
46 }
47
48 for ( i=n=0; n<p->images(); n++ ) {
49 for ( z=0; z<p->sizeZ(); z++ ) {
50 point[2] = z - origin.z();
51 for ( y=0; y<p->sizeY(); y++ ) {
52 point[1] = y - origin.y();
53 for ( x=0; x<p->sizeX(); x++, i++ ) {
54 point[0] = x - origin.x();
55 if ( normal.scalar(point) > 0 ) {
56 mask[i] = 1;
57 total++;
58 }
59 }
60 }
61 }
62 }
63
64 p->mask_combine(pmask, operation);
65 delete pmask;
66
67 if ( verbose & VERB_PROCESS )
68 cout << "Number of pixels in mask: " << total << endl << endl;
69
70 return 0;
71 }
72
90 int img_rectangular_mask(Bimage* p, float length, float width,
91 float rect_angle, int wrap, int operation)
92 {
93 if ( !p ) return -1;
94
95 p->change_type(UCharacter) ;
96
97 if ( verbose & ( VERB_LABEL | VERB_PROCESS ) )
98 cout << "Generating a mask along an axis" << endl;
99
100 if ( verbose & VERB_PROCESS ) {
101 cout << "Length and width: " << length << " x " << width << " pixels" << endl;
102 cout << "Axis angle: " << rect_angle*180.0/M_PI << " degrees" << endl;
103 }
104
105 unsigned long i, n, x, y, z, total = 0;
106 double xx, yy, xr, yr;
107 double cos_ang = bcos(rect_angle), sin_ang = bsin(rect_angle);
108 double half_length = length/2.0, half_width = width/2.0;
109 unsigned long datasize = p->data_size();
110 Bimage* pmask = p->copy_header();
111 pmask->data_type(UCharacter);
112 unsigned char* mask = pmask->data_alloc(datasize);
113
114 for ( n=0; n<p->images(); n++ ) {
115 for ( z=0; z<p->sizeZ(); z++ ) {
116 for ( y=0; y<p->sizeY(); y++ ) {
117 yy = y - p->image[n].origin().y();
118 if ( wrap ) if ( yy > (p->sizeY() - 1)/2 ) yy -= p->sizeY();
119 for ( x=0; x<p->sizeX(); x++ ) {
120 xx = x - p->image[n].origin().x();
121 if ( wrap ) if ( xx > (p->sizeX() - 1)/2 ) xx -= p->sizeX();
122 xr = xx*cos_ang + yy*sin_ang;
123 yr = -xx*sin_ang + yy*cos_ang;
124 if ( xr >= -half_length && xr <= half_length &&
125 yr >= -half_width && yr <= half_width ) {
126 // i = ((n*p->sizeZ() + z)*p->sizeY() + y)*p->sizeX() + x;
127 i = p->index(0,x,y,z,n);
128 mask[i] = 1;
129 total++;
130 }
131 }
132 }
133 }
134 }
135
136 p->mask_combine(pmask, operation);
137 delete pmask;
138
139 if ( verbose & VERB_PROCESS )
140 cout << "Number of pixels in mask: " << total << endl << endl;
141
142 return 0;
143 }
144
156 Bimage* img_composite_mask(int nfiles, Bstring* file_list, int mask_type)
157 {
158 if ( !file_list ) return NULL;
159
160 int val, bit, base_bit, base_level, max_level;
161 unsigned long i, j, n, nf;
162 Vector3<double> sampling(1,1,1);
163 Bstring* filename;
164 Bimage* p = NULL;
165 Bimage* pmask = new Bimage;
166
167 for ( nf=0, filename = file_list; filename && nf<nfiles; filename = filename->next, nf++ ) {
168 p = read_img(*filename, 0, -1);
169 if ( p != NULL ) {
170 if ( pmask->sizeX() < p->sizeX() ) pmask->sizeX(p->sizeX());
171 if ( pmask->sizeY() < p->sizeY() ) pmask->sizeY(p->sizeY());
172 if ( pmask->sizeZ() < p->sizeZ() ) pmask->sizeZ(p->sizeZ());
173 if ( pmask->images() < p->images() ) pmask->images(p->images());
174 if ( nf == 0 ) {
175 if ( p->sampling().x() > 0 ) sampling[0] = p->sampling().x();
176 if ( p->sampling().y() > 0 ) sampling[1] = p->sampling().y();
177 if ( p->sampling().z() > 0 ) sampling[2] = p->sampling().z();
178 }
179 delete p;
180 }
181 }
182
183 pmask->sampling(sampling);
184
185 if ( verbose ) {
186 if ( mask_type == 2 )
187 cout << "Generating a multi-bit mask from " << nfiles << " images:" << endl;
188 else
189 cout << "Generating a multi-level mask from " << nfiles << " images:" << endl;
190 }
191
192 if ( verbose & VERB_PROCESS )
193 cout << "New mask size: " << pmask->size() << endl;
194
195 unsigned long imgsize = pmask->sizeX()*pmask->sizeY()*pmask->sizeZ();
196 pmask->data_type(Integer);
197 pmask->data_alloc();
198 pmask->image = new Bsub_image[pmask->images()];
199
200 for ( nf=0, base_bit=0, base_level=max_level=0, filename = file_list; filename && nf<nfiles; filename = filename->next, nf++ ) {
201 p = read_img(*filename, 1, -1);
202 if ( p != NULL ) {
203 if ( verbose & VERB_LABEL )
204 cout << "Adding mask " << nf << endl;
205 p->change_type(Float) ;
206 for ( n=j=0; n<p->images(); n++ ) {
207 pmask->image[n].origin(p->image[n].origin());
208 for ( i=0; i<imgsize; i++, j++ ) {
209 if ( (*p)[j] > 0.5 ) { // What is zero stay whatever it currently is
210 val = (int) ((*p)[j] + 0.5);
211 if ( mask_type == 2 ) {
212 bit = val;
213 if ( base_bit > 0 ) bit <<= base_bit;
214 pmask->set(j, (char)(*pmask)[j] | bit);
215 } else {
216 pmask->set(j, base_level + val);
217 }
218 if ( max_level < (*pmask)[j] ) max_level = (int) (*pmask)[j];
219 }
220 }
221 }
222 delete p;
223 for ( base_bit = 0, val = max_level; val > 0; val >>= 1, base_bit++ ) ;
224 base_level = max_level;
225 }
226 }
227
228 pmask->statistics();
229
230 return pmask;
231 }
232
248 int* img_mask_interface_matrix(Bimage* pmask, int img_num, int* nmat)
249 {
250 pmask->change_type(Integer);
251
252 unsigned long ns = img_num, ne = img_num;
253 if ( img_num < 0 ) {
254 ns = 0;
255 ne = pmask->images() - 1;
256 }
257
258 unsigned long i, j, k, x, y, z, n, xx, yy, zz, m;
259 unsigned long xlo, xhi, ylo, yhi, zlo, zhi;
260 unsigned long imgsize = pmask->sizeX()*pmask->sizeY()*pmask->sizeZ();
261 unsigned long datasize = imgsize*pmask->images();
262
263 for ( i=m=0; i<datasize; i++ ) if ( m < (*pmask)[i] ) m = (unsigned long) (*pmask)[i];
264 m++;
265 *nmat = m;
266
267 int* tmp = new int[m];
268 int* ifmat = new int[m*m];
269
270 for ( j=0; j<m*m; j++ ) ifmat[j] = 0;
271
272 for ( n=ns, i=n*imgsize; n<=ne; n++ ) {
273 for ( z=0; z<pmask->sizeZ(); z++ ) {
274 zlo = (z>0)? z-1: z;
275 zhi = (z<pmask->sizeZ()-1)? z+1: z;
276 for ( y=0; y<pmask->sizeY(); y++ ) {
277 ylo = (y>0)? y-1: y;
278 yhi = (y<pmask->sizeY()-1)? y+1: y;
279 for ( x=0; x<pmask->sizeX(); x++, i++ ) {
280 xlo = (x>0)? x-1: x;
281 xhi = (x<pmask->sizeX()-1)? x+1: x;
282 if ( (*pmask)[i] >= 0 ) {
283 for ( j=0; j<m; j++ ) tmp[j] = 0;
284 for ( zz=zlo; zz<=zhi; zz++ ) {
285 for ( yy=ylo; yy<=yhi; yy++ ) {
286 for ( xx=xlo; xx<=xhi; xx++ ) {
287 // j = ((n*pmask->sizeZ() + zz)*pmask->y + yy)*pmask->x + xx;
288 j = pmask->index(0,xx,yy,zz,n);
289 if ( (*pmask)[i] != (*pmask)[j] && (*pmask)[j] >= 0 )
290 tmp[(int)(*pmask)[j]] = 1;
291 }
292 }
293 }
294 for ( j=0, k=(unsigned long)(*pmask)[i]*m+j; j<m; j++, k++ )
295 if ( tmp[j] ) ifmat[k] += 1;
296 }
297 }
298 }
299 }
300 }
301
302 delete[] tmp;
303
304 return ifmat;
305 }
306
318 int img_mask_region_interfaces(Bimage* pmask, int reg_num)
319 {
320 int i, j, k, l, m, nadj = 0;
321
322 int* ifmat = img_mask_interface_matrix(pmask, 0, &m);
323
324 if ( reg_num >= 0 ) {
325 cout << "Interfaces for region " << reg_num << ":" << endl;
326 cout << "Region\tVin\tVadj" << endl;
327 for ( i=0, k=m*reg_num+i, l=i*m+reg_num; i<m; i++, k++, l+=m ) {
328 cout << i << tab << ifmat[k] << tab << ifmat[l] << endl;
329 if ( i && ifmat[k] ) nadj++;
330 }
331 cout << endl;
332 cout << "Interfaced regions: " << nadj << endl;
333 } else {
334 cout << "Interface matrix:" << endl;
335 // if ( verbose & VERB_FULL ) {
336 cout << "Region";
337 for ( i=0; i<m; i++ ) cout << tab << i;
338 cout << endl;
339 for ( j=0; j<m; j++ ) {
340 cout << j;
341 for ( i=0, k=m*j+i; i<m; i++, k++ ) cout << tab << ifmat[k];
342 cout << endl;
343 }
344 // }
345 }
346 cout << endl;
347
348 delete[] ifmat;
349
350 return 0;
351 }
352
370 int img_mask_merge_delete(Bimage* pmask, int min_size, int min_if)
371 {
372 if ( min_if < 1 ) min_if = 1;
373
374 pmask->change_type(Integer);
375
376 unsigned long i, j, k, l, nm, nd, end, n;
377 unsigned long imgsize = pmask->sizeX()*pmask->sizeY()*pmask->sizeZ();
378 unsigned long datasize = imgsize*pmask->images();
379 int m, imax, max;
380
381 for ( i=m=0; i<datasize; i++ ) if ( m < (*pmask)[i] ) m = (int)(*pmask)[i];
382 m++;
383
384 int* cnt = new int[m];
385 int* map = new int[m];
386 int* ifmat;
387
388 if ( verbose ) {
389 cout << "Eliminating small regions by deletion and merging:" << endl;
390 cout << "Minimum size: " << min_size << " (" << pmask->sampling().volume()*min_size << " A3)" << endl;
391 cout << "Minimum interface area: " << min_if << " (" << pmask->sampling().x()*pmask->sampling().y()*min_if << " A2)" << endl;
392 cout << "Regions: " << m << endl;
393 }
394
395 for ( n=0; n<pmask->images(); n++ ) {
396 ifmat = img_mask_interface_matrix(pmask, n, &m);
397 for ( j=0; j<m; j++ ) cnt[j] = 0;
398 for ( i=n*imgsize, j=i+imgsize; i<j; i++ ) cnt[(int)(*pmask)[i]] += 1;
399 if ( verbose & VERB_FULL ) {
400 cout << "Region";
401 for ( k=1; k<m; k++ ) cout << tab << k;
402 cout << endl;
403 for ( j=1; j<m; j++ ) {
404 cout << j;
405 for ( k=1, l=m*j+k; k<m; k++, l++ ) cout << tab << ifmat[l];
406 cout << endl;
407 }
408 }
409 for ( j=1; j<m; j++ ) { // Find the largest interface for small regions
410 map[j] = j;
411 if ( cnt[j] < min_size ) {
412 max = min_if;
413 if ( max > cnt[j]/2 ) max = cnt[j]/2; // Change the interface cutoff for really small regions
414 if ( max < 1 ) max = 1;
415 for ( k=1, l=m*j+k, imax=0; k<m; k++, l++ ) {
416 if ( max <= ifmat[l] ) {
417 max = ifmat[l];
418 imax = k;
419 }
420 }
421 map[j] = imax;
422 }
423 }
424 delete[] ifmat;
425 if ( verbose & VERB_FULL ) {
426 cout << "Region\tPointer" << endl;
427 for ( j=1; j<m; j++ ) cout << j << tab << map[j] << endl;
428 }
429 for ( j=1; j<m; j++ ) if ( map[j] != j ) { // Resolve linked references
430 for ( k=1, cnt[0] = j, end=0; k<m && end==0; k++ ) {
431 cnt[k] = map[cnt[k-1]];
432 for ( l=0; l<k && cnt[k] != cnt[l]; l++ ) ; // Detect loops and self-reference
433 if ( l < k ) { // Set new references
434 end = cnt[k];
435 for ( l=0; l<k; l++ ) map[cnt[l]] = end;
436 }
437 }
438 }
439 for ( j=1, nm=nd=0; j<m; j++ ) { // Re-assign small regions
440 if ( map[j] != j ) {
441 if ( map[j] < 1 ) nd++;
442 for ( k=0, l=n*imgsize; k<imgsize; k++, l++ )
443 if ( (int)(*pmask)[l] == j ) pmask->set(l, map[j]);
444 if ( verbose & VERB_FULL )
445 cout << j << " -> " << map[j] << endl;
446 } else nm++;
447 }
448 }
449
450 if ( verbose ) {
451 cout << "New regions: " << nm << endl;
452 cout << "Regions deleted: " << nd << endl << endl;
453 }
454
455 delete[] cnt;
456 delete[] map;
457
458 return 0;
459 }
460
Bimage::change_type
void change_type(char letter)
Get the data type indicated by a single letter code.
Definition: Bimage.cpp:1438
Vector3::z
Type z()
Definition: Vector3.h:141
Bimage::sizeZ
void sizeZ(size_t nz)
Definition: Bimage.h:330
Bimage::copy_header
Bimage * copy_header()
Definition: Bimage.h:502
img_mask_interface_matrix
int * img_mask_interface_matrix(Bimage *pmask, int img_num, int *nmat)
Calculates the interfaces between regions.
Definition: img_mask.cpp:248
bcos
double bcos(double x)
Avoid non-zero values for cos(PI/2) and cos(-PI/2).
Definition: trigonometry.cpp:27
Bsub_image
General sub-image parameter class.
Definition: Bimage.h:100
utilities.h
Header file for general utilities.
img_mask.h
Header file for mask operation tools.
img_mask_merge_delete
int img_mask_merge_delete(Bimage *pmask, int min_size, int min_if)
Calculates the interfaces between regions and deletes/merges small ones.
Definition: img_mask.cpp:370
Complex.h
Class for complex numbers.
img_rectangular_mask
int img_rectangular_mask(Bimage *p, float length, float width, float rect_angle, int wrap, int operation)
Generates a mask along an axis within a 2D image.
Definition: img_mask.cpp:90
Float
Definition: Bimage.h:60
Vector3< float >
VERB_PROCESS
#define VERB_PROCESS
Definition: utilities.h:99
Bimage::index
size_t index(size_t nx, size_t ny)
Definition: Bimage.h:334
Bimage::statistics
size_t statistics()
Calculates the statistics for an image.
Definition: Bimage_stats.cpp:22
bsin
double bsin(double x)
Avoid non-zero values for sin(PI) and sin(-PI).
Definition: trigonometry.cpp:48
Bimage
General image parameter class.
Definition: Bimage.h:153
UCharacter
Definition: Bimage.h:52
Bimage::data_alloc
unsigned char * data_alloc()
Definition: Bimage.h:227
M_PI
#define M_PI
Definition: utilities.h:51
read_img
Bimage * read_img(const char *filename, int readdata, int img_select)
General driver function to read multiple image formats.
Definition: rwimg.cpp:75
Bstring::next
Bstring * next
Definition: Bstring.h:27
Bimage::sampling
void sampling(double s)
Definition: Bimage.h:412
img_filter.h
Header file for image utilities.
img_combine.h
Header file for combining two images in various ways.
Vector3::scalar
double scalar(const Vector3 &v) const
Definition: Vector3.h:219
Vector3::x
Type x()
Definition: Vector3.h:139
img_plane_mask
int img_plane_mask(Bimage *p, Vector3< float > origin, Vector3< float > normal, int operation)
Generates a mask on one side of a plane.
Definition: img_mask.cpp:31
val
int val
Definition: jpeglib.h:956
trigonometry.h
Header file for trigonometry functions.
Bimage::size
Vector3< size_t > size()
Definition: Bimage.h:325
Bsub_image::origin
void origin(double x, double y, double z)
Definition: Bimage.h:133
Bimage::set
void set(size_t j, double v)
Sets a single value at the given index.
Definition: Bimage.cpp:915
verbose
int verbose
Bimage::mask_combine
size_t mask_combine(Bimage *p, int operation)
Combines two masks with different operations.
Definition: Bimage_mask.cpp:219
Bimage::images
size_t images()
Definition: Bimage.h:410
Bimage::data_size
size_t data_size()
Definition: Bimage.h:226
Integer
Definition: Bimage.h:57
Bstring
Definition: Bstring.h:25
Bimage::sizeX
void sizeX(size_t nx)
Definition: Bimage.h:328
img_mask_region_interfaces
int img_mask_region_interfaces(Bimage *pmask, int reg_num)
Reports the whole interface matrix or interfaces for one region only.
Definition: img_mask.cpp:318
Vector3::normalize
double normalize()
Definition: Vector3.h:208
Bimage::sizeY
void sizeY(size_t ny)
Definition: Bimage.h:329
img_composite_mask
Bimage * img_composite_mask(int nfiles, Bstring *file_list, int mask_type)
Generates a composite of multiple masks.
Definition: img_mask.cpp:156
VERB_FULL
#define VERB_FULL
Definition: utilities.h:101
VERB_LABEL
#define VERB_LABEL
Definition: utilities.h:98
Bimage::data_type
DataType data_type()
Definition: Bimage.h:303
Vector3::y
Type y()
Definition: Vector3.h:140
tab
ostream & tab(ostream &out)
Definition: utilities.cpp:21
Bimage::image
Bsub_image * image
Definition: Bimage.h:184