| 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_segment.cpp
Go to the documentation of this file.
1
9 #include "rwimg.h"
10 #include "img_segment.h"
11 #include "img_feature.h"
12 #include "img_combine.h"
13 #include "linked_list.h"
14 #include "utilities.h"
15
16 // Declaration of global variables
17 extern int verbose; // Level of output to the screen
18
37 int img_blobs(Bimage* p, float threshold, float min_size, float max_size, float setvalue, int sign)
38 {
39 if ( min_size > max_size ) swap(min_size, max_size);
40
41 if ( sign < 0 ) sign = -1;
42 else if ( sign > 0 ) sign = 1;
43 else {
44 sign = 1;
45 if ( threshold < p->average() ) sign = -1;
46 }
47
48 p->change_type(Float) ;
49
50 if ( verbose & ( VERB_LABEL | VERB_PROCESS ) ) {
51 if ( sign > 0 )
52 cout << "Finding blobs above " << threshold << endl;
53 else
54 cout << "Finding blobs below " << threshold << endl;
55 }
56
57 if ( verbose & VERB_PROCESS ) {
58 cout << "Size range to keep: " << min_size << " - " << max_size << endl;
59 cout << "Set value: " << setvalue << endl << endl;
60 }
61
62 Bimage* pfeature = img_find_features(p, threshold, sign, 0);
63 int count = (int) pfeature->maximum();
64
65 unsigned long i, f, nvox = 0, nblobs = 0;
66 unsigned long datasize = p->sizeX()*p->sizeY()*p->sizeZ()*p->images();
67
68 int* feature_size = new int[count+1];
69
70 for ( i=0; i<=count; i++ ) feature_size[i] = 0;
71
72 for ( i=0; i<datasize; i++ ) feature_size[(long)(*pfeature)[i]]++;
73
74 if ( verbose & VERB_PROCESS ) {
75 cout << "Feature\tSize" << endl;
76 for ( i=0; i<=count; i++ ) {
77 cout << i << tab << feature_size[i];
78 if ( (i+1)%5 == 0 ) cout << endl;
79 }
80 cout << endl;
81 }
82
83 if ( ( min_size > 0 ) || ( max_size < datasize ) ) {
84 for ( i=1; i<=count; i++ )
85 if ( feature_size[i] < min_size || feature_size[i] > max_size ) nblobs++;
86
87 for ( i=0; i<datasize; i++ ) {
88 f = (long)(*pfeature)[i];
89 if ( f > 0 ) {
90 if ( ( feature_size[f] < min_size ) || ( feature_size[f] > max_size ) ) {
91 p->set(i, setvalue);
92 nvox++;
93 }
94 }
95 }
96 }
97
98 if ( verbose & VERB_PROCESS ) {
99 cout << "Number of blobs deleted: " << nblobs << endl;
100 cout << "Number of voxels set: " << nvox << endl << endl;
101 }
102
103 delete[] feature_size;
104
105 // write_img("pf.pif", pfeature);
106
107 delete pfeature;
108
109 p->statistics();
110
111 return nvox;
112 }
113
127 float img_find_threshold(Bimage* p, int img_num, double mol_weight, float rho)
128 {
129 p->change_type(Float) ;
130
131 if ( rho <= 0 ) rho = RHO;
132
133 unsigned long img_start = 0, img_end = p->images() - 1;
134
135 if ( img_num >= 0 ) img_start = img_end = img_num;
136
137 unsigned long i, j, n, nvox = 0;
138 long dnvox = -1;
139 unsigned long imgsize = p->sizeX()*p->sizeY()*p->sizeZ();
140 double voxel_size = 1;
141 if ( p->sizeX() > 1 ) voxel_size *= p->sampling().x();
142 if ( p->sizeY() > 1 ) voxel_size *= p->sampling().y();
143 if ( p->sizeZ() > 1 ) voxel_size *= p->sampling().z();
144
145 double mass, dmass;
146 double volume = mol_weight/rho;
147 double threshold;
148 double thresh_step;
149 double vol_diff;
150 double min_vol = voxel_size;
151 double min_step = 1e-6*p->standard_deviation();
152
153 if ( verbose & VERB_LABEL ) {
154 cout << "Finding the threshold for image " << img_num+1 << ":" << endl;
155 cout << "Protein density: " << rho << " Da/A3" << endl;
156 cout << "Molecular weight: " << mol_weight << " Da" << endl;
157 cout << "Molecular volume: " << volume << " A3" << endl;
158 cout << "Voxel size: " << voxel_size << " A3" << endl << endl;
159 }
160
161 if ( verbose )
162 cout << "Image\tThresh\tVolRes\tIntMass\tMW/mass" << endl;
163 for ( n=img_start; n<=img_end; n++ ) {
164 if ( verbose & VERB_FULL )
165 cout << " Threshold\tThreshStep\tVolume(A3)\tDifference\tMass" << endl;
166 threshold = p->average();
167 thresh_step = p->standard_deviation()/2;
168 nvox = 0;
169 mass = 0;
170 vol_diff = 1e30;
171 while ( fabs(vol_diff) >= min_vol && fabs(thresh_step) > min_step ) {
172 dnvox = nvox;
173 dmass = mass;
174 if ( vol_diff > 0 ) {
175 if ( thresh_step < 0 ) thresh_step *= -0.5;
176 } else {
177 if ( thresh_step > 0 ) thresh_step *= -0.5;
178 }
179 threshold += thresh_step;
180 for ( i=n*imgsize, j=i+imgsize, nvox = 0, mass = 0; i<j; i++ ) {
181 if ( (*p)[i] >= threshold ) {
182 nvox++;
183 mass += (*p)[i];
184 }
185 }
186 vol_diff = nvox*voxel_size - volume;
187 if ( verbose & VERB_FULL )
188 cout << threshold << tab << thresh_step << tab
189 << nvox*voxel_size << tab << vol_diff << tab << mass << endl;
190 dnvox = nvox - dnvox;
191 dmass = mass - dmass;
192 }
193 if ( verbose )
194 cout << n+1 << tab << threshold << tab <<
195 fabs(vol_diff)/volume << tab << mass << tab << mol_weight/mass << endl;
196 }
197 if ( verbose )
198 cout << endl;
199
200 /*
201 if ( verbose & VERB_LABEL ) {
202 cout << "Threshold: " << threshold << endl;
203 cout << "Relative volume residual: " << fabs(vol_diff)/volume << endl;
204 cout << "Integrated mass: " << mass << endl;
205 cout << "Molecular weight/mass: " << mol_weight/mass << endl << endl;
206 }
207 */
208 return threshold;
209 }
210
222 float img_mass_at_threshold(Bimage* p, int img_num, float threshold, float rho)
223 {
224 p->change_type(Float) ;
225
226 if ( rho <= 0 ) rho = RHO;
227
228 unsigned long i, j, nvox;
229 unsigned long imgsize = p->sizeX()*p->sizeY()*p->sizeZ();
230
231 for ( i=img_num*imgsize, j=i+imgsize, nvox=0; i<j; i++ )
232 if ( (*p)[i] >= threshold ) nvox++;
233
234 double voxel_size = 1;
235 if ( p->sizeX() > 1 ) voxel_size *= p->sampling().x();
236 if ( p->sizeY() > 1 ) voxel_size *= p->sampling().y();
237 if ( p->sizeZ() > 1 ) voxel_size *= p->sampling().z();
238
239 double volume = nvox*voxel_size;
240 double mass = volume*rho;
241
242 if ( verbose & VERB_LABEL ) {
243 cout << "Protein density: " << rho << " Da/A3" << endl;
244 cout << "Threshold: " << threshold << endl;
245 cout << "Volume: " << volume << " A3" << endl;
246 cout << "Molecular weight: " << mass << " Da" << endl << endl;
247 }
248
249 return mass;
250 }
251
264 int img_internal_volume(Bimage* p, float threshold, int mask_out_freq)
265 {
266 unsigned long i, j, jn, jz, jy, x, y, z, n;
267 unsigned long xx, yy, zz, xlo, xhi, ylo, yhi, zlo, zhi;
268 Vector3<unsigned long> min, max, min2, max2;
269 unsigned long iter, dvol, vol;
270 unsigned long slicesize = p->sizeX()*p->sizeY();
271 unsigned long imagesize = p->sizeX()*p->sizeY()*p->sizeZ();
272 double voxel_size = p->sampling().volume();
273
274 Bstring filename;
275
276 int nb, nbcut = 6, sign = 1;
277 if ( p->sizeZ() < 2 ) nbcut = 2;
278 if ( threshold < p->average() ) sign = -1;
279
280 p->change_type(Float) ;
281
282 float* fom = p->FOM_initialize();
283
284 for ( n=0; n<p->images(); n++ ) {
285 jn = n*imagesize;
286 x = (int) (p->image[n].origin().x() + 0.5);
287 y = (int) (p->image[n].origin().y() + 0.5);
288 z = (int) (p->image[n].origin().z() + 0.5);
289 min = max = Vector3<unsigned long>(x, y, z);
290 if ( min.x() > 0 ) min[0]--;
291 if ( max.x() < p->sizeX() - 1 ) max[0]++;
292 if ( min.y() > 0 ) min[1]--;
293 if ( max.y() < p->sizeY() - 1 ) max[1]++;
294 if ( min.z() > 0 ) min[2]--;
295 if ( max.z() < p->sizeZ() - 1 ) max[2]++;
296 // i = ((n*p->z + z)*p->y + y)*p->x + x;
297 i = p->index(0,x,y,z,n);
298 fom[i] = 2;
299 dvol = vol = 1;
300 if ( verbose ) {
301 cout << "Image " << n+1 << ":" << endl;
302 cout << "Origin: " << p->image[n].origin() << endl;
303 cout << "Iter\tVol\tdVol\tVol(A3)\tdVol(A3)" << endl;
304 }
305 iter = 0;
306 while ( dvol > 0 ) {
307 dvol = 0;
308 iter++;
309 for ( z=min.z(); z<=max.z(); z++ ) {
310 zlo = ( z > 0 )? z-1: z;
311 zhi = ( z < p->sizeZ()-1 )? z+1: z;
312 for ( y=min.y(); y<=max.y(); y++ ) {
313 ylo = ( y > 0 )? y-1: y;
314 yhi = ( y < p->sizeY()-1 )? y+1: y;
315 for ( x=min.x(); x<=max.x(); x++ ) {
316 xlo = ( x > 0 )? x-1: x;
317 xhi = ( x < p->sizeX()-1 )? x+1: x;
318 // i = ((n*p->z + z)*p->y + y)*p->x + x;
319 i = p->index(0,x,y,z,n);
320 nb = 0;
321 if ( fom[i] < 1 && sign*(*p)[i] <= threshold ) {
322 jz = jn + zlo*slicesize;
323 for ( zz=zlo; zz<=zhi; zz++, jz += slicesize ) {
324 jy = jz + ylo*p->sizeX();
325 for ( yy=ylo; yy<=yhi; yy++, jy += p->sizeX() ) {
326 j = jy + xlo;
327 for ( xx=xlo; xx<=xhi; xx++, j++ ) {
328 if ( i != j && fom[j] > 1 ) nb++;
329 }
330 }
331 }
332 if ( ( nb >= vol ) || ( nb > nbcut ) ) {
333 fom[i] = 1;
334 dvol++;
335 } else fom[i] = 0;
336 }
337 }
338 }
339 }
340 min2 = min;
341 max2 = max;
342 for ( z=min2.z(); z<=max2.z(); z++ ) {
343 for ( y=min2.y(); y<=max2.y(); y++ ) {
344 for ( x=min2.x(); x<=max2.x(); x++ ) {
345 // i = ((n*p->z + z)*p->y + y)*p->x + x;
346 i = p->index(0,x,y,z,n);
347 if ( fom[i] == 1 ) {
348 fom[i] = 2;
349 if ( min.x() == x && x > 0 ) min[0]--;
350 if ( min.y() == y && y > 0 ) min[1]--;
351 if ( min.z() == z && z > 0 ) min[2]--;
352 if ( max.x() == x && x < p->sizeX() - 1 ) max[0]++;
353 if ( max.y() == y && y < p->sizeY() - 1 ) max[1]++;
354 if ( max.z() == z && z < p->sizeZ() - 1 ) max[2]++;
355 }
356 }
357 }
358 }
359 vol += dvol;
360 if ( verbose )
361 cout << iter << tab << vol << tab << dvol << tab
362 << vol*voxel_size << tab << dvol*voxel_size << endl;
363 if ( mask_out_freq > 0 && iter%mask_out_freq == 0 ) {
364 if ( p->images() == 1 ) filename = Bstring(iter, "v%04ld.map");
365 else filename = Bstring(n, "v%02ld") + Bstring(iter, "_%04ld.map");
366 write_fom_as_image(filename, p);
367 }
368 }
369 }
370
371 return 0;
372 }
373
382 int img_segment_threshold_series(Bimage* p, float threshold_first,
383 float threshold_last, float threshold_step)
384 {
385 int sign = 1;
386 double threshold, a(0);
387 Bimage* pfeat;
388
389 if ( threshold_step == 0 ) {
390 if ( threshold_last == threshold_first )
391 threshold_step = 1;
392 else
393 threshold_step = threshold_last - threshold_first;
394 } else {
395 if ( threshold_step > 0 && threshold_first > threshold_last )
396 threshold_step = -threshold_step;
397 if ( threshold_step < 0 && threshold_first < threshold_last )
398 threshold_step = -threshold_step;
399 }
400
401 if ( threshold_step < 0 ) sign = -1;
402 threshold_last += threshold_step/2;
403
404 cout << "Finding the number of regions at each threshold:" << endl;
405 cout << "Thresh\tRegions\tAvgSize" << endl;
406 for ( threshold = threshold_first; sign*threshold <= sign*threshold_last;
407 threshold+=threshold_step ) {
408 pfeat = img_find_features(p, threshold, 0, 0);
409 a = img_average_feature_size(pfeat);
410 cout << threshold << tab << pfeat->maximum() << tab << a << endl;
411 delete pfeat;
412 }
413 cout << endl;
414
415 return 0;
416 }
417
418
439 Bimage* img_flood_fill(Bimage* p, Bimage* pfeature, float threshold_hi,
440 float threshold_lo, float threshold_step, int fill_borders)
441 {
442 if ( !pfeature ) {
443 error_show("No feature mask in img_flood_fill", __FILE__, __LINE__);
444 return NULL;
445 }
446
447 unsigned long i;
448
449 // The extreme considered as a feature depends on the sign of the threshold
450 int sign = 1;
451 if ( threshold_hi < p->average() ) sign = -1;
452 if ( fabs(threshold_hi-p->average()) < fabs(threshold_lo-p->average()) )
453 swap(threshold_hi, threshold_lo);
454 double threshold;
455 if ( threshold_step == 0 )
456 threshold_step = (threshold_lo - threshold_hi)/100;
457 else if ( (threshold_lo - threshold_hi)/threshold_step < 0 )
458 threshold_step *= -1;
459 double abs_threshold = sign*threshold_hi;
460 double abs_threshold_lo = sign*threshold_lo;
461
462 if ( verbose & VERB_LABEL ) {
463 cout << "Segmenting an image by flooding from a threshold or feature set:" << endl;
464 if ( pfeature )
465 cout << "Feature set: " << pfeature->file_name() << endl;
466 cout << "Starting threshold: " << threshold_hi << endl;
467 cout << "Finishing threshold: " << threshold_lo << endl;
468 cout << "Threshold step: " << threshold_step << endl << endl;
469 }
470
471 // if ( !pfeature )
472 // pfeature = img_find_features(p, threshold_hi, 0, 0);
473 // else
474 // img_set_second_mask(p, pfeature, threshold_hi);
475
476 if ( !p->check_if_same_size(pfeature) ) {
477 error_show("Error in img_flood_fill", __FILE__, __LINE__);
478 cerr << "The feature mask must have the same dimensions as the image!" << endl;
479 return NULL;
480 }
481
482 if ( pfeature->data_type() != Integer ) {
483 if ( pfeature->data_type() > Integer )
484 cerr << "Warning: The feature mask must of integer type!" << endl;
485 pfeature->change_type(Integer);
486 }
487
488 if ( verbose & VERB_LABEL )
489 cout << "Regions: " << pfeature->maximum() << endl;
490
491 Bimage* pmask = pfeature->copy();
492
493 unsigned long datasize = p->sizeX()*p->sizeY()*p->sizeZ()*p->images();
494
495 // Progressively decrease threshold and find new adjacent voxels belonging to
496 // each feature - disputes over voxel assignment are settled later
497 for ( threshold=threshold_hi; abs_threshold>abs_threshold_lo; threshold+=threshold_step ) {
498 abs_threshold = sign*threshold;
499 if ( verbose & VERB_PROCESS )
500 cout << "Processing threshold: " << threshold << " (" << 100*(threshold - threshold_hi)/(threshold_lo - threshold_hi) << " %) \r" << flush;
501
502 #ifdef HAVE_GCD
503 dispatch_apply(datasize, dispatch_get_global_queue(0, 0), ^(size_t it){
504 if ( sign*(*p)[it] > abs_threshold )
505 pmask->set(it, img_check_neighbors(pfeature, it));
506 else
507 pmask->set(it, 0);
508 });
509 #else
510 #pragma omp parallel for
511 for ( long it=0; it<datasize; it++ ) {
512 if ( sign*(*p)[it] > abs_threshold )
513 pmask->set(it, img_check_neighbors(pfeature, it));
514 else
515 pmask->set(it, 0);
516 }
517 #endif
518 for ( i=0; i<datasize; i++ ) pfeature->set(i, (*pmask)[i]);
519 }
520
521 if ( verbose & VERB_PROCESS )
522 cout << endl;
523
524 unsigned long nborder = 0;
525 int maxtries = 20;
526
527 for ( i=0; i<datasize; i++ ) if ( (*pmask)[i] < 0 ) nborder++;
528 if ( verbose & VERB_LABEL )
529 cout << "Border voxels: " << nborder << endl;
530
531 // Assign the borders between features to one of the features
532 if ( fill_borders ) {
533 if ( verbose & VERB_PROCESS )
534 cout << "Assigning borders:" << endl;
535
536 while ( maxtries-- > 0 && nborder > 0 ) {
537 nborder = 0;
538
539 #ifdef HAVE_GCD
540 dispatch_apply(datasize, dispatch_get_global_queue(0, 0), ^(size_t it){
541 if ( (*pmask)[it] < 0 ) {
542 unsigned long j = img_find_highest_in_kernel(p, it, 1);
543 pmask->set(it, (*pmask)[j]);
544 if ( (*pmask)[it] < 0 ) {
545 j = img_find_highest_in_kernel(p, it, 2);
546 pmask->set(it, (*pmask)[j]);
547 }
548 }
549 });
550 #else
551 #pragma omp parallel for
552 for ( long it=0; it<datasize; it++ ) {
553 if ( (*pmask)[it] < 0 ) {
554 unsigned long j = img_find_highest_in_kernel(p, it, 1);
555 pmask->set(it, (*pmask)[j]);
556 if ( (*pmask)[it] < 0 ) {
557 j = img_find_highest_in_kernel(p, it, 2);
558 pmask->set(it, (*pmask)[j]);
559 }
560 }
561 }
562 #endif
563 for ( long it=0; it<datasize; it++ ) if ( (*pmask)[it] < 0 ) nborder++;
564
565 }
566
567 if ( verbose && nborder > 0 )
568 cerr << "Warning: " << nborder << " border voxels were not assigned!" << endl << endl;
569 }
570
571 unsigned long nseg = (unsigned long)(pfeature->maximum() + 1.9);
572 int* vol;
573
574 if ( verbose & VERB_FULL ) {
575 vol = new int[nseg];
576 for ( i=0; i<nseg; i++ ) vol[i] = 0;
577 for ( i=0; i<datasize; i++ )
578 if ( (*pmask)[i] > -1 ) vol[(long)(*pmask)[i]]++;
579 cout << "Region\tVoxels\tVolume\tMass" << endl;
580 for ( i=1; i<nseg; i++ )
581 cout << i << tab << vol[i] << tab << vol[i]*p->sampling().volume()
582 << tab << vol[i]*p->sampling().volume()*RHO << endl;
583 delete[] vol;
584 }
585
586 if ( verbose )
587 cout << endl;
588
589 if ( verbose & VERB_DEBUG )
590 cout << "DEBUG img_flood_fill: Finished with segmentation" << endl;
591
592 return pmask;
593 }
594
612 Bimage* img_flood_peaks(Bimage* p, int kernel_size, float threshold)
613 {
614 if ( kernel_size < 3 ) kernel_size = 3;
615
616 p->change_type(Float) ;
617
618 unsigned long i, j, imax, x, y, z, n, xx, yy, zz, dn;
619 unsigned long hk = kernel_size/2, xlo, xhi, ylo, yhi, zlo, zhi, npeak = 0;
620 unsigned long datasize = p->sizeX()*p->sizeY()*p->sizeZ()*p->images();
621 double dmax;
622
623 if ( verbose & VERB_LABEL ) {
624 cout << "Segmenting an image by flooding from peaks:" << endl;
625 cout << "Kernel size: " << 2*hk+1 << endl;
626 cout << "Threshold: " << threshold << endl;
627 }
628
629 Bimage* pmask = new Bimage(Integer, TSimple, p->sizeX(), p->sizeY(), p->sizeZ(), p->images());
630 pmask->sampling(p->sampling());
631 for ( n=0; n<p->images(); n++ ) pmask->image[n] = p->image[n];
632
633 int* pnt = new int[datasize];
634
635 for ( i=n=0; n<p->images(); n++ ) {
636 for ( z=0; z<p->sizeZ(); z++ ) {
637 zlo = (z>hk)? z-hk: 0;
638 zhi = (z<p->sizeZ()-hk)? z+hk: p->sizeZ()-1;
639 for ( y=0; y<p->sizeY(); y++ ) {
640 ylo = (y>hk)? y-hk: 0;
641 yhi = (y<p->sizeY()-hk)? y+hk: p->sizeY()-1;
642 for ( x=0; x<p->sizeX(); x++, i++ ) {
643 xlo = (x>hk)? x-hk: 0;
644 xhi = (x<p->sizeX()-hk)? x+hk: p->sizeX()-1;
645 pnt[i] = 0;
646 if ( (*p)[i] >= threshold ) {
647 imax = i;
648 dmax = (*p)[i];
649 for ( zz=zlo; zz<=zhi; zz++ ) {
650 for ( yy=ylo; yy<=yhi; yy++ ) {
651 for ( xx=xlo; xx<=xhi; xx++ ) {
652 // j = ((n*p->z + zz)*p->y + yy)*p->x + xx;
653 j = p->index(0,xx,yy,zz,n);
654 if ( dmax < (*p)[j] ) {
655 dmax = (*p)[j];
656 imax = j;
657 }
658 }
659 }
660 }
661 pnt[i] = imax;
662 if ( pnt[i] == i ) pmask->set(i, ++npeak);
663 }
664 }
665 }
666 }
667 }
668
669 n = 0;
670 dn = 1;
671 while ( dn ) {
672 dn = n;
673 for ( i=0; i<datasize; i ++ ) if ( (*p)[i] >= threshold && (*pmask)[i] < 1 ) {
674 pmask->set(i, (*pmask)[pnt[i]]);
675 }
676 for ( i=n=0; i<datasize; i ++ ) if ( (*pmask)[i] > 0 ) n++;
677 dn = n - dn;
678 }
679
680 delete pnt;
681
682 pmask->maximum(npeak);
683
684 if ( verbose & VERB_LABEL )
685 cout << "Number of peaks: " << npeak << endl << endl;
686
687 return pmask;
688 }
689
701 int img_set_second_mask(Bimage* p, Bimage* pmask, float threshold)
702 {
703 p->change_type(Float) ;
704
705 if ( pmask->data_type() != Integer ) {
706 if ( pmask->data_type() > Integer )
707 cerr << "Warning: The mask must of integer type!" << endl;
708 pmask->change_type(Integer);
709 }
710
711 unsigned long i, mval = (unsigned long) (pmask->maximum() + 1.5);
712 unsigned long datasize = p->sizeX()*p->sizeY()*p->sizeZ()*p->images();
713
714 for ( i=0; i<datasize; i++ )
715 if ( (*pmask)[i] < 1 && (*p)[i] >= threshold ) pmask->set(i, mval);
716
717 pmask->statistics();
718
719 return 0;
720 }
721
731 int img_check_neighbors(Bimage* p, unsigned long index)
732 {
733 // unsigned long* voxel = img_find_voxel_from_index(p, index);
734 // long x(voxel[0]), y(voxel[1]), z(voxel[2]), n(voxel[3]);
735
736 // delete[] voxel;
737
738 if ( (*p)[index] != 0 ) return (int)(*p)[index];
739
740 unsigned long x, y, z, n;
741 p->coordinates(index, x, y, z, n);
742
743 // Calculate the new size and set up
744 unsigned long i;
745 long zlo, zhi, ylo, yhi, xlo, xhi;
746 long nv = 0;
747
748 //calculate the bounds on the kernel
749 zlo = z - 1;
750 if ( zlo < 0 ) zlo = 0;
751 zhi = z + 1;
752 if ( zhi >= p->sizeZ() ) zhi = p->sizeZ() - 1;
753 ylo = y - 1;
754 if ( ylo < 0 ) ylo = 0;
755 yhi = y + 1;
756 if ( yhi >= p->sizeY() ) yhi = p->sizeY() - 1;
757 xlo = x - 1;
758 if ( xlo < 0 ) xlo = 0;
759 xhi = x + 1;
760 if ( xhi >= p->sizeX() ) xhi = p->sizeX() - 1;
761
762 // Loop through the kernel and check neighbors
763 for ( z=zlo; z<=zhi; z++ ) {
764 for ( y=ylo; y<=yhi; y++ ) {
765 for ( x=xlo; x<=xhi; x++ ) {
766 // i = ((n*p->z + z)*p->y + y)*p->x + x;
767 i = p->index(0,x,y,z,n);
768 if ( i != index ) {
769 if ( (*p)[i] > 0 ) {
770 if ( nv == 0 )
771 nv = (long)(*p)[i];
772 else if ( nv != (*p)[i] )
773 nv = -100; // Border voxel
774 }
775 }
776 }
777 }
778 }
779
780 if ( verbose & VERB_DEBUG )
781 cout << "DEBUG img_check_neighbors: Ending with feature " << (int)(*p)[index] << endl;
782
783 return nv;
784 }
785
796 long img_find_highest_in_kernel(Bimage* p, unsigned long index, int size)
797 {
798 unsigned long x, y, z, n;
799 p->coordinates(index, x, y, z, n);
800
801 unsigned long i, ihi(index);
802 long zlo, zhi, ylo, yhi, xlo, xhi;
803 double max_val(-1e30);
804
805 //calculate the bounds on the kernel
806 zlo = z - size;
807 if ( zlo < 0 ) zlo = 0;
808 zhi = z + size;
809 if ( zhi >= p->sizeZ() ) zhi = p->sizeZ() - 1;
810 ylo = y - size;
811 if ( ylo < 0 ) ylo = 0;
812 yhi = y + size;
813 if ( yhi >= p->sizeY() ) yhi = p->sizeY() - 1;
814 xlo = x - size;
815 if ( xlo < 0 ) xlo = 0;
816 xhi = x + size;
817 if ( xhi >= p->sizeX() ) xhi = p->sizeX() - 1;
818
819 // Loop through the kernel and check neighbors
820 for ( z=zlo; z<=zhi; z++ ) {
821 for ( y=ylo; y<=yhi; y++ ) {
822 for ( x=xlo; x<=xhi; x++ ) {
823 i = p->index(0,x,y,z,n);
824 if ( max_val < (*p)[i] ) {
825 if ( i != index ) {
826 max_val = (*p)[i];
827 ihi = i;
828 }
829 }
830 }
831 }
832 }
833
834 return ihi;
835 }
836
850 Bimage* img_excise_feature(Bimage* p, Bimage* pfeature, Bmarker* markers)
851 {
852 unsigned long nmark = count_list((char *) markers);
853
854 if ( nmark < 1 ) return NULL;
855
856 p->change_type(Float) ;
857
858 unsigned long i, j, k, ivoxel, n;
859 long* index = new long[nmark];
860
861 if ( verbose & ( VERB_LABEL | VERB_PROCESS ) ) {
862 if ( nmark == 1 )
863 cout << "Excising 1 feature:" << endl;
864 else
865 cout << "Excising " << nmark << " features:" << endl;
866 }
867
868 if ( verbose & VERB_PROCESS )
869 cout << "x\ty\tz\tn\tIndex\tValue" << endl;
870
871 Bmarker* mark;
872
873 for ( j=0, mark=markers; mark; mark=mark->next, j++ ) {
874 ivoxel = (unsigned long) (((mark->img_num*p->sizeZ() + mark->loc.z())*p->sizeY() +
875 mark->loc.y())*p->sizeX() + mark->loc.x());
876 index[j] = (long)(*pfeature)[ivoxel];
877 if ( verbose & VERB_PROCESS )
878 cout << mark->loc.x() << tab << mark->loc.y() << tab <<
879 mark->loc.z() << tab << mark->img_num << tab <<
880 index[j] << tab << (*p)[ivoxel] << endl;
881 }
882 cout << endl;
883
884 unsigned long max_ind(0), nvox(0);
885 unsigned long imgsize = p->sizeX()*p->sizeY()*p->sizeZ();
886 double max = -1e30;
887 double voxel_size = 1;
888 if ( p->sizeX() > 1 ) voxel_size *= p->sampling().x();
889 if ( p->sizeY() > 1 ) voxel_size *= p->sampling().y();
890 if ( p->sizeZ() > 1 ) voxel_size *= p->sampling().z();
891
892 Bimage* pex = p->copy_header();
893 pex->data_alloc();
894
895 for ( i=n=0; i<p->images(); n++ ) {
896 for ( k=0; k<imgsize; k++, i++ ) {
897 if ( (*pfeature)[i] > 0 ) {
898 for ( j=0; j<nmark && (*pfeature)[i] != index[j]; j++ ) ;
899 if ( j < nmark && (*pfeature)[i] == index[j] ) {
900 pex->set(i, (*p)[i]);
901 if ( max < (*p)[i] ) {
902 max = (*p)[i];
903 max_ind = i;
904 }
905 p->set(i, p->image[n].background());
906 nvox++;
907 }
908 }
909 }
910 }
911
912 pex->statistics();
913
914 // unsigned long* max_vox = img_find_voxel_from_index(p, max_ind);
915 unsigned long x, y, z;
916 p->coordinates(max_ind, x, y, z, n);
917
918 if ( verbose & VERB_LABEL ) {
919 cout << "Voxels: " << nvox << endl;
920 cout << "Maximum: " << max << endl;
921 cout << "Maximum voxel: " << x << " "
922 << y << " " << z << " " << n << endl;
923 cout << "Volume: " << nvox*voxel_size << " A3" << endl;
924 cout << "Molecular weight: " << nvox*voxel_size*RHO << " Da" << endl << endl;
925 }
926
927 delete[] index;
928 // delete[] max_vox;
929
930 return pex;
931 }
932
944 Bimage* img_excise_all_features(Bimage* p, Bimage* pfeature)
945 {
946 unsigned long i, j, k, c;
947 unsigned long imagesize = p->sizeX()*p->sizeY()*p->sizeZ();
948 Bimage* pex = new Bimage(p->data_type(), p->compound_type(),
949 p->sizeX(), p->sizeY(), p->sizeZ(), (unsigned long) pfeature->maximum());
950 pex->sampling(p->sampling());
951 for ( i=0; i<pex->images(); i++ ) pex->image[i] = p->image[0];
952
953 if ( verbose & VERB_PROCESS )
954 cout << "Excising %g features" << pfeature->maximum() << endl << endl;
955
956 for ( i=0; i<imagesize; i++ ) if ( (*pfeature)[i] > 0 ) {
957 j = (((unsigned long)(*pfeature)[i] - 1)*imagesize + i)*pex->channels();
958 for ( c=0, k=i*pex->channels(); c<pex->channels(); c++, j++, k++ ) pex->set(j, (*p)[k]);
959 }
960
961 return pex;
962 }
963
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
verbose
int verbose
img_flood_fill
Bimage * img_flood_fill(Bimage *p, Bimage *pfeature, float threshold_hi, float threshold_lo, float threshold_step, int fill_borders)
Creates and expands a feature map from a starting to ending threshold value.
Definition: img_segment.cpp:439
img_flood_peaks
Bimage * img_flood_peaks(Bimage *p, int kernel_size, float threshold)
Generates a segmented image from peaks above a threshold value.
Definition: img_segment.cpp:612
img_set_second_mask
int img_set_second_mask(Bimage *p, Bimage *pmask, float threshold)
A second level mask is added to a primary mask based on a threshold.
Definition: img_segment.cpp:701
img_find_features
Bimage * img_find_features(Bimage *p, float threshold, int sign, int wrap)
Segments an image into contiguous regions (features).
Definition: img_feature.cpp:407
utilities.h
Header file for general utilities.
VERB_DEBUG
#define VERB_DEBUG
Definition: utilities.h:104
Bsub_image::background
double background()
Definition: Bimage.h:127
Bimage::compound_type
CompoundType compound_type()
Definition: Bimage.h:305
img_segment.h
Header file for image segmenting functions.
Float
Definition: Bimage.h:60
Bmarker
Definition: marker.h:21
count_list
long count_list(char *list)
Counts the number of items in a linked list.
Definition: linked_list.cpp:235
Vector3
Definition: Quaternion.h:17
error_show
int error_show(const char *message, const char *file, int line)
Displays the error with file and line reference.
Definition: utilities.cpp:652
VERB_PROCESS
#define VERB_PROCESS
Definition: utilities.h:99
img_excise_feature
Bimage * img_excise_feature(Bimage *p, Bimage *pfeature, Bmarker *markers)
Finds the density around a voxel associated with a particular feature.
Definition: img_segment.cpp:850
Bimage::index
size_t index(size_t nx, size_t ny)
Definition: Bimage.h:334
Bimage::average
double average(size_t cc, double xf, double yf, double zf, size_t nn, double iscale)
Averages in the xy plane when scaling is less than 1.
Definition: Bimage.cpp:1149
Bimage::statistics
size_t statistics()
Calculates the statistics for an image.
Definition: Bimage_stats.cpp:22
TSimple
Definition: Bimage.h:71
img_average_feature_size
double img_average_feature_size(Bimage *p)
Calculates the average size of regions (features) in a level mask.
Definition: img_feature.cpp:455
img_internal_volume
int img_internal_volume(Bimage *p, float threshold, int mask_out_freq)
Finds the density threshold associated with a particular molecular weight.
Definition: img_segment.cpp:264
Bimage
General image parameter class.
Definition: Bimage.h:153
Bimage::data_alloc
unsigned char * data_alloc()
Definition: Bimage.h:227
linked_list.h
Header file for generalized linked list functions.
Bimage::maximum
double maximum()
Definition: Bimage.h:428
Bimage::FOM_initialize
float * FOM_initialize()
Allocates and initializes the FOM block.
Definition: Bimage.cpp:677
Bimage::channels
size_t channels()
Definition: Bimage.h:323
Bimage::sampling
void sampling(double s)
Definition: Bimage.h:412
Bimage::coordinates
void coordinates(size_t i, size_t &nx, size_t &ny, size_t &nz)
Definition: Bimage.h:358
img_combine.h
Header file for combining two images in various ways.
img_mass_at_threshold
float img_mass_at_threshold(Bimage *p, int img_num, float threshold, float rho)
Calculates the mass from the density threshold.
Definition: img_segment.cpp:222
img_find_threshold
float img_find_threshold(Bimage *p, int img_num, double mol_weight, float rho)
Finds the density threshold associated with a particular molecular weight.
Definition: img_segment.cpp:127
Vector3::x
Type x()
Definition: Vector3.h:139
Bimage::file_name
void file_name(Bstring s)
Definition: Bimage.h:214
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
Bmarker::next
Bmarker * next
Definition: marker.h:22
Bimage::standard_deviation
double standard_deviation()
Definition: Bimage.h:430
Bimage::images
size_t images()
Definition: Bimage.h:410
write_fom_as_image
int write_fom_as_image(Bstring &filename, Bimage *p)
Converts a FOM block to an image for output.
Definition: rwimg.cpp:438
Integer
Definition: Bimage.h:57
Bstring
Definition: Bstring.h:25
Bimage::copy
Bimage * copy()
Copies the header information and data of an image into a new image structure.
Definition: Bimage.cpp:2283
Bimage::sizeX
void sizeX(size_t nx)
Definition: Bimage.h:328
Bmarker::img_num
int img_num
Definition: marker.h:24
img_excise_all_features
Bimage * img_excise_all_features(Bimage *p, Bimage *pfeature)
Extracts all the features associated with a multi-level mask.
Definition: img_segment.cpp:944
Bimage::sizeY
void sizeY(size_t ny)
Definition: Bimage.h:329
RHO
#define RHO
Definition: utilities.h:83
Bmarker::loc
Vector3< float > loc
Definition: marker.h:25
img_feature.h
Header file for feature extraction tools.
img_blobs
int img_blobs(Bimage *p, float threshold, float min_size, float max_size, float setvalue, int sign)
Identifies contiguous regions above a given threshold (blobs) and eliminate those less than a minimum...
Definition: img_segment.cpp:37
img_segment_threshold_series
int img_segment_threshold_series(Bimage *p, float threshold_first, float threshold_last, float threshold_step)
Segments a map through a series of thresholds and reports results.
Definition: img_segment.cpp:382
Bimage::check_if_same_size
bool check_if_same_size(Bimage *p)
Check if two images are the same size.
Definition: Bimage.cpp:487
rwimg.h
Header file for 2D and 3D image I/O.
img_check_neighbors
int img_check_neighbors(Bimage *p, unsigned long index)
Check neighbors in feature map and assign a value if a neighbor is assigned.
Definition: img_segment.cpp:731
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
img_find_highest_in_kernel
long img_find_highest_in_kernel(Bimage *p, unsigned long index, int size)
Finds the highest value in a kernel excluding the central voxel.
Definition: img_segment.cpp:796
Bimage::image
Bsub_image * image
Definition: Bimage.h:184