/* ** slicetime correction for non-constant TR */ void VSlicetime_NC(VAttrList list, VShort minval, VFloat tdel, VBoolean slicetime_correction, float *onset_array, VString filename) { FILE *fp = NULL; VImage src; VAttrListPosn posn; VString buf, str; int b, r, c, i, j, nt = 0, mt = 0, val, del = 0; double xmin, xmax, sum, nx, estim_tr = 0; double *xx = NULL, *yy = NULL, xi, yi, slicetime = 0, u = 0; gsl_interp_accel *acc = NULL; gsl_spline *spline = NULL; xmin = (VShort) VRepnMinValue(VShortRepn); xmax = (VShort) VRepnMaxValue(VShortRepn); buf = VMalloc(LEN); /* ** read scan times from file, non-constant TR */ if(strlen(filename) > 2) { fp = fopen(filename, "r"); if(!fp) VError(" error opening file %s", filename); i = 0; while(!feof(fp)) { for(j = 0; j < LEN; j++) buf[j] = '\0'; fgets(buf, LEN, fp); if(buf[0] == '%' || buf[0] == '#') continue; if(strlen(buf) < 2) continue; i++; } rewind(fp); nt = i; fprintf(stderr, " num timesteps: %d\n", nt); xx = (double *) VCalloc(nt, sizeof(double)); yy = (double *) VCalloc(nt, sizeof(double)); i = 0; sum = 0; while(!feof(fp)) { for(j = 0; j < LEN; j++) buf[j] = '\0'; fgets(buf, LEN, fp); if(buf[0] == '%' || buf[0] == '#') continue; if(strlen(buf) < 2) continue; if(sscanf(buf, "%lf", &u) != 1) VError(" line %d: illegal input format", i + 1); xx[i] = u * 1000.0; /* convert to millisec */ if(i > 1) sum += xx[i] - xx[i - 1]; i++; } fclose(fp); estim_tr = sum / (double)(nt - 2); fprintf(stderr, " average scan interval = %.3f sec\n", estim_tr / 1000.0); } /* ** process data */ b = -1; for(VFirstAttr(list, & posn); VAttrExists(& posn); VNextAttr(& posn)) { if(VGetAttrRepn(& posn) != VImageRepn) continue; VGetAttrValue(& posn, NULL, VImageRepn, & src); if(VPixelRepn(src) != VShortRepn) continue; VSetAttr(VImageAttrList(src), "repetition_time", NULL, VLongRepn, (VLong)estim_tr); VExtractAttr(VImageAttrList(src), "MPIL_vista_0", NULL, VStringRepn, &str, FALSE); b++; if(VImageNRows(src) < 2) continue; /* ** get header info */ if(VGetAttr(VImageAttrList(src), "slice_time", NULL, VDoubleRepn, (VPointer) & slicetime) != VAttrFound && slicetime_correction && onset_array == NULL) VError(" 'slice_time' info missing"); if(onset_array != NULL) slicetime = onset_array[b]; if(nt != VImageNBands(src)) VError(" inconsistent number of time steps, %d %d", nt, VImageNBands(src)); if(acc == NULL && slicetime_correction) { acc = gsl_interp_accel_alloc(); spline = gsl_spline_alloc(gsl_interp_akima, nt); for(i = 0; i < 5; i++) { if(xx[i] / 1000.0 > tdel) break; } del = i; fprintf(stderr, " The first %.2f secs (%d timesteps) will be replaced.\n", tdel, del); } /* ** loop through all voxels in current slice */ if(slicetime_correction) fprintf(stderr, " slice: %3d, %10.3f ms\r", b, slicetime); for(r = 0; r < VImageNRows(src); r++) { for(c = 0; c < VImageNColumns(src); c++) { if(VPixel(src, 0, r, c, VShort) < minval) continue; /* replace first few time steps by average */ if(del > 0) { mt = del + 10; if(mt > nt) mt = nt; sum = nx = 0; for(i = del; i < mt; i++) { sum += VPixel(src, i, r, c, VShort); nx++; } if(nx < 1) continue; val = sum / nx; for(i = 0; i < del; i++) { VPixel(src, i, r, c, VShort) = val; } } if(!slicetime_correction) continue; /* correct for slicetime offsets using cubic spline interpolation */ for(i = 0; i < nt; i++) { yy[i] = VPixel(src, i, r, c, VShort); } gsl_spline_init(spline, xx, yy, nt); for(i = 1; i < nt; i++) { xi = xx[i] - slicetime; yi = gsl_spline_eval(spline, xi, acc); val = (int)(yi + 0.49); if(val > xmax) val = xmax; if(val < xmin) val = xmin; VPixel(src, i, r, c, VShort) = val; } } } } fprintf(stderr, "\n"); }
void VImageManager::prepareScaleValue() { QPtrList<V_ImageRec>::iterator it = m_imageList.begin(); unsigned int lastIndex = 90; if ( lastIndex >= m_imageList.count() ) lastIndex = m_imageList.count(); for ( unsigned int i = 0; i < lastIndex; i++ ) { VImage src = m_imageList.at( i ); int ncols = VImageNColumns( src ); int nrows = VImageNRows( src ); int nbands = VImageNFrames( src ); int npixels = nbands * nrows * ncols; int smin = ( int )VRepnMinValue( VShortRepn ); int smax = ( int )VRepnMaxValue( VShortRepn ); int i = 0, j = 0; int dim = 2 * smax + 1; float *histo = new float[dim]; for ( j = 0; j < dim; j++ ) histo[j] = 0; VShort *src_pp = ( VShort * ) VImageData( src ); for ( i = 0; i < ( int )( npixels ); i++ ) { j = *src_pp; src_pp ++; j -= smin; histo[j]++; } float sum = 0; for ( j = 0; j < dim; j++ ) sum += histo[j]; for ( j = 0; j < dim; j++ ) histo[j] /= sum; sum = 0; for ( j = 0; j < dim; j++ ) { sum += histo[j]; if ( sum > m_black ) break; } int xmin = j + smin; sum = 0; for ( j = dim; j > 0; j-- ) { sum += histo[j]; if ( sum > m_white ) break; } int xmax = j + smin; if ( xmin < m_xmin ) m_xmin = xmin; if ( xmax > m_xmax ) m_xmax = xmax; } }
int * KMeans(gsl_matrix *mat, int nclusters, double *bic, double *aic) { int *labels = NULL, *bestlabels = NULL, *list = NULL; int i, j, s, dim, iter, nvectors, maxiter = 1000; double xmax, dmin, d, nx, mx, best, xbic = 0; double rss = 0; gsl_vector *kmean[N], *kmean_sav[N]; gsl_vector *vec = NULL, *tmp = NULL; unsigned long int seed; gsl_rng *rx = NULL; const gsl_rng_type *T = NULL; /* random */ seed = 35521738; gsl_rng_env_setup(); T = gsl_rng_default; rx = gsl_rng_alloc(T); gsl_rng_set(rx, (unsigned long int)seed); /* alloc */ xmax = VRepnMaxValue(VDoubleRepn); dim = mat->size1; /* vector length */ nvectors = mat->size2; /* num vectors (matrix columns) */ vec = gsl_vector_calloc(dim); tmp = gsl_vector_calloc(dim); labels = (int *) VCalloc(nvectors, sizeof(int)); bestlabels = (int *) VCalloc(nvectors, sizeof(int)); list = (int *) VCalloc(nclusters, sizeof(int)); for(i = 0; i < nclusters; i++) { kmean[i] = gsl_vector_calloc(dim); kmean_sav[i] = gsl_vector_calloc(dim); } /* ini */ best = VRepnMaxValue(VDoubleRepn); /* best = 1.0e+999 !!!!!!!!!!!!!! */ for(s = 0; s < 50; s++) { /* try several starting values */ Centers(nvectors, nclusters, list, rx); for(i = 0; i < nclusters; i++) gsl_matrix_get_col(kmean[i], mat, list[i]); /* iterations */ for(iter = 0; iter < maxiter; iter++) { /* get nearest neighbour */ for(j = 0; j < nvectors; j++) { gsl_matrix_get_col(vec, mat, j); dmin = xmax; for(i = 0; i < nclusters; i++) { d = dist(kmean[i], vec); if(d < dmin) { dmin = d; labels[j] = i; } } } /* update cluster means */ for(i = 0; i < nclusters; i++) { gsl_vector_memcpy(kmean_sav[i], kmean[i]); gsl_vector_set_zero(kmean[i]); nx = 0; for(j = 0; j < nvectors; j++) { if(labels[j] != i) continue; gsl_matrix_get_col(vec, mat, j); gsl_vector_add(kmean[i], vec); nx++; } gsl_vector_scale(kmean[i], 1.0 / nx); } /* stop iterations if no significant changes occurr */ d = 0; for(i = 0; i < nclusters; i++) d += dist(kmean[i], kmean_sav[i]); if(d < 1.0e-10) break; } /* residual sum of squares, RSS */ rss = 0; for(i = 0; i < nclusters; i++) { for(j = 0; j < nvectors; j++) { if(labels[j] != i) continue; gsl_matrix_get_col(vec, mat, j); rss += dist(kmean[i], vec); } } if(rss < best) { best = rss; for(j = 0; j < nvectors; j++) bestlabels[j] = labels[j]; } } /* Bayesian information criterion (not very useful) */ nx = (double)nvectors; mx = (double)nclusters; xbic = nx * log(best) + mx * log(nx); (*bic) = log(best) + log(nx) * mx / nx; (*aic) = log(best) + 2.0 * mx / nx; (*bic) = xbic; return bestlabels; }
/* ** slicetime correction with constant TR */ void VSlicetime(VAttrList list, VShort minval, VFloat tdel, VBoolean slicetime_correction, float *onset_array) { VImage src; VAttrListPosn posn; VString str, buf; int b, r, c, i, nt, mt, val, del = 0; double xmin, xmax, sum, nx; double *xx = NULL, *yy = NULL, xi, yi, tr = 0, xtr = 0, slicetime = 0; gsl_interp_accel *acc = NULL; gsl_spline *spline = NULL; xmin = (VShort) VRepnMinValue(VShortRepn); xmax = (VShort) VRepnMaxValue(VShortRepn); buf = VMalloc(256); /* ** process data */ b = -1; for(VFirstAttr(list, & posn); VAttrExists(& posn); VNextAttr(& posn)) { if(VGetAttrRepn(& posn) != VImageRepn) continue; VGetAttrValue(& posn, NULL, VImageRepn, & src); if(VPixelRepn(src) != VShortRepn) continue; b++; if(VImageNRows(src) < 2) continue; /* ** get header info */ if(VGetAttr(VImageAttrList(src), "slice_time", NULL, VDoubleRepn, (VPointer) & slicetime) != VAttrFound && slicetime_correction && onset_array == NULL) VError(" 'slice_time' info missing");; if(onset_array != NULL) slicetime = onset_array[b]; tr = 0; if(VGetAttr(VImageAttrList(src), "repetition_time", NULL, VDoubleRepn, (VPointer) & tr) != VAttrFound) { tr = 0; if(VGetAttr(VImageAttrList(src), "MPIL_vista_0", NULL, VStringRepn, (VPointer) & str) == VAttrFound) { sscanf(str, " repetition_time=%lf %s", &tr, buf); } } if(tr < 1) VError(" attribute 'repetition_time' missing"); xtr = tr / 1000.0; del = (int)(tdel / xtr + 0.5); /* num timesteps to be ignored */ nt = VImageNBands(src); if(acc == NULL) { acc = gsl_interp_accel_alloc(); spline = gsl_spline_alloc(gsl_interp_akima, nt); xx = (double *) VCalloc(nt, sizeof(double)); yy = (double *) VCalloc(nt, sizeof(double)); fprintf(stderr, " The first %.2f secs (%d timesteps) will be replaced.\n", tdel, del); } /* ** loop through all voxels in current slice */ if(slicetime_correction) fprintf(stderr, " slice: %3d, %10.3f ms, TR: %.3f\r", b, slicetime, xtr); for(r = 0; r < VImageNRows(src); r++) { for(c = 0; c < VImageNColumns(src); c++) { if(VPixel(src, 0, r, c, VShort) < minval) continue; /* replace first few time steps by average */ if(del > 0) { mt = del + 10; if(mt > nt) mt = nt; sum = nx = 0; for(i = del; i < mt; i++) { sum += VPixel(src, i, r, c, VShort); nx++; } if(nx < 1) continue; val = sum / nx; for(i = 0; i < del; i++) { VPixel(src, i, r, c, VShort) = val; } } if(!slicetime_correction) continue; /* correct for slicetime offsets using cubic spline interpolation */ for(i = 0; i < nt; i++) { xi = i; xx[i] = xi * tr; yy[i] = VPixel(src, i, r, c, VShort); } gsl_spline_init(spline, xx, yy, nt); for(i = 1; i < nt; i++) { xi = xx[i] - slicetime; yi = gsl_spline_eval(spline, xi, acc); val = (int)(yi + 0.49); if(val > xmax) val = xmax; if(val < xmin) val = xmin; VPixel(src, i, r, c, VShort) = val; } } } } fprintf(stderr, "\n"); }
/*! \fn VImage VContrastShort(VImage src,VImage dest,VFloat percent,VFloat background) \param src input image (short repn) \param dest output image (ubyte repn) */ VImage VContrastShort(VImage src,VImage dest,VFloat low,VFloat high) { int nbands,nrows,ncols,npixels; float u,v,xmin,xmax,slope,sum; float *histo; int i,j,dim; VShort *src_pp; VUByte *dest_pp; double smin,smax; double percent1,percent2; if (VPixelRepn(src) != VShortRepn) VError(" input pixel repn must be short"); nbands = VImageNBands(src); nrows = VImageNRows(src); ncols = VImageNColumns(src); npixels = nbands * nrows * ncols; dest = VSelectDestImage("VContrastShort",dest,nbands,nrows,ncols,VUByteRepn); if (! dest) VError(" err creating dest image"); VFillImage(dest,VAllBands,0); smin = VRepnMinValue(VShortRepn); smax = VRepnMaxValue(VShortRepn); percent1 = low; /* unten */ percent2 = high; /* oben */ dim = 2.0 * smax + 1.0; histo = (float *) VCalloc(dim,sizeof(float)); for (j=0; j<dim; j++) histo[j] = 0; src_pp = (VShort *) VImageData(src); for (i=0; i<npixels; i++) { j = *src_pp++; j -= smin; histo[j]++; } sum = 0; for (j=0; j<dim; j++) sum += histo[j]; for (j=0; j<dim; j++) histo[j] /= sum; xmin = 0; sum = 0; for (j=0; j<dim; j++) { sum += histo[j]; if (sum > percent1) break; } xmin = j+smin; xmax = dim; sum = 0; for (j=dim; j>0; j--) { sum += histo[j]; if (sum > percent2) break; } xmax = j+smin; slope = 255.0f / (xmax - xmin); src_pp = (VShort *) VImageData(src); dest_pp = (VUByte *) VImageData(dest); for (i=0; i<npixels; i++) { u = *src_pp++; v = (int) (slope * (u - xmin) + 0.5); if (v < 0) v = 0; if (v > 255) v = 255; *dest_pp++ = (VUByte) v; } VFree(histo); VCopyImageAttrs (src, dest); return dest; }
VImage VHistoEqualize(VImage src,VImage dest,VFloat exponent) { int nbands,nrows,ncols,npixels; float u,v,sum; float *histo,*p; int i,j,dim; VShort *src_pp; VUByte *dest_pp; double smin,smax,x,y; if (VPixelRepn(src) != VShortRepn) VError(" input pixel repn must be short"); if (exponent < 0.5) VError("parameter '-exponent' should be >= 0.5"); if (exponent > 10) VWarning("parameter '-exponent' should be < 10"); nbands = VImageNBands(src); nrows = VImageNRows(src); ncols = VImageNColumns(src); npixels = nbands * nrows * ncols; dest = VSelectDestImage("VContrastShort",dest,nbands,nrows,ncols,VUByteRepn); if (! dest) VError(" err creating dest image"); VFillImage(dest,VAllBands,0); y = (double) exponent; smin = VRepnMinValue(VShortRepn); smax = VRepnMaxValue(VShortRepn); dim = 2.0 * smax + 1.0; histo = (float *) VCalloc(dim,sizeof(float)); for (j=0; j<dim; j++) histo[j] = 0; p = (float *) VCalloc(dim,sizeof(float)); src_pp = (VShort *) VImageData(src); for (i=0; i<npixels; i++) { j = *src_pp++; j -= smin; if (j == 0) continue; histo[j]++; } sum = 0; for (j=0; j<dim; j++) sum += histo[j]; for (j=0; j<dim; j++) histo[j] /= sum; /* cumulative hist */ for (i=0; i<dim; i++) { sum = 0; for (j=0; j<=i; j++) sum += histo[j]; p[i] = sum; } /* make lut */ for (i=0; i<dim; i++) { x = (double)p[i]; if (x > 0) p[i] = (float)(pow(x,y) * 255.0); } /* apply lut */ src_pp = (VShort *) VImageData(src); dest_pp = (VUByte *) VImageData(dest); for (i=0; i<npixels; i++) { u = *src_pp++; j = (int) (u-smin); v = (double)p[j]; if (v < 0) v = 0; if (v > 255) v = 255; *dest_pp++ = (VUByte) v; } VFree(p); VFree(histo); VCopyImageAttrs (src, dest); return dest; }
VImage VScaleIntensity(VImage src, double white, double black) /* scale any input image to VUByte, mapping white (black) percent of the voxel to white (black) */ { int x, y, z, nx, ny, nz, i, range, maxshort; unsigned int lb, ub, limit, sum, *histo; double m, b, max, min, mean, var, v; VImage dst; maxshort = (int)(VRepnMaxValue(VShortRepn)); histo = (unsigned int *)VCalloc(maxshort, sizeof(unsigned int)); nx = VImageNColumns(src); ny = VImageNRows(src); nz = VImageNBands(src); if (white < 0 || white > 100 || black < 0 || black > 100 || white+black >= 100) { fprintf(stderr, "VScaleIntensity: illegal percentage given.\n"); return 0; }; /* first pass: find maximum and minimum values */ VImageStats(src, VAllBands, &min, &max, &mean, &var); if (max == min) { fprintf(stderr, "VScaleIntensity: illegal data in image.\n"); return 0; }; b = min; m = (max-min) / (double)maxshort; /* second pass: build a histogram*/ for (z = 0; z < nz; z++) { for (y = 0; y < ny; y++) { for (x = 0; x < nx; x++) { v = VGetPixel(src, z, y, x); i = (int)((v-b)/m+0.5); histo[i]++; }; }; }; /* throw away pc percent of the voxel below lb and pc percent above ub */ limit = (black * nx * ny * nz) / 100; lb = 0; sum = 0; for (i = 0; i < maxshort; i++) { sum += histo[i]; if (sum >= limit) { lb = i; break; }; }; limit = (white * nx * ny * nz) / 100; ub = maxshort-1; sum = 0; for (i = maxshort-1; i >= 0; i--) { sum += histo[i]; if (sum >= limit) { ub = i; break; }; }; min = lb*m+b; max = ub*m+b; /* third pass: create and convert image */ dst = VCreateImage(nz, ny, nx, VUByteRepn); if (dst == 0) return 0; range = 256; m = range / (max - min); b = range - (m * max); for (z = 0; z < nz; z++) { for (y = 0; y < ny; y++) { for (x = 0; x < nx; x++) { v = VGetPixel(src, z, y, x); i = (int)(v * m + b + 0.5); if (i < 0) i = 0; else if (i >= range) i = range-1; VPixel(dst, z, y, x, VUByte) = i; }; }; }; VFree(histo); VCopyImageAttrs(src, dst); return dst; }
VAttrList VBayes(VImage cbeta_images[], VImage sd_images[], int nimages, VBoolean level, VBoolean zscore) { VAttrList out_list = NULL; VImage dest = NULL, sigma_image = NULL; int i, j, k, npixels; VFloat *dest_pp, *beta_pp[N], *sd_pp[N], *sigma_pp = NULL; VFloat pmin, pmax; double mean = 0, sigma = 0; float rx, wsum, msum, w0, wx, s, msumold; float result = 0; float gmean[N], gvar[N]; float tiny = 1.0e-12; /* ** create output image */ dest = VCopyImage(cbeta_images[0], NULL, VAllBands); if(!dest) return NULL; VFillImage(dest, VAllBands, 0); VSetAttr(VImageAttrList(dest), "num_images", NULL, VShortRepn, (VShort)nimages); VSetAttr(VImageAttrList(dest), "modality", NULL, VStringRepn, "bayes_map"); VSetAttr(VImageAttrList(dest), "name", NULL, VStringRepn, "bayes"); if(level == TRUE) { VSetAttr(VImageAttrList(dest), "modality", NULL, VStringRepn, "mean"); VSetAttr(VImageAttrList(dest), "name", NULL, VStringRepn, "mean"); sigma_image = VCopyImage(dest, NULL, VAllBands); if(!sigma_image) return NULL; VFillImage(sigma_image, VAllBands, 0); VSetAttr(VImageAttrList(sigma_image), "num_images", NULL, VShortRepn, (VShort)nimages); VSetAttr(VImageAttrList(sigma_image), "modality", NULL, VStringRepn, "std_dev"); VSetAttr(VImageAttrList(sigma_image), "name", NULL, VStringRepn, "std_dev"); } /* ** for each voxel */ pmax = VRepnMinValue(VFloatRepn); pmin = VRepnMaxValue(VFloatRepn); npixels = VImageNPixels(cbeta_images[0]); for(i = 0; i < nimages; i++) { beta_pp[i] = (VFloat *) VImageData(cbeta_images[i]); sd_pp[i] = (VFloat *) VImageData(sd_images[i]); } dest_pp = (VFloat *) VImageData(dest); if(level == TRUE) sigma_pp = (VFloat *) VImageData(sigma_image); for(j = 0; j < npixels; j++) { if(j % 10000 == 0) fprintf(stderr, "...%.2f%%\r", (float)100 * j / (float)npixels); result = mean = sigma = 0; /* ** read data from input images */ for(k = 0; k < nimages; k++) { gmean[k] = *beta_pp[k]++; /* mean c*beta */ rx = *sd_pp[k]++; /* standard deviation of c*beta*/ gvar[k] = rx * rx; /* variation of c*beta*/ } /* see Box,Tiao, pp.17-18 calculate probability distribution */ wsum = 0; msum = 0; w0 = 0; for(k = 0; k < nimages; k++) { /* for each image */ s = gvar[k]; if(s < tiny) goto next; s = sqrt((double)s); if(s < tiny) goto next; wx = 1.0 / (s * s); wsum = w0 + wx; msumold = msum; msum = (w0 * msum + wx * gmean[k]) / wsum; w0 = wsum; sigma = 1.0 / sqrt(wsum); } if(wsum < tiny) goto next; /* resulting mean and std dev */ mean = msum; sigma = 1.0 / sqrt(wsum); if(level == TRUE) { result = mean; goto next; } /* calculate probability under distribution */ result = CumulativeNormal(mean, sigma); /* output */ if(zscore) { /* CHECK HERE IF "1.0-" is correct */ result = (float)p2z((double)(1.0 - result)); if(mean < 0) result = -result; if(result > 20) result = 20; if(result < -20) result = -20; } else { result *= 100.0; if(result > 100) result = 100; if(mean < 0) result = -result; } if(result < pmin) pmin = result; if(result > pmax) pmax = result; next: *dest_pp++ = result; if(level) *sigma_pp++ = sigma; } out_list = VCreateAttrList(); fprintf(stderr, "...100.00%%\n"); if(level == FALSE) { fprintf(stderr, "\n min: %.3f, max: %.3f\n", pmin, pmax); VAppendAttr(out_list, "zmap", NULL, VImageRepn, dest); return out_list; } else { VAppendAttr(out_list, "mean", NULL, VImageRepn, dest); VAppendAttr(out_list, "std_dev", NULL, VImageRepn, sigma_image); return out_list; } return NULL; }
VImage VGetTrans(VImage ref, VImage src, int minval, int maxval, float pitch, float roll, float yaw, float shift[3], float shiftcorr, float offset, VShort scanwidth, VShort type) { VImage transform = NULL; VString str; long i, j, k, b, r, c, n = 6; float sb, sr, sc, range, range2; float theta, phi, psi; float theta0, phi0, psi0, step1, step2, angle; float theta1 = 0, phi1 = 0, psi1 = 0, sb1 = 0, sr1 = 0, sc1 = 0; float nx, u, deg; int iter, maxiter; double d, dmin; char typename[40]; const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex; gsl_multimin_fminimizer *s = NULL; gsl_vector *stepsizes = NULL, *p = NULL; gsl_multimin_function minex_func; size_t np = 6; struct my_params params; int status; double size, fret = 0; deg = (float) 180.0 / (float) PI; xminval = minval; xmaxval = maxval; itype = type; if(type == 0) sprintf(typename, "corr"); if(type == 1) sprintf(typename, "MI"); s1 = ref; s2 = src; nbands1 = VImageNBands(ref); nrows1 = VImageNRows(ref); ncols1 = VImageNColumns(ref); nbands2 = VImageNBands(src); nrows2 = VImageNRows(src); ncols2 = VImageNColumns(src); if(VPixelRepn(ref) != VUByteRepn) VError(" ref must be ubyte"); if(VPixelRepn(src) != VUByteRepn) VError(" src must be ubyte"); if(offset < 1) offset = 1; slicedist = offset; /* distance between slices */ center[0] = (float) nbands1 * 0.5; /* center of rotation */ center[1] = (float) nrows1 * 0.5; center[2] = (float) ncols1 * 0.5; bmin = rmin = cmin = VRepnMaxValue(VLongRepn); bmax = rmax = cmax = 0; ave2 = nx = 0; for(b = 0; b < nbands2; b++) { for(r = 0; r < nrows2; r++) { for(c = 0; c < ncols2; c++) { u = VPixel(src, b, r, c, VUByte); if(u > xminval && u < xmaxval) { if(r > rmax) rmax = r; if(c > cmax) cmax = c; if(r < rmin) rmin = r; if(c < cmin) cmin = c; ave2 += u; nx++; } } } } ave2 /= nx; ave1 = nx = 0; b = (int) VRint((float) nbands1 * 0.5); step2 = nbands2 + 2; for(b = 0; b < nbands1; b += (int)offset) { for(r = 0; r < nrows1; r += step2) { for(c = 0; c < ncols1; c += step2) { u = VPixel(ref, b, r, c, VUByte); if(u > minval && u < xmaxval) { ave1 += u; nx++; } } } } ave1 /= nx; /* ** get initial shift */ range = 30; range2 = 10; step1 = 2; psi0 = pitch / deg; /* set initial guesses of angles */ phi0 = roll / deg; theta0 = yaw / deg; n = 6; p = gsl_vector_calloc(n); shift[0] = center[0]; shift[1] += center[1]; shift[2] += center[2]; dmin = VRepnMaxValue(VFloatRepn); for(sb = 0; sb < nbands1; sb += step1) { for(sr = -range2 + shift[1]; sr <= range2 + shift[1]; sr += step1) { for(sc = -range2 + shift[2]; sc <= range2 + shift[2]; sc += step1) { gsl_vector_set(p, 0, sb); gsl_vector_set(p, 1, sr); gsl_vector_set(p, 2, sc); gsl_vector_set(p, 3, psi0); gsl_vector_set(p, 4, psi0); gsl_vector_set(p, 5, theta0); if(type == 0) d = func1(p, ¶ms); else d = func2(p, ¶ms); if(d < dmin) { dmin = d; sb1 = sb; sr1 = sr; sc1 = sc; } } } } shift[0] = sb1; shift[1] = sr1; shift[2] = sc1; /* ** get both shift and rotation */ if(scanwidth == 0) { maxiter = 2; angle = 9.0 / deg; step2 = 3.0 / deg; range = 6; step1 = 3; } else { maxiter = 3; angle = 12.0 / deg; step2 = 3.0 / deg; range = 12; step1 = 4; } psi0 = pitch / deg; phi0 = 0; theta0 = 0; psi = psi1 = psi0; phi = phi1 = phi0; theta = theta1 = theta0; gsl_vector_set(p, 0, shift[0]); gsl_vector_set(p, 1, shift[1]); gsl_vector_set(p, 2, shift[2]); gsl_vector_set(p, 3, psi0); gsl_vector_set(p, 4, phi0); gsl_vector_set(p, 5, theta0); if(type == 0) d = func1(p, ¶ms); else d = func2(p, ¶ms); if(verbose >= 1) fprintf(stderr, " %6.2f %6.2f %6.2f, %6.2f %6.2f %6.2f, %s: %7.4f\n", shift[0], shift[1], shift[2], psi0 * deg, phi0 * deg, theta0 * deg, typename, sqrt(ABS(d))); dmin = d; for(k = 0; k < maxiter; k++) { if(verbose >= 1) fprintf(stderr, " shift range: %g (step=%g), angle range: %g (step=%g)\n", range, step1, angle * deg, step2 * deg); for(sb = -range + shift[0]; sb <= range + shift[0]; sb += step1) { for(sr = -range + shift[1]; sr <= range + shift[1]; sr += step1) { for(sc = -range + shift[2]; sc <= range + shift[2]; sc += step1) { for(psi = psi0 - angle; psi <= psi0 + angle; psi += step2) { for(phi = phi0 - angle; phi <= phi0 + angle; phi += step2) { for(theta = theta0 - angle; theta <= theta0 + angle; theta += step2) { gsl_vector_set(p, 0, sb); gsl_vector_set(p, 1, sr); gsl_vector_set(p, 2, sc); gsl_vector_set(p, 3, psi); gsl_vector_set(p, 4, phi); gsl_vector_set(p, 5, theta); if(type == 0) d = func1(p, ¶ms); else d = func2(p, ¶ms); if(d < dmin) { dmin = d; sb1 = sb; sr1 = sr; sc1 = sc; psi1 = psi; phi1 = phi; theta1 = theta; if(verbose >= 1) fprintf(stderr, " %6.2f %6.2f %6.2f, %6.2f %6.2f %6.2f, %s: %7.4f\n", sb, sr, sc, psi * deg, phi * deg, theta * deg, typename, sqrt(ABS(dmin))); } } } } } } } angle -= 3.0 / deg; step2 *= 0.5; if(step2 < 2.0 / deg) step2 = 2.0 / deg; if(scanwidth == 0) range -= 2; else range -= 3; step1 -= 1; if(step1 < 2) step1 = 2; psi0 = psi1; phi0 = phi1; theta0 = theta1; shift[0] = sb1; shift[1] = sr1; shift[2] = sc1; }
/* ** goal function 1, linear correlation */ double func1(const gsl_vector *vec, void *params) { struct my_params *par = params; float u, v, nx1, nx2; float sum1, sum2, sum3; int b = 0, r, c, bb, rr, cc; float bx, rx, cx; float bx1, bx2, bx3, rx1, rx2, rx3; float phi, psi, theta, sb, sr, sc; int step; double corr; VDouble reject = VRepnMaxValue(VFloatRepn); step = 2 + nbands2; if(step > 8) step = 8; sb = gsl_vector_get(vec, 0); sr = gsl_vector_get(vec, 1); sc = gsl_vector_get(vec, 2); psi = gsl_vector_get(vec, 3); phi = gsl_vector_get(vec, 4); theta = gsl_vector_get(vec, 5); rotation_matrix(psi, phi, theta); corr = 0; sum1 = sum2 = sum3 = 0; nx1 = nx2 = 0; for(b = 0; b < nbands2; b++) { bx = (float) b * slicedist; bx -= center[0]; bx1 = rot[0][0] * bx; bx2 = rot[1][0] * bx; bx3 = rot[2][0] * bx; for(r = rmin; r < rmax; r += step) { rx = (float) r; rx -= center[1]; rx1 = rot[0][1] * rx; rx2 = rot[1][1] * rx; rx3 = rot[2][1] * rx; for(c = cmin; c < cmax; c += step) { cx = (float) c; cx -= center[2]; nx2++; bb = (int) VRint(bx1 + rx1 + rot[0][2] * cx + sb); if(bb < 0 || bb >= nbands1) continue; rr = (int) VRint(bx2 + rx2 + rot[1][2] * cx + sr); if(rr < 0 || rr >= nrows1) continue; cc = (int) VRint(bx3 + rx3 + rot[2][2] * cx + sc); if(cc < 0 || cc >= ncols1) continue; u = VPixel(s1, bb, rr, cc, VUByte); if(u < xminval || u > xmaxval) continue; u -= ave1; v = (float) VPixel(s2, b, r, c, VUByte) - ave2; sum1 += u * v; sum2 += u * u; sum3 += v * v; nx1++; } } } if(nx1 < nx2 * 0.33) return reject; if(sum2 *sum3 != 0) corr = (sum1 * sum1) / (sum2 * sum3); else corr = 1.0; return -corr; }
/* ** goal function 2, mutual information */ double func2(const gsl_vector *vec, void *params) { struct my_params *par = params; VDouble reject = VRepnMaxValue(VFloatRepn); int i, j, n, m; float nx1, nx2; int u, v; int b = 0, r, c, bb, rr, cc; float bx, rx, cx; float bx1, bx2, bx3, rx1, rx2, rx3; float phi, psi, theta, sb, sr, sc; int step; float nn[N][N]; float sumi[N], sumj[N]; float hxy, hx, hy, ixy, px, sum; float tiny = 1.0e-30; m = 16; m = 8; n = 256 / m; if(n > N) VError(" MI arrays too large"); step = 2 + nbands2; if(step > 8) step = 8; sb = gsl_vector_get(vec, 0); sr = gsl_vector_get(vec, 1); sc = gsl_vector_get(vec, 2); psi = gsl_vector_get(vec, 3); phi = gsl_vector_get(vec, 4); theta = gsl_vector_get(vec, 5); rotation_matrix(psi, phi, theta); for(i = 0; i < n; i++) for(j = 0; j < n; j++) nn[i][j] = 0; nx1 = nx2 = 0; for(b = 0; b < nbands2; b++) { bx = (float) b * slicedist; bx -= center[0]; bx1 = rot[0][0] * bx; bx2 = rot[1][0] * bx; bx3 = rot[2][0] * bx; for(r = rmin; r < rmax; r += step) { rx = (float) r; rx -= center[1]; rx1 = rot[0][1] * rx; rx2 = rot[1][1] * rx; rx3 = rot[2][1] * rx; for(c = cmin; c < cmax; c += step) { cx = (float) c; cx -= center[2]; nx2++; bb = (int) VRint(bx1 + rx1 + rot[0][2] * cx + sb); if(bb < 0 || bb >= nbands1) continue; rr = (int) VRint(bx2 + rx2 + rot[1][2] * cx + sr); if(rr < 0 || rr >= nrows1) continue; cc = (int) VRint(bx3 + rx3 + rot[2][2] * cx + sc); if(cc < 0 || cc >= ncols1) continue; u = (int) VPixel(s1, bb, rr, cc, VUByte); i = u / m; v = (int) VPixel(s2, b, r, c, VUByte); j = v / m; nn[i][j]++; nx1++; } } } if(nx1 < nx2 * 0.33) return reject; sum = 0; for(i = 0; i < n; i++) { sumi[i] = 0; for(j = 0; j < n; j++) { sumi[i] += nn[i][j]; sum += nn[i][j]; } } if(sum < tiny) return reject; for(j = 0; j < n; j++) { sumj[j] = 0; for(i = 0; i < n; i++) sumj[j] += nn[i][j]; } hx = hy = 0; for(i = 0; i < n; i++) { if(sumi[i] > 0) { px = sumi[i] / sum; hx -= px * log(px); } if(sumj[i] > 0) { px = sumj[i] / sum; hy -= px * log(px); } } hxy = 0; for(i = 0; i < n; i++) { for(j = 0; j < n; j++) { if(nn[i][j] > 0) { px = nn[i][j] / sum; hxy -= px * log(px); } } } ixy = hx + hy - hxy; return (double)(-ixy); }