Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

filters.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------- 00002 @COPYRIGHT : 00003 Copyright 1993,1994,1995 David MacDonald, 00004 McConnell Brain Imaging Centre, 00005 Montreal Neurological Institute, McGill University. 00006 Permission to use, copy, modify, and distribute this 00007 software and its documentation for any purpose and without 00008 fee is hereby granted, provided that the above copyright 00009 notice appear in all copies. The author and McGill University 00010 make no representations about the suitability of this 00011 software for any purpose. It is provided "as is" without 00012 express or implied warranty. 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 /* ----------------------------- MNI Header ----------------------------------- 00026 @NAME : get_slice_weights_for_filter 00027 @INPUT : volume 00028 voxel_position 00029 voxel_direction 00030 filter_type 00031 full_width_half_max 00032 @OUTPUT : positions 00033 weights 00034 @RETURNS : 00035 @DESCRIPTION: Computes the slice weights for the given filter. 00036 @METHOD : 00037 @GLOBALS : 00038 @CALLS : 00039 @CREATED : 1993 David MacDonald 00040 @MODIFIED : 00041 ---------------------------------------------------------------------------- */ 00042 00043 public int get_slice_weights_for_filter( 00044 Volume volume, 00045 Real voxel_position[], 00046 Real voxel_direction[], /* if filter_type != NEAREST */ 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 }

Generated on Wed Jul 28 09:10:57 2004 for BICPL by doxygen 1.3.7