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

smooth.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 #include <bicpl/geom.h> 00018 #include <bicpl/trans.h> 00019 00020 #ifndef lint 00021 static char rcsid[] = "$Header: /software/source//libraries/bicpl/Volumes/smooth.c,v 1.21 2000/02/06 15:30:57 stever Exp $"; 00022 #endif 00023 00024 private Real calculate_weight( 00025 int x, 00026 Real dx, 00027 Real x_min, 00028 Real x_max ); 00029 00030 /* ----------------------------- MNI Header ----------------------------------- 00031 @NAME : smooth_resample_volume 00032 @INPUT : volume 00033 new_nx 00034 new_ny 00035 new_nz 00036 @OUTPUT : 00037 @RETURNS : resampled volume 00038 @DESCRIPTION: Resamples the volume using a simple box filter, basically 00039 retessellating the volume to the given resolution. 00040 @METHOD : 00041 @GLOBALS : 00042 @CALLS : 00043 @CREATED : 1993 David MacDonald 00044 @MODIFIED : 00045 ---------------------------------------------------------------------------- */ 00046 00047 public Volume smooth_resample_volume( 00048 Volume volume, 00049 int new_nx, 00050 int new_ny, 00051 int new_nz ) 00052 { 00053 Volume resampled_volume; 00054 int sizes[MAX_DIMENSIONS], new_sizes[MAX_DIMENSIONS]; 00055 int dest_voxel[N_DIMENSIONS], src_voxel[N_DIMENSIONS], c; 00056 Real x_min, x_max, y_min, y_max, z_min, z_max; 00057 Real separations[N_DIMENSIONS]; 00058 Real dx, dy, dz; 00059 Real voxel; 00060 Real x_weight, xy_weight, weight; 00061 Real *y_weights, *z_weights; 00062 Real val; 00063 Transform scale_transform, translation_transform, transform; 00064 General_transform general_transform, tmp; 00065 progress_struct progress; 00066 00067 if( get_volume_n_dimensions(volume) != 3 ) 00068 { 00069 handle_internal_error( "smooth_resample_volume: volume must be 3D.\n" ); 00070 } 00071 00072 get_volume_sizes( volume, sizes ); 00073 00074 new_sizes[X] = new_nx; 00075 new_sizes[Y] = new_ny; 00076 new_sizes[Z] = new_nz; 00077 00078 for_less( c, 0, N_DIMENSIONS ) 00079 if( new_sizes[c] <= 0 ) 00080 new_sizes[c] = sizes[c]; 00081 00082 resampled_volume = create_volume( 3, volume->dimension_names, 00083 volume->nc_data_type, 00084 volume->signed_flag, 00085 get_volume_voxel_min(volume), 00086 get_volume_voxel_max(volume) ); 00087 00088 set_volume_sizes( resampled_volume, new_sizes ); 00089 00090 set_volume_real_range( resampled_volume, get_volume_real_min(volume), 00091 get_volume_real_max(volume) ); 00092 00093 dx = (Real) sizes[X] / (Real) new_sizes[X]; 00094 dy = (Real) sizes[Y] / (Real) new_sizes[Y]; 00095 dz = (Real) sizes[Z] / (Real) new_sizes[Z]; 00096 00097 get_volume_separations( volume, separations ); 00098 00099 separations[X] *= dx; 00100 separations[Y] *= dy; 00101 separations[Z] *= dz; 00102 00103 set_volume_separations( resampled_volume, separations ); 00104 00105 make_translation_transform( dx / 2.0 - 0.5, dy / 2.0 - 0.5, dz / 2.0 - 0.5, 00106 &translation_transform ); 00107 make_scale_transform( dx, dy, dz, &scale_transform ); 00108 00109 concat_transforms( &transform, &scale_transform, &translation_transform ); 00110 00111 create_linear_transform( &tmp, &transform ); 00112 00113 concat_general_transforms( &tmp, get_voxel_to_world_transform(volume), 00114 &general_transform ); 00115 delete_general_transform( &tmp ); 00116 00117 set_voxel_to_world_transform( resampled_volume, &general_transform ); 00118 00119 alloc_volume_data( resampled_volume ); 00120 00121 ALLOC( y_weights, (int) dy + 2 ); 00122 ALLOC( z_weights, (int) dz + 2 ); 00123 00124 initialize_progress_report( &progress, FALSE, new_nx * new_ny, 00125 "Resampling" ); 00126 00127 for_less( dest_voxel[X], 0, new_nx ) 00128 { 00129 x_min = (Real) dest_voxel[X] * dx; 00130 x_max = (Real) (dest_voxel[X]+1) * dx; 00131 00132 for_less( dest_voxel[Y], 0, new_ny ) 00133 { 00134 y_min = (Real) dest_voxel[Y] * dy; 00135 y_max = (Real) (dest_voxel[Y]+1) * dy; 00136 00137 for_less( dest_voxel[Z], 0, new_nz ) 00138 { 00139 z_min = (Real) dest_voxel[Z] * dz; 00140 z_max = (Real) (dest_voxel[Z]+1) * dz; 00141 00142 for_inclusive( src_voxel[Y], (int) y_min, (int) y_max ) 00143 { 00144 y_weights[src_voxel[Y]-(int)y_min] = 00145 calculate_weight( src_voxel[Y], dy, y_min, y_max ); 00146 } 00147 00148 for_inclusive( src_voxel[Z], (int) z_min, (int) z_max ) 00149 { 00150 z_weights[src_voxel[Z]-(int)z_min] = 00151 calculate_weight( src_voxel[Z], dz, z_min, z_max ); 00152 } 00153 00154 val = 0.0; 00155 00156 for_inclusive( src_voxel[X], (int) x_min, (int) x_max ) 00157 { 00158 x_weight = calculate_weight( src_voxel[X], dx, 00159 x_min, x_max ); 00160 00161 for_inclusive( src_voxel[Y], (int) y_min, (int) y_max ) 00162 { 00163 xy_weight = x_weight * 00164 y_weights[src_voxel[Y]-(int)y_min]; 00165 00166 for_inclusive( src_voxel[Z], (int) z_min, (int) z_max ) 00167 { 00168 weight = xy_weight * 00169 z_weights[src_voxel[Z]-(int)z_min]; 00170 00171 if( weight > 0.0 ) 00172 { 00173 voxel = get_volume_voxel_value( volume, 00174 src_voxel[X], src_voxel[Y], 00175 src_voxel[Z], 0, 0 ); 00176 val += weight * voxel; 00177 } 00178 } 00179 } 00180 } 00181 00182 set_volume_voxel_value( resampled_volume, 00183 dest_voxel[X], dest_voxel[Y], dest_voxel[Z], 0, 0, 00184 val + 0.5 ); 00185 } 00186 00187 update_progress_report( &progress, 00188 dest_voxel[X] * new_ny + dest_voxel[Y] + 1 ); 00189 } 00190 } 00191 00192 terminate_progress_report( &progress ); 00193 00194 FREE( y_weights ); 00195 FREE( z_weights ); 00196 00197 return( resampled_volume ); 00198 } 00199 00200 /* ----------------------------- MNI Header ----------------------------------- 00201 @NAME : calculate_weight 00202 @INPUT : x 00203 dx 00204 x_min 00205 y_min 00206 @OUTPUT : 00207 @RETURNS : weight 00208 @DESCRIPTION: Computes the weight of the box in the 1D case. 00209 @METHOD : 00210 @GLOBALS : 00211 @CALLS : 00212 @CREATED : 1993 David MacDonald 00213 @MODIFIED : 00214 ---------------------------------------------------------------------------- */ 00215 00216 private Real calculate_weight( 00217 int x, 00218 Real dx, 00219 Real x_min, 00220 Real x_max ) 00221 { 00222 Real start, end, weight; 00223 00224 start = MAX( x_min, (Real) x ); 00225 end = MIN( x_max, (Real) (x+1) ); 00226 00227 if( end < start || end - start > 1.0 ) 00228 { 00229 handle_internal_error( "calculate_weight" ); 00230 } 00231 00232 weight = (end - start) / dx; 00233 00234 return( weight ); 00235 }

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