00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
#include <volume_io/internal_volume_io.h>
00016
#include <bicpl/vols.h>
00017
00018
#ifndef lint
00019
static char rcsid[] =
"$Header: /software/source//libraries/bicpl/Volumes/filters.c,v 1.14 2000/02/06 15:30:55 stever Exp $";
00020
#endif
00021
00022 #define N_STD_DEVIATIONS 3.0
00023 #define N_SAMPLES 9
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 public int get_slice_weights_for_filter(
00044 Volume volume,
00045 Real voxel_position[],
00046 Real voxel_direction[],
00047 Filter_types filter_type,
00048 Real full_width_half_max,
00049 Real ***positions,
00050 Real *weights[] )
00051 {
00052
int i, c, n_slices, n_dims, axis;
00053
int slice, first_slice, last_slice, s;
00054 Real sum_weights, frac, start, end, weight;
00055 Real half_width, sigma, start_interval, end_interval, x;
00056 Real *origins;
00057
00058 n_dims = get_volume_n_dimensions( volume );
00059
00060 n_slices = 0;
00061
00062
switch( filter_type )
00063 {
00064
case NEAREST_NEIGHBOUR:
00065 ALLOC( origins, 1 );
00066 ALLOC( *weights, 1 );
00067 origins[0] = 0.0;
00068 (*weights)[0] = 1.0;
00069 n_slices = 1;
00070
break;
00071
00072
case LINEAR_INTERPOLATION:
00073 ALLOC( origins, 2 );
00074 ALLOC( *weights, 2 );
00075
00076 axis = -1;
00077 for_less( c, 0, n_dims )
00078 {
00079
if( voxel_direction[c] != 0.0 )
00080 {
00081
if( axis == -1 )
00082 axis = c;
00083
else
00084 {
00085 print_error(
00086
"Cannot do linear interpolation on non-ortho axis\n" );
00087 }
00088 }
00089 }
00090 frac = FRACTION( voxel_position[c] );
00091 origins[0] = (Real) (
int) voxel_position[c];
00092 (*weights)[0] = frac;
00093 n_slices = 1;
00094
00095
if( frac > 0.0 )
00096 {
00097 origins[1] = (Real) ((
int) voxel_position[c] + 1);
00098 (*weights)[1] = 1.0 - frac;
00099 n_slices = 2;
00100 }
00101
break;
00102
00103
case BOX_FILTER:
00104
case TRIANGLE_FILTER:
00105
case GAUSSIAN_FILTER:
00106
switch( filter_type )
00107 {
00108
case BOX_FILTER: half_width = full_width_half_max / 2.0;
break;
00109
case TRIANGLE_FILTER: half_width = full_width_half_max;
break;
00110
case GAUSSIAN_FILTER:
00111 sigma = full_width_half_max / 2.0 / sqrt(log(2.0));
00112 half_width =
N_STD_DEVIATIONS * sigma;
00113
break;
00114 }
00115 first_slice = (
int) (-half_width - 0.5);
00116 last_slice = (
int) (half_width + 0.5);
00117
00118 n_slices = last_slice - first_slice + 1;
00119 ALLOC( origins, n_slices );
00120 ALLOC( *weights, n_slices );
00121
00122 for_inclusive( slice, first_slice, last_slice )
00123 {
00124 origins[slice-first_slice] = (Real) slice;
00125
00126
if( slice == first_slice )
00127 start_interval = -half_width;
00128
else
00129 start_interval = (Real) slice - 0.5;
00130
00131
if( slice == last_slice )
00132 end_interval = half_width;
00133
else
00134 end_interval = (Real) slice + 0.5;
00135
00136
switch( filter_type )
00137 {
00138
case BOX_FILTER:
00139 weight = end_interval - start_interval;
00140
break;
00141
case TRIANGLE_FILTER:
00142 weight = 0.0;
00143
if( start_interval < 0.0 )
00144 {
00145 end = MIN( end_interval, 0.0);
00146 weight = (end - start_interval) *
00147 ((start_interval + end) / 2.0 + half_width) /
00148 half_width;
00149 }
00150
if( end_interval > 0.0 )
00151 {
00152 start = MAX( start_interval, 0.0);
00153 weight += (end_interval - start) *
00154 (half_width - (start + end_interval) / 2.0) /
00155 half_width;
00156 }
00157
break;
00158
case GAUSSIAN_FILTER:
00159 weight = 0.0;
00160
if( end_interval > start_interval )
00161 {
00162 for_less( s, 0,
N_SAMPLES )
00163 {
00164 x = start_interval + (end_interval - start_interval) *
00165 ((Real) s + 0.5) / (Real)
N_SAMPLES;
00166 weight += (end_interval - start_interval) *
00167 exp ( - x * x / sigma / sigma );
00168 }
00169 }
00170
break;
00171 }
00172
00173 (*weights)[slice-first_slice] = weight;
00174 }
00175
00176
break;
00177 }
00178
00179
if( n_slices < 1 )
00180 {
00181 handle_internal_error(
"get_slice_weights_for_filter" );
00182
return( 0 );
00183 }
00184
00185 ALLOC2D( *positions, n_slices, n_dims );
00186 sum_weights = 0.0;
00187 for_less( i, 0, n_slices )
00188 sum_weights += (*weights)[i];
00189
00190 for_less( i, 0, n_slices )
00191 {
00192
if( sum_weights == 0.0 )
00193 (*weights)[i] = 1.0 / (Real) n_slices;
00194
else
00195 (*weights)[i] /= sum_weights;
00196
00197 for_less( c, 0, n_dims )
00198 {
00199
if( filter_type == NEAREST_NEIGHBOUR )
00200 {
00201 (*positions)[i][c] = voxel_position[c];
00202 }
00203
else
00204 {
00205 (*positions)[i][c] = voxel_position[c] +
00206 origins[i] * voxel_direction[c];
00207 }
00208 }
00209 }
00210
00211 FREE( origins );
00212
00213
return( n_slices );
00214 }