VIOAPI VIO_Status input_volume( VIO_STR filename, int n_dimensions, VIO_STR dim_names[], nc_type volume_nc_data_type, VIO_BOOL volume_signed_flag, VIO_Real volume_voxel_min, VIO_Real volume_voxel_max, VIO_BOOL create_volume_flag, VIO_Volume *volume, minc_input_options *options ) { VIO_Status status; VIO_Real amount_done; volume_input_struct input_info; VIO_progress_struct progress; static const int FACTOR = 1000; VIO_Real volume_min=0.0,volume_max=0.0; status = start_volume_input( filename, n_dimensions, dim_names, volume_nc_data_type, volume_signed_flag, volume_voxel_min, volume_voxel_max, create_volume_flag, volume, options, &input_info ); if( status == VIO_OK ) { initialize_progress_report( &progress, FALSE, FACTOR, "Reading Volume"); while( input_more_of_volume( *volume, &input_info, &amount_done ) ) { update_progress_report( &progress, VIO_ROUND( (VIO_Real) FACTOR * amount_done)); } if (amount_done < 1.0) { status = VIO_ERROR; } terminate_progress_report( &progress ); delete_volume_input( &input_info ); if( !volume_is_alloced( *volume ) ) { delete_volume( *volume ); *volume = NULL; status = VIO_ERROR; } } if (status == VIO_OK) { get_volume_voxel_range( *volume, &volume_min, &volume_max ); } return( status ); }
/* ----------------------------- MNI Header ----------------------------------- @NAME : compute_chamfer @INPUT/OUTPUT: chamfer The original input volume will be destroyed and replaced with the resulting chamfer distance volume. The chamfer will contains 0's where the mask was and values > 0.0 for all other voxels, where the value is an estimate of the distance to the the nearest voxel of the mask. @RETURNS : ERROR if error, OK otherwise @DESCRIPTION: Uses an idea from georges, who got it from claire, who got it from Borgefors @GLOBALS : @CALLS : @CREATED : Nov 2, 1998 Louis @MODIFIED : ---------------------------------------------------------------------------- */ VIO_Status compute_chamfer(VIO_Volume chamfer, VIO_Real max_val) { VIO_Real mask_f[3][3][3], mask_b[3][3][3], zero, min, vox_min, vox_max, val, val2; int sizes[VIO_MAX_DIMENSIONS], i,j,k, ind0,ind1,ind2; VIO_progress_struct progress; get_volume_sizes(chamfer, sizes); get_volume_voxel_range(chamfer, &vox_min, &vox_max); zero = CONVERT_VALUE_TO_VOXEL(chamfer,0.0); /* init chamfer to be binary valued with 0.0 on the object, and infinity (or vox_max) elsewhere */ if (debug) print ("initing chamfer vol (%d %d %d)\n",sizes[0],sizes[1],sizes[2]); for(ind0=0; ind0<sizes[0]; ind0++) { for(ind1=0; ind1<sizes[1]; ind1++) { for(ind2=0; ind2<sizes[2]; ind2++) { GET_VOXEL_3D(val, chamfer, ind0, ind1, ind2); if (val == zero) { SET_VOXEL_3D(chamfer, ind0, ind1, ind2, vox_max ); } else { SET_VOXEL_3D(chamfer, ind0, ind1, ind2, vox_min); } } } } if (debug) print ("building mask\n"); build_mask(chamfer, mask_f, mask_b); set_volume_real_range(chamfer, 0.0, max_val); zero = CONVERT_VALUE_TO_VOXEL(chamfer,0.0); if (verbose) initialize_progress_report( &progress, TRUE, sizes[0], "forward pass"); for(ind0=1; ind0<sizes[0]-1; ind0++) { for(ind1=1; ind1<sizes[1]-1; ind1++) { for(ind2=1; ind2<sizes[2]-1; ind2++) { GET_VALUE_3D(val, chamfer, ind0, ind1, ind2); if (val != zero) { /* then apply forward mask */ min = val; for(i=-1; i<=+1; i++) { for(j=-1; j<=+1; j++) { for(k=-1; k<=+1; k++) { GET_VALUE_3D(val, chamfer, i+ind0, j+ind1, k+ind2); val2 = val + mask_f[i+1][j+1][k+1]; min = MIN (min, val2); } } } min = convert_value_to_voxel(chamfer, min); SET_VOXEL_3D(chamfer, ind0, ind1, ind2, min ); } /* if val != 0.0 */ } /* ind2 */ } /* ind1 */ if (verbose) update_progress_report( &progress, ind0+1 ); } /* ind0 */ if (verbose) terminate_progress_report( &progress ); if (verbose) initialize_progress_report( &progress, TRUE, sizes[0], "reverse pass"); for(ind0=sizes[0]-2; ind0>=1; ind0--) { for(ind1=sizes[1]-2; ind1>=1; ind1--) { for(ind2=sizes[2]-2; ind2>=1; ind2--) { GET_VALUE_3D(val, chamfer, ind0, ind1, ind2); if (val != zero) { /* then apply backwardmask */ min = val; for(i=-1; i<=1; i++) { for(j=-1; j<=+1; j++) { for(k=-1; k<=+1; k++) { GET_VALUE_3D(val, chamfer, i+ind0, j+ind1, k+ind2); val2 = val + mask_b[i+1][j+1][k+1]; min = MIN (min, val2); } } } min = convert_value_to_voxel(chamfer, min); SET_VOXEL_3D(chamfer, ind0, ind1, ind2, min ); } /* if val != 0.0 */ } /* ind2 */ } /* ind1 */ if (verbose) update_progress_report( &progress, ind0+1 ); } /* ind0 */ if (verbose) terminate_progress_report( &progress ); return (OK); }
void make_zscore_volume(VIO_Volume d1, VIO_Volume m1, VIO_Real *threshold) { unsigned long count; int stat_count, sizes[VIO_MAX_DIMENSIONS], s,r,c; VIO_Real wx,wy,wz, valid_min_dvoxel, valid_max_dvoxel, min,max, sum, sum2, mean, var, std, data_vox,data_val, thick[VIO_MAX_DIMENSIONS]; PointR voxel; VIO_Volume vol; VIO_progress_struct progress; /* get default information from data and mask */ /* build temporary working volume */ vol = copy_volume_definition(d1, NC_UNSPECIFIED, FALSE, 0.0, 0.0); set_volume_real_range(vol, MIN_ZRANGE, MAX_ZRANGE); get_volume_sizes(d1, sizes); get_volume_separations(d1, thick); get_volume_voxel_range(d1, &valid_min_dvoxel, &valid_max_dvoxel); /* initialize counters and sums */ count = 0; sum = 0.0; sum2 = 0.0; min = 1e38; max = -1e38; stat_count = 0; initialize_progress_report(&progress, FALSE, sizes[0]*sizes[1]*sizes[2] + 1, "Tally stats" ); /* do first pass, to get mean and std */ for(s=0; s<sizes[0]; s++) { for(r=0; r<sizes[1]; r++) { for(c=0; c<sizes[2]; c++) { stat_count++; update_progress_report( &progress, stat_count); convert_3D_voxel_to_world(d1, (VIO_Real)s, (VIO_Real)r, (VIO_Real)c, &wx, &wy, &wz); if (m1 != NULL) { convert_3D_world_to_voxel(m1, wx, wy, wz, &Point_x(voxel), &Point_y(voxel), &Point_z(voxel)); } else { wx = 0.0; wy = 0.0; wz = 0.0; } if (point_not_masked(m1, wx,wy,wz)) { GET_VOXEL_3D( data_vox, d1 , s, r, c ); if (data_vox >= valid_min_dvoxel && data_vox <= valid_max_dvoxel) { data_val = CONVERT_VOXEL_TO_VALUE(d1, data_vox); if (data_val > *threshold) { sum += data_val; sum2 += data_val*data_val; count++; if (data_val < min) min = data_val; else if (data_val > max) max = data_val; } } } } } } terminate_progress_report( &progress ); stat_count = 0; initialize_progress_report(&progress, FALSE, sizes[0]*sizes[1]*sizes[2] + 1, "Zscore convert" ); /* calc mean and std */ mean = sum / (float)count; var = ((float)count*sum2 - sum*sum) / ((float)count*((float)count-1)); std = sqrt(var); min = 1e38; max = -1e38; /* replace the voxel values */ for(s=0; s<sizes[0]; s++) { for(r=0; r<sizes[1]; r++) { for(c=0; c<sizes[2]; c++) { stat_count++; update_progress_report( &progress, stat_count); GET_VOXEL_3D( data_vox, d1, s, r, c ); if (data_vox >= valid_min_dvoxel && data_vox <= valid_max_dvoxel) { data_val = CONVERT_VOXEL_TO_VALUE(d1, data_vox); if (data_val > *threshold) { /* instead of data_val = CONVERT_VALUE_TO_VOXEL(d1, data_vox); i will use data_val = CONVERT_VALUE_TO_VOXEL(d1, vol); since the values in vol are changed with respect to the new z-score volume */ data_val = (data_val - mean) / std; if (data_val< MIN_ZRANGE) data_val = MIN_ZRANGE; if (data_val> MAX_ZRANGE) data_val = MAX_ZRANGE; data_vox = CONVERT_VALUE_TO_VOXEL( vol, data_val); if (data_val < min) { min = data_val; } else { if (data_val > max) max = data_val; } } else data_vox = -DBL_MAX; /* should be fill_value! */ SET_VOXEL_3D( d1 , s, r, c, data_vox ); } } } } terminate_progress_report( &progress ); set_volume_real_range(d1, MIN_ZRANGE, MAX_ZRANGE); /* reset the data volume's range */ *threshold = (*threshold - mean) / std; delete_volume(vol); }
void add_speckle_to_volume(VIO_Volume d1, float speckle, double *start, int *count, VectorR directions[]) { VectorR vector_step; PointR starting_position, slice, row, col; VIO_Real valid_min_voxel, valid_max_voxel; double tx,ty,tz, voxel_value; int xi,yi,zi, flip_flag,r,c,s; flip_flag = FALSE; get_volume_voxel_range(d1, &valid_min_voxel, &valid_max_voxel); fill_Point( starting_position, start[0], start[1], start[2]); for(s=0; s<count[SLICE_IND]; s++) { SCALE_VECTOR( vector_step, directions[SLICE_IND], s); ADD_POINT_VECTOR( slice, starting_position, vector_step ); for(r=0; r<count[ROW_IND]; r++) { SCALE_VECTOR( vector_step, directions[ROW_IND], r); ADD_POINT_VECTOR( row, slice, vector_step ); SCALE_POINT( col, row, 1.0); /* init first col position */ for(c=0; c<count[COL_IND]; c++) { convert_3D_world_to_voxel(d1, Point_x(col), Point_y(col), Point_z(col), &tx, &ty, &tz); xi = (int)floor(tx + 0.5); yi = (int)floor( ty + 0.5); zi = (int)floor( tz + 0.5 ); GET_VOXEL_3D( voxel_value, d1 , xi, yi, zi ); if (voxel_value >= valid_min_voxel && voxel_value <= valid_max_voxel) { if (flip_flag) voxel_value = voxel_value * (1 + 0.01*speckle); else voxel_value = voxel_value * (1 - 0.01*speckle); SET_VOXEL_3D( d1 , xi, yi, zi, voxel_value ); } flip_flag = !flip_flag; ADD_POINT_VECTOR( col, col, directions[COL_IND] ); } } } }
void get_zscore_values(VIO_Volume d1, VIO_Volume m1, VIO_Real threshold, VIO_Real *mean, VIO_Real *std) { unsigned long count; int sizes[VIO_MAX_DIMENSIONS], s,r,c; VIO_Real wx,wy,wz, valid_min_dvoxel, valid_max_dvoxel, min,max, sum, sum2, var, data_vox,data_val, thick[VIO_MAX_DIMENSIONS]; /* get default information from data and mask */ get_volume_sizes(d1, sizes); get_volume_separations(d1, thick); get_volume_voxel_range(d1, &valid_min_dvoxel, &valid_max_dvoxel); /* initialize counters and sums */ count = 0; sum = 0.0; sum2 = 0.0; min = FLT_MAX; max = -FLT_MAX; /* get mean and std */ for(s=0; s<sizes[0]; s++) { for(r=0; r<sizes[1]; r++) { for(c=0; c<sizes[2]; c++) { convert_3D_voxel_to_world(d1, (VIO_Real)s, (VIO_Real)r, (VIO_Real)c, &wx, &wy, &wz); if (point_not_masked(m1, wx,wy,wz)) { GET_VOXEL_3D( data_vox, d1 , s, r, c ); if (data_vox >= valid_min_dvoxel && data_vox <= valid_max_dvoxel) { data_val = CONVERT_VOXEL_TO_VALUE(d1, data_vox); if (data_val > threshold) { sum += data_val; sum2 += data_val*data_val; count++; if (data_val < min) min = data_val; else if (data_val > max) max = data_val; } } } } } } /* calc mean and std */ *mean = sum / (float)count; var = ((float)count*sum2 - sum*sum) / ((float)count*((float)count-1)); *std = sqrt(var); }