int main(int argc, char *argv[]) { char **av ; int ac, nargs ; MRI *mri_src, *mri_ref, *mri_tmp ; double accuracy ; MRI_REGION box ; /* rkt: check for and handle version tag */ nargs = handle_version_option (argc, argv, "$Id: mri_label_accuracy.c,v 1.2 2011/03/02 00:04:22 nicks Exp $", "$Name: stable5 $"); if (nargs && argc - nargs == 1) exit (0); argc -= nargs; Progname = argv[0] ; ErrorInit(NULL, NULL, NULL) ; DiagInit(NULL, NULL, NULL) ; ac = argc ; av = argv ; for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++) { nargs = get_option(argc, argv) ; argc -= nargs ; argv += nargs ; } if (argc < 3) usage_exit(1) ; mri_src = MRIread(argv[1]) ; if (mri_src == NULL) ErrorExit(ERROR_BADPARM, "%s: could not read input volume %s\n", Progname,argv[1]); MRIboundingBox(mri_src, 0, &box) ; mri_tmp = MRIextractRegionAndPad(mri_src, NULL, &box, PAD) ; MRIfree(&mri_src) ; mri_src = mri_tmp ; if (mri_src->type == MRI_SHORT) { mri_tmp = MRIchangeType(mri_src, MRI_FLOAT, 0, 0, 0) ; MRIfree(&mri_src) ; mri_src = mri_tmp ; } mri_ref = MRIread(argv[2]) ; if (mri_ref == NULL) ErrorExit(ERROR_BADPARM, "%s: could not read reference volume %s\n", Progname,argv[1]); MRIboundingBox(mri_ref, 0, &box) ; mri_tmp = MRIextractRegionAndPad(mri_ref, NULL, &box, PAD) ; MRIfree(&mri_ref) ; mri_ref = mri_tmp ; accuracy = MRIcomputeLabelAccuracy(mri_src, mri_ref, MRI_MEAN_MIN_DISTANCE, stdout) ; if (Gdiag_fp) fclose(Gdiag_fp) ; exit(0) ; return(0) ; }
int main(int argc, char *argv[]) { tesselation_parms *parms; MRIS **mris_table, *mris,*mris_corrected; MRI *mri; char cmdline[CMD_LINE_LEN] ; make_cmd_version_string (argc, argv, "$Id: mri_mc.c,v 1.22 2011/03/02 00:04:23 nicks Exp $", "$Name: stable5 $", cmdline); Progname=argv[0]; if (argc > 1 && (stricmp(argv[1], "-d") == 0)) { downsample = atoi(argv[2]) ; argc -= 2; argv += 2 ; printf("downsampling input volume %d times\n", downsample) ; } if (argc < 4) { fprintf(stderr,"\n\nUSAGE: mri_mc input_volume " "label_value output_surface [connectivity]"); fprintf(stderr, "\noption connectivity: 1=6+,2=18,3=6,4=26 (default=1)\n\n"); exit(-1); } parms=(tesselation_parms*)calloc(1,sizeof(tesselation_parms)); if (!parms) ErrorExit(ERROR_NOMEMORY, "tesselation parms\n") ; mri=MRIread(argv[1]); if (downsample > 0) { MRI *mri_tmp ; mri_tmp = MRIdownsample2(mri, NULL) ; MRIfree(&mri) ; mri = mri_tmp ; } { MRI *mri_tmp ; mri_tmp = MRIalloc(mri->width+2, mri->height+2, mri->depth+2, mri->type) ; MRIextractInto(mri, mri_tmp, 0, 0, 0, mri->width, mri->height, mri->depth, 1, 1, 1) ; MRIfree(&mri) ; mri = mri_tmp ; } MRIreInitCache(mri); if (mri->type != MRI_UCHAR) { MRI *mri_tmp ; float min_val, max_val ; MRIvalRange(mri, &min_val, &max_val) ; if (min_val < 0 || max_val > 255) ErrorExit (ERROR_UNSUPPORTED, "%s: input volume (val range [%2.1f %2.1f]) must be " "convertible to UCHAR", Progname, min_val, max_val) ; printf("changing type of input volume to 8 bits/voxel...\n") ; mri_tmp = MRIchangeType(mri, MRI_UCHAR, 0.0, 0.999, TRUE) ; MRIfree(&mri) ; mri = mri_tmp ; } parms->mri=mri; parms->number_of_labels=1; //only one single label parms->label_values=(int*)malloc(sizeof(int)); parms->label_values[0]=atoi(argv[2]);//label; parms->ind=0; mris_table=(MRIS**)malloc(sizeof(MRIS*)); //final surface information parms->mris_table=mris_table; if ((!parms->label_values) || (!mris_table)) ErrorExit(ERROR_NOMEMORY, "labels/surfaces tables\n") ; if (argc==5) parms->connectivity=atoi(argv[4]);//connectivity; else parms->connectivity=1; initTesselationParms(parms); generateMCtesselation(parms); free(parms->label_values); mris=parms->mris_table[0]; free(parms->mris_table); freeTesselationParms(&parms); { float dist,max_e=0.0; int n,p,vn0,vn2; VERTEX *v,*vp; fprintf(stderr,"computing the maximum edge length..."); for (n = 0 ; n < mris->nvertices ; n++) { v=&mris->vertices[n]; for (p = 0 ; p < v->vnum ; p++) { vp = &mris->vertices[v->v[p]]; dist=SQR(vp->x-v->x)+SQR(vp->y-v->y)+SQR(vp->z-v->z); if (dist>max_e) max_e=dist; } } fprintf(stderr,"%f mm",sqrt(max_e)); fprintf(stderr,"\nreversing orientation of faces..."); for (n = 0 ; n < mris->nfaces ; n++) { vn0=mris->faces[n].v[0]; vn2=mris->faces[n].v[2]; /* vertex 0 becomes vertex 2 */ v=&mris->vertices[vn0]; for (p = 0 ; p < v->num ; p++) if (v->f[p]==n) v->n[p]=2; mris->faces[n].v[2]=vn0; /* vertex 2 becomes vertex 0 */ v=&mris->vertices[vn2]; for (p = 0 ; p < v->num ; p++) if (v->f[p]==n) v->n[p]=0; mris->faces[n].v[0]=vn2; } } fprintf(stderr,"\nchecking orientation of surface..."); MRISmarkOrientationChanges(mris); mris_corrected=MRISextractMainComponent(mris,0,1,0); MRISfree(&mris); fprintf(stderr,"\nwriting out surface..."); MRISaddCommandLine(mris_corrected, cmdline) ; if (mriConformed(mri) == 0) { printf("input volume is not conformed - using useRealRAS=1\n") ; mris_corrected->useRealRAS = 1 ; } // getVolGeom(mri, &mris_corrected->vg); MRISwrite(mris_corrected,argv[3]); fprintf(stderr,"done\n"); MRIfree(&mri); MRISfree(&mris_corrected); return 0; }
/*--------------------------------------------------*/ int main(int argc, char **argv) { int nargs, err, asegid, c, r, s, nctx, annot,vtxno,nripped; int annotid, IsCortex=0, IsWM=0, IsHypo=0, hemi=0, segval=0; int RibbonVal=0,nbrute=0; float dmin=0.0, lhRibbonVal=0, rhRibbonVal=0; /* rkt: check for and handle version tag */ nargs = handle_version_option (argc, argv, vcid, "$Name: stable5 $"); if (nargs && argc - nargs == 1) { exit (0); } argc -= nargs; Progname = argv[0] ; argc --; argv++; ErrorInit(NULL, NULL, NULL) ; DiagInit(NULL, NULL, NULL) ; if (argc == 0) { usage_exit(); } SUBJECTS_DIR = getenv("SUBJECTS_DIR"); if (SUBJECTS_DIR==NULL) { printf("ERROR: SUBJECTS_DIR not defined in environment\n"); exit(1); } parse_commandline(argc, argv); check_options(); dump_options(stdout); /* ------ Load subject's lh white surface ------ */ sprintf(tmpstr,"%s/%s/surf/lh.white",SUBJECTS_DIR,subject); printf("\nReading lh white surface \n %s\n",tmpstr); lhwhite = MRISread(tmpstr); if (lhwhite == NULL) { fprintf(stderr,"ERROR: could not read %s\n",tmpstr); exit(1); } /* ------ Load subject's lh pial surface ------ */ sprintf(tmpstr,"%s/%s/surf/lh.pial",SUBJECTS_DIR,subject); printf("\nReading lh pial surface \n %s\n",tmpstr); lhpial = MRISread(tmpstr); if (lhpial == NULL) { fprintf(stderr,"ERROR: could not read %s\n",tmpstr); exit(1); } if (lhwhite->nvertices != lhpial->nvertices) { printf("ERROR: lh white and pial have a different number of " "vertices (%d,%d)\n", lhwhite->nvertices,lhpial->nvertices); exit(1); } /* ------ Load lh annotation ------ */ sprintf(annotfile,"%s/%s/label/lh.%s.annot",SUBJECTS_DIR,subject,annotname); printf("\nLoading lh annotations from %s\n",annotfile); err = MRISreadAnnotation(lhwhite, annotfile); if (err) { printf("ERROR: MRISreadAnnotation() failed %s\n",annotfile); exit(1); } /* ------ Load subject's rh white surface ------ */ sprintf(tmpstr,"%s/%s/surf/rh.white",SUBJECTS_DIR,subject); printf("\nReading rh white surface \n %s\n",tmpstr); rhwhite = MRISread(tmpstr); if (rhwhite == NULL) { fprintf(stderr,"ERROR: could not read %s\n",tmpstr); exit(1); } /* ------ Load subject's rh pial surface ------ */ sprintf(tmpstr,"%s/%s/surf/rh.pial",SUBJECTS_DIR,subject); printf("\nReading rh pial surface \n %s\n",tmpstr); rhpial = MRISread(tmpstr); if (rhpial == NULL) { fprintf(stderr,"ERROR: could not read %s\n",tmpstr); exit(1); } if (rhwhite->nvertices != rhpial->nvertices) { printf("ERROR: rh white and pial have a different " "number of vertices (%d,%d)\n", rhwhite->nvertices,rhpial->nvertices); exit(1); } /* ------ Load rh annotation ------ */ sprintf(annotfile,"%s/%s/label/rh.%s.annot",SUBJECTS_DIR,subject,annotname); printf("\nLoading rh annotations from %s\n",annotfile); err = MRISreadAnnotation(rhwhite, annotfile); if (err) { printf("ERROR: MRISreadAnnotation() failed %s\n",annotfile); exit(1); } if (lhwhite->ct) { printf("Have color table for lh white annotation\n"); } if (rhwhite->ct) { printf("Have color table for rh white annotation\n"); } //print_annotation_table(stdout); if (UseRibbon) { sprintf(tmpstr,"%s/%s/mri/lh.ribbon.mgz",SUBJECTS_DIR,subject); printf("Loading lh ribbon mask from %s\n",tmpstr); lhRibbon = MRIread(tmpstr); if (lhRibbon == NULL) { printf("ERROR: loading %s\n",tmpstr); exit(1); } sprintf(tmpstr,"%s/%s/mri/rh.ribbon.mgz",SUBJECTS_DIR,subject); printf("Loading rh ribbon mask from %s\n",tmpstr); rhRibbon = MRIread(tmpstr); if (rhRibbon == NULL) { printf("ERROR: loading %s\n",tmpstr); exit(1); } } if (UseNewRibbon) { sprintf(tmpstr,"%s/%s/mri/ribbon.mgz",SUBJECTS_DIR,subject); printf("Loading ribbon segmentation from %s\n",tmpstr); RibbonSeg = MRIread(tmpstr); if (RibbonSeg == NULL) { printf("ERROR: loading %s\n",tmpstr); exit(1); } } if (LabelHypoAsWM) { sprintf(tmpstr,"%s/%s/mri/filled.mgz",SUBJECTS_DIR,subject); printf("Loading filled from %s\n",tmpstr); filled = MRIread(tmpstr); if (filled == NULL) { printf("ERROR: loading filled %s\n",tmpstr); exit(1); } } // ------------ Rip ----------------------- if (RipUnknown) { printf("Ripping vertices labeled as unkown\n"); nripped = 0; for (vtxno = 0; vtxno < lhwhite->nvertices; vtxno++) { annot = lhwhite->vertices[vtxno].annotation; CTABfindAnnotation(lhwhite->ct, annot, &annotid); // Sometimes the annotation will be "none" indicated by // annotid = -1. We interpret this as "unknown". if (annotid == 0 || annotid == -1) { lhwhite->vertices[vtxno].ripflag = 1; lhpial->vertices[vtxno].ripflag = 1; nripped++; } } printf("Ripped %d vertices from left hemi\n",nripped); nripped = 0; for (vtxno = 0; vtxno < rhwhite->nvertices; vtxno++) { annot = rhwhite->vertices[vtxno].annotation; CTABfindAnnotation(rhwhite->ct, annot, &annotid); if (annotid == 0 || annotid == -1) { rhwhite->vertices[vtxno].ripflag = 1; rhpial->vertices[vtxno].ripflag = 1; nripped++; } } printf("Ripped %d vertices from right hemi\n",nripped); } printf("\n"); printf("Building hash of lh white\n"); lhwhite_hash = MHTfillVertexTableRes(lhwhite, NULL,CURRENT_VERTICES,hashres); printf("\n"); printf("Building hash of lh pial\n"); lhpial_hash = MHTfillVertexTableRes(lhpial, NULL,CURRENT_VERTICES,hashres); printf("\n"); printf("Building hash of rh white\n"); rhwhite_hash = MHTfillVertexTableRes(rhwhite, NULL,CURRENT_VERTICES,hashres); printf("\n"); printf("Building hash of rh pial\n"); rhpial_hash = MHTfillVertexTableRes(rhpial, NULL,CURRENT_VERTICES,hashres); /* ------ Load ASeg ------ */ sprintf(tmpstr,"%s/%s/mri/aseg.mgz",SUBJECTS_DIR,subject); if (!fio_FileExistsReadable(tmpstr)) { sprintf(tmpstr,"%s/%s/mri/aseg.mgh",SUBJECTS_DIR,subject); if (!fio_FileExistsReadable(tmpstr)) { sprintf(tmpstr,"%s/%s/mri/aseg/COR-.info",SUBJECTS_DIR,subject); if (!fio_FileExistsReadable(tmpstr)) { printf("ERROR: cannot find aseg\n"); exit(1); } else { sprintf(tmpstr,"%s/%s/mri/aseg/",SUBJECTS_DIR,subject); } } } printf("\nLoading aseg from %s\n",tmpstr); ASeg = MRIread(tmpstr); if (ASeg == NULL) { printf("ERROR: loading aseg %s\n",tmpstr); exit(1); } mritmp = MRIchangeType(ASeg,MRI_INT,0,0,1); MRIfree(&ASeg); ASeg = mritmp; if (CtxSegFile) { printf("Loading Ctx Seg File %s\n",CtxSegFile); CtxSeg = MRIread(CtxSegFile); if (CtxSeg == NULL) { exit(1); } } AParc = MRIclone(ASeg,NULL); if (OutDistFile != NULL) { Dist = MRIclone(ASeg,NULL); mritmp = MRIchangeType(Dist,MRI_FLOAT,0,0,0); if (mritmp == NULL) { printf("ERROR: could change type\n"); exit(1); } MRIfree(&Dist); Dist = mritmp; } Vox2RAS = MRIxfmCRS2XYZtkreg(ASeg); printf("ASeg Vox2RAS: -----------\n"); MatrixPrint(stdout,Vox2RAS); printf("-------------------------\n"); CRS = MatrixAlloc(4,1,MATRIX_REAL); CRS->rptr[4][1] = 1; RAS = MatrixAlloc(4,1,MATRIX_REAL); RAS->rptr[4][1] = 1; if (crsTest) { printf("Testing point %d %d %d\n",ctest,rtest,stest); err = FindClosestLRWPVertexNo(ctest,rtest,stest, &lhwvtx, &lhpvtx, &rhwvtx, &rhpvtx, Vox2RAS, lhwhite, lhpial, rhwhite, rhpial, lhwhite_hash, lhpial_hash, rhwhite_hash, rhpial_hash); printf("Result: err = %d\n",err); exit(err); } printf("\nLabeling Slice\n"); nctx = 0; annot = 0; annotid = 0; nbrute = 0; // Go through each voxel in the aseg for (c=0; c < ASeg->width; c++) { printf("%3d ",c); if (c%20 ==19) { printf("\n"); } fflush(stdout); for (r=0; r < ASeg->height; r++) { for (s=0; s < ASeg->depth; s++) { asegid = MRIgetVoxVal(ASeg,c,r,s,0); if (asegid == 3 || asegid == 42) { IsCortex = 1; } else { IsCortex = 0; } if (asegid >= 77 && asegid <= 82) { IsHypo = 1; } else { IsHypo = 0; } if (asegid == 2 || asegid == 41) { IsWM = 1; } else { IsWM = 0; } if (IsHypo && LabelHypoAsWM && MRIgetVoxVal(filled,c,r,s,0)) { IsWM = 1; } // integrate surface information // // Only Do This for GM,WM or Unknown labels in the ASEG !!! // // priority is given to the ribbon computed from the surface // namely // ribbon=GM => GM // aseg=GM AND ribbon=WM => WM // ribbon=UNKNOWN => UNKNOWN if (UseNewRibbon && ( IsCortex || IsWM || asegid==0 ) ) { RibbonVal = MRIgetVoxVal(RibbonSeg,c,r,s,0); MRIsetVoxVal(ASeg,c,r,s,0, RibbonVal); if (RibbonVal==2 || RibbonVal==41) { IsWM = 1; IsCortex = 0; } else if (RibbonVal==3 || RibbonVal==42) { IsWM = 0; IsCortex = 1; } if (RibbonVal==0) { IsWM = 0; IsCortex = 0; } } // If it's not labeled as cortex or wm in the aseg, skip if (!IsCortex && !IsWM) { continue; } // If it's wm but not labeling wm, skip if (IsWM && !LabelWM) { continue; } // Check whether this point is in the ribbon if (UseRibbon) { lhRibbonVal = MRIgetVoxVal(lhRibbon,c,r,s,0); rhRibbonVal = MRIgetVoxVal(rhRibbon,c,r,s,0); if (IsCortex) { // ASeg says it's in cortex if (lhRibbonVal < 0.5 && rhRibbonVal < 0.5) { // but it is not part of the ribbon, // so set it to unknown (0) and go to the next voxel. MRIsetVoxVal(ASeg,c,r,s,0,0); continue; } } } // Convert the CRS to RAS CRS->rptr[1][1] = c; CRS->rptr[2][1] = r; CRS->rptr[3][1] = s; RAS = MatrixMultiply(Vox2RAS,CRS,RAS); vtx.x = RAS->rptr[1][1]; vtx.y = RAS->rptr[2][1]; vtx.z = RAS->rptr[3][1]; // Get the index of the closest vertex in the // lh.white, lh.pial, rh.white, rh.pial if (UseHash) { lhwvtx = MHTfindClosestVertexNo(lhwhite_hash,lhwhite,&vtx,&dlhw); lhpvtx = MHTfindClosestVertexNo(lhpial_hash, lhpial, &vtx,&dlhp); rhwvtx = MHTfindClosestVertexNo(rhwhite_hash,rhwhite,&vtx,&drhw); rhpvtx = MHTfindClosestVertexNo(rhpial_hash, rhpial, &vtx,&drhp); if (lhwvtx < 0 && lhpvtx < 0 && rhwvtx < 0 && rhpvtx < 0) { /* printf(" Could not map to any surface with hash table:\n"); printf(" crs = %d %d %d, ras = %6.4f %6.4f %6.4f \n", c,r,s,vtx.x,vtx.y,vtx.z); printf(" Using brute force search %d ... \n",nbrute); fflush(stdout); */ lhwvtx = MRISfindClosestVertex(lhwhite,vtx.x,vtx.y,vtx.z,&dlhw); lhpvtx = MRISfindClosestVertex(lhpial,vtx.x,vtx.y,vtx.z,&dlhp); rhwvtx = MRISfindClosestVertex(rhwhite,vtx.x,vtx.y,vtx.z,&drhw); rhpvtx = MRISfindClosestVertex(rhpial,vtx.x,vtx.y,vtx.z,&drhp); nbrute ++; //exit(1); } } else { lhwvtx = MRISfindClosestVertex(lhwhite,vtx.x,vtx.y,vtx.z,&dlhw); lhpvtx = MRISfindClosestVertex(lhpial,vtx.x,vtx.y,vtx.z,&dlhp); rhwvtx = MRISfindClosestVertex(rhwhite,vtx.x,vtx.y,vtx.z,&drhw); rhpvtx = MRISfindClosestVertex(rhpial,vtx.x,vtx.y,vtx.z,&drhp); } if (lhwvtx < 0) { dlhw = 1000000000000000.0; } if (lhpvtx < 0) { dlhp = 1000000000000000.0; } if (rhwvtx < 0) { drhw = 1000000000000000.0; } if (rhpvtx < 0) { drhp = 1000000000000000.0; } if (dlhw <= dlhp && dlhw < drhw && dlhw < drhp && lhwvtx >= 0) { annot = lhwhite->vertices[lhwvtx].annotation; hemi = 1; if (lhwhite->ct) { CTABfindAnnotation(lhwhite->ct, annot, &annotid); } else { annotid = annotation_to_index(annot); } dmin = dlhw; } if (dlhp < dlhw && dlhp < drhw && dlhp < drhp && lhpvtx >= 0) { annot = lhwhite->vertices[lhpvtx].annotation; hemi = 1; if (lhwhite->ct) { CTABfindAnnotation(lhwhite->ct, annot, &annotid); } else { annotid = annotation_to_index(annot); } dmin = dlhp; } if (drhw < dlhp && drhw < dlhw && drhw <= drhp && rhwvtx >= 0) { annot = rhwhite->vertices[rhwvtx].annotation; hemi = 2; if (rhwhite->ct) { CTABfindAnnotation(rhwhite->ct, annot, &annotid); } else { annotid = annotation_to_index(annot); } dmin = drhw; } if (drhp < dlhp && drhp < drhw && drhp < dlhw && rhpvtx >= 0) { annot = rhwhite->vertices[rhpvtx].annotation; hemi = 2; if (rhwhite->ct) { CTABfindAnnotation(rhwhite->ct, annot, &annotid); } else { annotid = annotation_to_index(annot); } dmin = drhp; } // Sometimes the annotation will be "none" indicated by // annotid = -1. We interpret this as "unknown". if (annotid == -1) { annotid = 0; } // why was this here in the first place? /* if (annotid == 0 && lhwvtx >= 0 && lhpvtx >= 0 && rhwvtx >= 0 && rhpvtx >= 0) { printf("%d %d %d %d\n", lhwhite->vertices[lhwvtx].ripflag, lhpial->vertices[lhpvtx].ripflag, rhwhite->vertices[rhwvtx].ripflag, rhpial->vertices[rhpvtx].ripflag); } */ if ( IsCortex && hemi == 1) { segval = annotid+1000 + baseoffset; //ctx-lh } if ( IsCortex && hemi == 2) { segval = annotid+2000 + baseoffset; //ctx-rh } if (!IsCortex && hemi == 1) { segval = annotid+3000 + baseoffset; // wm-lh } if (!IsCortex && hemi == 2) { segval = annotid+4000 + baseoffset; // wm-rh } if (!IsCortex && dmin > dmaxctx && hemi == 1) { segval = 5001; } if (!IsCortex && dmin > dmaxctx && hemi == 2) { segval = 5002; } // This is a hack for getting the right cortical seg with --rip-unknown // The aparc+aseg should be passed as CtxSeg. if (IsCortex && CtxSeg) { segval = MRIgetVoxVal(CtxSeg,c,r,s,0); } MRIsetVoxVal(ASeg,c,r,s,0,segval); MRIsetVoxVal(AParc,c,r,s,0,annot); if (OutDistFile != NULL) { MRIsetVoxVal(Dist,c,r,s,0,dmin); } if (debug || annotid == -1) { // Gets here when there is no label at the found vertex. // This is different than having a vertex labeled as "unknown" if (!debug) { continue; } printf("\n"); printf("Found closest vertex, but it has no label.\n"); printf("aseg id = %d\n",asegid); printf("crs = %d %d %d, ras = %6.4f %6.4f %6.4f \n", c,r,s,vtx.x,vtx.y,vtx.z); if (lhwvtx > 0) printf("lhw %d %7.5f %6.4f %6.4f %6.4f\n", lhwvtx, dlhw, lhwhite->vertices[lhwvtx].x, lhwhite->vertices[lhwvtx].y, lhwhite->vertices[lhwvtx].z); if (lhpvtx > 0) printf("lhp %d %7.5f %6.4f %6.4f %6.4f\n", lhpvtx, dlhp, lhpial->vertices[lhpvtx].x, lhpial->vertices[lhpvtx].y, lhpial->vertices[lhpvtx].z); if (rhwvtx > 0) printf("rhw %d %7.5f %6.4f %6.4f %6.4f\n", rhwvtx, drhw, rhwhite->vertices[rhwvtx].x, rhwhite->vertices[rhwvtx].y, rhwhite->vertices[rhwvtx].z); if (rhpvtx > 0) printf("rhp %d %7.5f %6.4f %6.4f %6.4f\n", rhpvtx, drhp, rhpial->vertices[rhpvtx].x, rhpial->vertices[rhpvtx].y, rhpial->vertices[rhpvtx].z); printf("annot = %d, annotid = %d\n",annot,annotid); CTABprintASCII(lhwhite->ct,stdout); continue; } nctx++; } } } printf("nctx = %d\n",nctx); printf("Used brute-force search on %d voxels\n",nbrute); if (FixParaHipWM) { /* This is a bit of a hack. There are some vertices that have been ripped because they are "unkown". When the above alorithm finds these, it searches for the closest known vertex. If this is less than dmax away, then the wm voxel gets labeled accordingly. However, there are often some voxels near ventralDC that are just close enough in 3d space to parahip to get labeled even though they are very far away along the surface. These voxels end up forming an island. CCSegment() will eliminate any islands. Unforunately, CCSegment() uses 6-neighbor (face) definition of connectedness, so some voxels may be eliminated. */ printf("Fixing Parahip LH WM\n"); CCSegment(ASeg, 3016, 5001); //3016 = lhphwm, 5001 = unsegmented WM left printf("Fixing Parahip RH WM\n"); CCSegment(ASeg, 4016, 5002); //4016 = rhphwm, 5002 = unsegmented WM right } printf("Writing output aseg to %s\n",OutASegFile); MRIwrite(ASeg,OutASegFile); if (OutAParcFile != NULL) { printf("Writing output aparc to %s\n",OutAParcFile); MRIwrite(AParc,OutAParcFile); } if (OutDistFile != NULL) { printf("Writing output dist file to %s\n",OutDistFile); MRIwrite(Dist,OutDistFile); } return(0); }
int main(int argc, char *argv[]) { char **av, *source_fname, *target_fname, *out_fname, fname[STRLEN] ; int ac, nargs, new_transform = 0, pad ; MRI *mri_target, *mri_source, *mri_orig_source ; MRI_REGION box ; struct timeb start ; int msec, minutes, seconds ; GCA_MORPH *gcam ; MATRIX *m_L/*, *m_I*/ ; LTA *lta ; /* initialize the morph params */ memset(&mp, 0, sizeof(GCA_MORPH_PARMS)); /* for nonlinear morph */ mp.l_jacobian = 1 ; mp.min_sigma = 0.4 ; mp.l_distance = 0 ; mp.l_log_likelihood = .025 ; mp.dt = 0.005 ; mp.noneg = True ; mp.exp_k = 20 ; mp.diag_write_snapshots = 1 ; mp.momentum = 0.9 ; if (FZERO(mp.l_smoothness)) mp.l_smoothness = 2 ; mp.sigma = 8 ; mp.relabel_avgs = -1 ; mp.navgs = 256 ; mp.levels = 6 ; mp.integration_type = GCAM_INTEGRATE_BOTH ; mp.nsmall = 1 ; mp.reset_avgs = -1 ; mp.npasses = 3 ; mp.regrid = regrid? True : False ; mp.tol = 0.1 ; mp.niterations = 1000 ; TimerStart(&start) ; setRandomSeed(-1L) ; DiagInit(NULL, NULL, NULL) ; ErrorInit(NULL, NULL, NULL) ; Progname = argv[0] ; ac = argc ; av = argv ; for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++) { nargs = get_option(argc, argv) ; argc -= nargs ; argv += nargs ; } if (argc < 4) usage_exit(1) ; source_fname = argv[1] ; target_fname = argv[2] ; out_fname = argv[3] ; FileNameOnly(out_fname, fname) ; FileNameRemoveExtension(fname, fname) ; strcpy(mp.base_name, fname) ; mri_source = MRIread(source_fname) ; if (!mri_source) ErrorExit(ERROR_NOFILE, "%s: could not read source label volume %s", Progname, source_fname) ; if (mri_source->type == MRI_INT) { MRI *mri_tmp = MRIchangeType(mri_source, MRI_FLOAT, 0, 1, 1) ; MRIfree(&mri_source); mri_source = mri_tmp ; } mri_target = MRIread(target_fname) ; if (!mri_target) ErrorExit(ERROR_NOFILE, "%s: could not read target label volume %s", Progname, target_fname) ; if (mri_target->type == MRI_INT) { MRI *mri_tmp = MRIchangeType(mri_target, MRI_FLOAT, 0, 1, 1) ; MRIfree(&mri_target); mri_target = mri_tmp ; } if (erosions > 0) { int n ; for (n = 0 ; n < erosions ; n++) { MRIerodeZero(mri_target, mri_target) ; MRIerodeZero(mri_source, mri_source) ; } } if (scale_values > 0) { MRIscalarMul(mri_source, mri_source, scale_values) ; MRIscalarMul(mri_target, mri_target, scale_values) ; } if (transform && transform->type == MORPH_3D_TYPE) TransformRas2Vox(transform, mri_source,NULL) ; if (use_aseg == 0) { if (match_peak_intensity_ratio) MRImatchIntensityRatio(mri_source, mri_target, mri_source, .8, 1.2, 100, 125) ; else if (match_mean_intensity) MRImatchMeanIntensity(mri_source, mri_target, mri_source) ; MRIboundingBox(mri_source, 0, &box) ; pad = (int)ceil(PADVOX * MAX(mri_target->xsize,MAX(mri_target->ysize,mri_target->zsize)) / MIN(mri_source->xsize,MIN(mri_source->ysize,mri_source->zsize))); #if 0 { MRI *mri_tmp ; if (pad < 1) pad = 1 ; printf("padding source with %d voxels...\n", pad) ; mri_tmp = MRIextractRegionAndPad(mri_source, NULL, &box, pad) ; if ((Gdiag & DIAG_WRITE) && DIAG_VERBOSE_ON) MRIwrite(mri_tmp, "t.mgz") ; MRIfree(&mri_source) ; mri_source = mri_tmp ; } #endif } mri_orig_source = MRIcopy(mri_source, NULL) ; mp.max_grad = 0.3*mri_source->xsize ; if (transform == NULL) transform = TransformAlloc(LINEAR_VOXEL_TO_VOXEL, NULL) ; if (transform->type != MORPH_3D_TYPE) // initializing m3d from a linear transform { new_transform = 1 ; lta = ((LTA *)(transform->xform)) ; if (lta->type != LINEAR_VOX_TO_VOX) { printf("converting ras xform to voxel xform\n") ; m_L = MRIrasXformToVoxelXform(mri_source, mri_target, lta->xforms[0].m_L, NULL) ; MatrixFree(<a->xforms[0].m_L) ; lta->type = LINEAR_VOX_TO_VOX ; } else { printf("using voxel xform\n") ; m_L = lta->xforms[0].m_L ; } #if 0 if (Gsx >= 0) // update debugging coords { VECTOR *v1, *v2 ; v1 = VectorAlloc(4, MATRIX_REAL) ; Gsx -= (box.x-pad) ; Gsy -= (box.y-pad) ; Gsz -= (box.z-pad) ; V3_X(v1) = Gsx ; V3_Y(v1) = Gsy ; V3_Z(v1) = Gsz ; VECTOR_ELT(v1,4) = 1.0 ; v2 = MatrixMultiply(m_L, v1, NULL) ; Gsx = nint(V3_X(v2)) ; Gsy = nint(V3_Y(v2)) ; Gsz = nint(V3_Z(v2)) ; MatrixFree(&v2) ; MatrixFree(&v1) ; printf("mapping by transform (%d, %d, %d) --> (%d, %d, %d) for rgb writing\n", Gx, Gy, Gz, Gsx, Gsy, Gsz) ; } #endif if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON) write_snapshot(mri_target, mri_source, m_L, &mp, 0, 1, "linear_init"); lta->xforms[0].m_L = m_L ; printf("initializing GCAM with vox->vox matrix:\n") ; MatrixPrint(stdout, m_L) ; gcam = GCAMcreateFromIntensityImage(mri_source, mri_target, transform) ; #if 0 gcam->gca = gcaAllocMax(1, 1, 1, mri_target->width, mri_target->height, mri_target->depth, 0, 0) ; #endif GCAMinitVolGeom(gcam, mri_source, mri_target) ; if (use_aseg) { if (ribbon_name) { char fname[STRLEN], path[STRLEN], *str, *hemi ; int h, s, label ; MRI_SURFACE *mris_white, *mris_pial ; MRI *mri ; for (s = 0 ; s <= 1 ; s++) // source and target { if (s == 0) { str = source_surf ; mri = mri_source ; FileNamePath(mri->fname, path) ; strcat(path, "/../surf") ; } else { mri = mri_target ; FileNamePath(mri->fname, path) ; strcat(path, "/../elastic") ; str = target_surf ; } // sorry - these values come from FreeSurferColorLUT.txt MRIreplaceValueRange(mri, mri, 1000, 1034, Left_Cerebral_Cortex) ; MRIreplaceValueRange(mri, mri, 1100, 1180, Left_Cerebral_Cortex) ; MRIreplaceValueRange(mri, mri, 2000, 2034, Right_Cerebral_Cortex) ; MRIreplaceValueRange(mri, mri, 2100, 2180, Right_Cerebral_Cortex) ; for (h = LEFT_HEMISPHERE ; h <= RIGHT_HEMISPHERE ; h++) { if (h == LEFT_HEMISPHERE) { hemi = "lh" ; label = Left_Cerebral_Cortex ; } else { label = Right_Cerebral_Cortex ; hemi = "rh" ; } sprintf(fname, "%s/%s%s.white", path, hemi, str) ; mris_white = MRISread(fname) ; if (mris_white == NULL) ErrorExit(ERROR_NOFILE, "%s: could not read surface %s", Progname, fname) ; MRISsaveVertexPositions(mris_white, WHITE_VERTICES) ; sprintf(fname, "%s/%s%s.pial", path, hemi, str) ; mris_pial = MRISread(fname) ; if (mris_pial == NULL) ErrorExit(ERROR_NOFILE, "%s: could not read surface %s", Progname, fname) ; MRISsaveVertexPositions(mris_pial, PIAL_VERTICES) ; if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON) { sprintf(fname, "sb.mgz") ; MRIwrite(mri_source, fname) ; sprintf(fname, "tb.mgz") ; MRIwrite(mri_target, fname) ; } insert_ribbon_into_aseg(mri, mri, mris_white, mris_pial, h) ; if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON) { sprintf(fname, "sa.mgz") ; MRIwrite(mri_source, fname) ; sprintf(fname, "ta.mgz") ; MRIwrite(mri_target, fname) ; } MRISfree(&mris_white) ; MRISfree(&mris_pial) ; } } if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON) { sprintf(fname, "s.mgz") ; MRIwrite(mri_source, fname) ; sprintf(fname, "t.mgz") ; MRIwrite(mri_target, fname) ; } } GCAMinitLabels(gcam, mri_target) ; GCAMsetVariances(gcam, 1.0) ; mp.mri_dist_map = create_distance_transforms(mri_source, mri_target, NULL, 40.0, gcam) ; } } else /* use a previously create morph and integrate it some more */ { printf("using previously create gcam...\n") ; gcam = (GCA_MORPH *)(transform->xform) ; GCAMrasToVox(gcam, mri_source) ; if (use_aseg) { GCAMinitLabels(gcam, mri_target) ; GCAMsetVariances(gcam, 1.0) ; mp.mri_dist_map = create_distance_transforms(mri_source, mri_target, NULL, 40.0, gcam) ; } else GCAMaddIntensitiesFromImage(gcam, mri_target) ; } if (gcam->width != mri_source->width || gcam->height != mri_source->height || gcam->depth != mri_source->depth) ErrorExit(ERROR_BADPARM, "%s: warning gcam (%d, %d, %d), doesn't match source vol (%d, %d, %d)", Progname, gcam->width, gcam->height, gcam->depth, mri_source->width, mri_source->height, mri_source->depth) ; mp.mri_diag = mri_source ; mp.diag_morph_from_atlas = 0 ; mp.diag_write_snapshots = 1 ; mp.diag_sample_type = use_aseg ? SAMPLE_NEAREST : SAMPLE_TRILINEAR ; mp.diag_volume = use_aseg ? GCAM_LABEL : GCAM_MEANS ; if (renormalize) GCAMnormalizeIntensities(gcam, mri_target) ; if (mp.write_iterations != 0) { char fname[STRLEN] ; MRI *mri_gca ; if (getenv("DONT_COMPRESS")) sprintf(fname, "%s_target.mgh", mp.base_name) ; else sprintf(fname, "%s_target.mgz", mp.base_name) ; if (mp.diag_morph_from_atlas == 0) { printf("writing target volume to %s...\n", fname) ; MRIwrite(mri_target, fname) ; sprintf(fname, "%s_target", mp.base_name) ; MRIwriteImageViews(mri_target, fname, IMAGE_SIZE) ; } else { if (use_aseg) mri_gca = GCAMwriteMRI(gcam, NULL, GCAM_LABEL) ; else { mri_gca = MRIclone(mri_source, NULL) ; GCAMbuildMostLikelyVolume(gcam, mri_gca) ; } printf("writing target volume to %s...\n", fname) ; MRIwrite(mri_gca, fname) ; sprintf(fname, "%s_target", mp.base_name) ; MRIwriteImageViews(mri_gca, fname, IMAGE_SIZE) ; MRIfree(&mri_gca) ; } } if (nozero) { printf("disabling zero nodes\n") ; GCAMignoreZero(gcam, mri_target) ; } mp.mri = mri_target ; if (mp.regrid == True && new_transform == 0) GCAMregrid(gcam, mri_target, PAD, &mp, &mri_source) ; mp.write_fname = out_fname ; GCAMregister(gcam, mri_source, &mp) ; // atlas is target, morph target into register with it if (apply_transform) { MRI *mri_aligned ; char fname[STRLEN] ; FileNameRemoveExtension(out_fname, fname) ; strcat(fname, ".mgz") ; mri_aligned = GCAMmorphToAtlas(mp.mri, gcam, NULL, -1, mp.diag_sample_type) ; printf("writing transformed output volume to %s...\n", fname) ; MRIwrite(mri_aligned, fname) ; MRIfree(&mri_aligned) ; } printf("writing warp vector field to %s\n", out_fname) ; GCAMvoxToRas(gcam) ; GCAMwrite(gcam, out_fname) ; GCAMrasToVox(gcam, mri_source) ; msec = TimerStop(&start) ; seconds = nint((float)msec/1000.0f) ; minutes = seconds / 60 ; seconds = seconds % 60 ; printf("registration took %d minutes and %d seconds.\n", minutes, seconds) ; exit(0) ; return(0) ; }
/* Actually no need to modify this function, since I will only use the float * type here, so the roundoff I added will never take effect. * What I need to modify is the MRIchangeType function! */ MRI *MRIlinearTransformInterpBSpline(MRI *mri_src, MRI *mri_dst, MATRIX *mA, int splinedegree) { int y1, y2, y3, width, height, depth ; VECTOR *v_X, *v_Y ; /* original and transformed coordinate systems */ MATRIX *mAinv ; /* inverse of mA */ double val, x1, x2, x3 ; MRI *mri_Bcoeff; mAinv = MatrixInverse(mA, NULL) ; /* will sample from dst back to src */ if (!mAinv) ErrorReturn(NULL, (ERROR_BADPARM, "MRIlinearTransformBSpline: xform is singular")) ; if (!mri_dst) mri_dst = MRIclone(mri_src, NULL) ; else MRIclear(mri_dst) ; /* set all values to zero */ if (mri_src->type != MRI_FLOAT) mri_Bcoeff = MRIchangeType(mri_src, MRI_FLOAT, 0, 1.0, 1); else mri_Bcoeff = MRIcopy(mri_src, NULL); /* convert between a representation based on image samples */ /* and a representation based on image B-spline coefficients */ if (SamplesToCoefficients(mri_Bcoeff, splinedegree)) { ErrorReturn(NULL, (ERROR_BADPARM, "Change of basis failed\n")); } printf("Direct B-spline Transform Finished. \n"); width = mri_src->width ; height = mri_src->height ; depth = mri_src->depth ; v_X = VectorAlloc(4, MATRIX_REAL) ; /* input (src) coordinates */ v_Y = VectorAlloc(4, MATRIX_REAL) ; /* transformed (dst) coordinates */ v_Y->rptr[4][1] = 1.0f ; for (y3 = 0 ; y3 < mri_dst->depth ; y3++) { V3_Z(v_Y) = y3 ; for (y2 = 0 ; y2 < mri_dst->height ; y2++) { V3_Y(v_Y) = y2 ; for (y1 = 0 ; y1 < mri_dst->width ; y1++) { V3_X(v_Y) = y1 ; MatrixMultiply(mAinv, v_Y, v_X) ; x1 = V3_X(v_X) ; x2 = V3_Y(v_X) ; x3 = V3_Z(v_X) ; if (x1 <= -0.5 || x1 >= (width - 0.5) || x2 <= -0.5 || x2 >= (height - 0.5) || x3 <= -0.5 || x3 >= (depth-0.5)) val = 0.0; else val = InterpolatedValue(mri_Bcoeff, x1, x2, x3, splinedegree); switch (mri_dst->type) { case MRI_UCHAR: if (val <-0.5) val = -0.5; if (val > 254.5) val = 254.5; MRIvox(mri_dst,y1,y2,y3) = (BUFTYPE)nint(val+0.5) ; break ; case MRI_SHORT: MRISvox(mri_dst,y1,y2,y3) = (short)nint(val+0.5) ; break ; case MRI_FLOAT: MRIFvox(mri_dst,y1,y2,y3) = (float)(val) ; break ; case MRI_INT: MRIIvox(mri_dst,y1,y2,y3) = nint(val+0.5) ; break ; default: ErrorReturn(NULL, (ERROR_UNSUPPORTED, "MRIlinearTransformBSpline: unsupported dst type %d", mri_dst->type)) ; break ; } } } } MatrixFree(&v_X) ; MatrixFree(&mAinv) ; MatrixFree(&v_Y) ; MRIfree(&mri_Bcoeff); return(mri_dst) ; }
int main(int argc, char *argv[]) { char **av, *in_vol, *out_vol; int ac, nargs; MRI *mri_in, *mri_out, *mri_tmp ; LTA *lta = 0; MATRIX *i_to_r_src = 0; /* src geometry of the input LTA */ MATRIX *V_to_V = 0; /* Final voxel-to-voxel transform */ MATRIX *r_to_i_dst = 0; /* dst geometry of the input LTA */ MATRIX *m_tmp = 0; MATRIX *i_to_r_reg = 0; /* i_to_r of the volume after registration */ MATRIX *r_to_i_out = 0; /* r_to_i of the final output volume */ VOL_GEOM vgm_in; int x, y, z; double maxV, minV, value; // MATRIX *i_to_r, *r_to_i; /* rkt: check for and handle version tag */ nargs = handle_version_option (argc, argv, "$Id: mri_transform_to_COR.c,v 1.8 2011/03/02 00:04:55 nicks Exp $", "$Name: stable5 $"); if (nargs && argc - nargs == 1) usage_exit (0); argc -= nargs; Progname = argv[0] ; ErrorInit(NULL, NULL, NULL) ; DiagInit(NULL, NULL, NULL) ; ac = argc ; av = argv ; for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++) { nargs = get_option(argc, argv) ; argc -= nargs ; argv += nargs ; } if (argc < 3) usage_exit(0) ; in_vol = argv[1] ; out_vol = argv[2] ; printf("reading volume from %s...\n", in_vol) ; mri_in = MRIread(in_vol) ; if (!mri_in) ErrorExit(ERROR_NOFILE, "%s: could not read MRI volume %s", Progname, in_vol) ; /* Convert mri_in to float type */ /* double would be more accurate */ if (mri_in->type != MRI_FLOAT) { printf("Input volume type is %d\n", mri_in->type); printf("Change input volume to float type for convenience and accuracy"); mri_tmp = MRIchangeType(mri_in, MRI_FLOAT, 0, 1.0, 1); MRIfree(&mri_in); mri_in = mri_tmp; //swap } /* Get input volume geometry, which is needed to compute i_to_r * and r_to_i of input volume. Note that i_to_r and r_to_i assumed * a certain prespecified c_r, c_a, c_s */ getVolGeom(mri_in, &vgm_in); maxV = -10000.0; minV = 10000.0; for (z=0; z < mri_in->depth; z++) for (y=0; y< mri_in->height; y++) for (x=0; x < mri_in->width; x++) { if (MRIFvox(mri_in, x, y, z) > maxV ) maxV = MRIFvox(mri_in, x, y,z) ; if (MRIFvox(mri_in, x, y, z) < minV ) minV = MRIFvox(mri_in, x, y,z) ; } printf("Input volume has max = %g, min =%g\n", maxV, minV); printf("Scale input volume by %g \n", scale); maxV = -10000.0; minV = 10000.0; for (z=0; z < mri_in->depth; z++) for (y=0; y< mri_in->height; y++) for (x=0; x < mri_in->width; x++) { MRIFvox(mri_in, x, y, z) *= scale; if (MRIFvox(mri_in, x, y, z) > maxV ) maxV = MRIFvox(mri_in, x, y,z) ; if (MRIFvox(mri_in, x, y, z) < minV ) minV = MRIFvox(mri_in, x, y,z) ; } printf("Input volume after scaling has max = %g, min =%g\n", maxV, minV); /* Try to compute the Voxel_to_Voxel transform from the input volume * and the registration target/reference volume! * If no registration is involved, vox_to_vox is simply identity */ /* Things become more complicated when allowing inverse transform */ if (transform_flag) { int transform_type; printf("INFO: Applying transformation from file %s...\n", transform_fname); transform_type = TransformFileNameType(transform_fname); /* Read in LTA transform file name */ if (transform_type == MNI_TRANSFORM_TYPE || transform_type == TRANSFORM_ARRAY_TYPE || transform_type == REGISTER_DAT || transform_type == FSLREG_TYPE ) { printf("Reading transform ...\n"); lta = LTAreadEx(transform_fname) ; if (!lta) ErrorExit(ERROR_NOFILE, "%s: could not read transform file %s", Progname, transform_fname) ; if (transform_type == FSLREG_TYPE) { if (lta_src == 0 || lta_dst == 0) { fprintf(stderr, "ERROR: fslmat does not have information on the src and dst volumes\n"); fprintf(stderr, "ERROR: you must give options '-src' and '-dst' to specify the src and dst volume infos for the registration\n"); } LTAmodifySrcDstGeom(lta, lta_src, lta_dst); // add src and dst information //The following is necessary to interpret FSLMAT correctly!!! LTAchangeType(lta, LINEAR_VOX_TO_VOX); } if (lta->xforms[0].src.valid == 0) { if (lta_src == 0) { fprintf(stderr, "The transform does not have the valid src volume info.\n"); fprintf(stderr, "Either you give src volume info by option -src or\n"); fprintf(stderr, "make the transform to have the valid src info.\n"); ErrorExit(ERROR_BAD_PARM, "Bailing out...\n"); } else { LTAmodifySrcDstGeom(lta, lta_src, NULL); // add src information } } if (lta->xforms[0].dst.valid == 0) { if (lta_dst == 0) { fprintf(stderr, "The transform does not have the valid dst volume info.\n"); fprintf(stderr, "Either you give src volume info by option -dst or\n"); fprintf(stderr, "make the transform to have the valid dst info.\n"); fprintf(stderr, "If the dst was average_305, then you can set\n"); fprintf(stderr, "environmental variable USE_AVERAGE305 true\n"); fprintf(stderr, "instead.\n"); ErrorExit(ERROR_BAD_PARM, "Bailing out...\n"); } else { LTAmodifySrcDstGeom(lta, NULL, lta_dst); // add dst information } } // The following procedure aims to apply an LTA computed from COR format to a volume in non-COR format, or vice versa, as long as they share the same RAS // first change to LINEAR RAS_TO_RAS using old info if (lta->type != LINEAR_RAS_TO_RAS) { LTAchangeType(lta, LINEAR_RAS_TO_RAS); } // now possiblly reset the src and dst if (lta_src != NULL) { //always trust the user LTAmodifySrcDstGeom(lta, lta_src, NULL); } if (lta_dst != NULL) { //always trust the user LTAmodifySrcDstGeom(lta, NULL, lta_dst); } if (lta->type == LINEAR_RAS_TO_RAS) { /* Convert it to VOX_TO_VOX */ /* VOXELsrc_to_VOXELdst = R2Vdst*R2Rlta*V2Rsrc */ /* Note whether the input should be identical to src or dst here depends * on whether the LTA here is the direct or inverse transform */ i_to_r_src = vg_i_to_r(<a->xforms[0].src); r_to_i_dst = vg_r_to_i(<a->xforms[0].dst); if (!r_to_i_dst || !i_to_r_src) ErrorExit(ERROR_BADFILE, "%s: failed to extract volume geometries from input LTA file",Progname); m_tmp = MatrixMultiply(lta->xforms[0].m_L, i_to_r_src, NULL); V_to_V = MatrixMultiply(r_to_i_dst, m_tmp, NULL); MatrixFree(&m_tmp); MatrixFree(&i_to_r_src); MatrixFree(&r_to_i_dst); } } else { fprintf(stderr, "unknown transform type in file %s\n", transform_fname); exit(1); } if (invert_flag) { /* Geometry of input volume should match that of the dst of the LTA */ if (MYvg_isEqual(<a->xforms[0].dst, &vgm_in) == 0) { ErrorExit(ERROR_BADFILE, "%s: dst volume of lta doesn't match that of input volume",Progname); } i_to_r_reg = vg_i_to_r(<a->xforms[0].src); if (!i_to_r_reg) ErrorExit(ERROR_BADFILE, "%s: failed to extract i_to_r of registered volume from LTA",Progname); m_tmp = MatrixInverse(V_to_V, NULL); if (!m_tmp) ErrorExit(ERROR_BADPARM, "%s: transform is singular!", Progname); MatrixFree(&V_to_V); V_to_V = m_tmp; } else { /* Geometry of input volume should match that of the src of the LTA */ if (MYvg_isEqual(<a->xforms[0].src, &vgm_in) == 0) { ErrorExit(ERROR_BADFILE, "%s: src volume of lta doesn't match that of input volume",Progname); } i_to_r_reg = vg_i_to_r(<a->xforms[0].dst); if (!i_to_r_reg) ErrorExit(ERROR_BADFILE, "%s: failed to extract i_to_r of registered volume from LTA",Progname); } } else { /* No registration transform need be applied */ V_to_V = MatrixIdentity(4, NULL); i_to_r_reg = extract_i_to_r(mri_in); if (!i_to_r_reg) ErrorExit(ERROR_BADFILE, "%s: failed to extract i_to_r from input volume",Progname); } /* Now need to find the vox-to-vox transformation between registered volume * (or input volume itself if no registration involved) and the output * volume, either in COR format or as the out-like volume */ /* Given a volume with a certain i_to_r, we need to compute the necessary * vox-to-voxel transform to change its i_to_r to like another volume. * The vox-to-vox is equal to R2V(r_to_i)_likevol*i_to_r_current_vol. */ if (out_like_fname) { mri_tmp = MRIread(out_like_fname) ; if (!mri_tmp) ErrorExit(ERROR_NOFILE, "%s: could not read template volume from %s",out_like_fname) ; /* out_type = mri_tmp->type; */ /* specify the out-type to float initially so as not to lose accuracy * during reslicing, will change type to correct type later. */ mri_out = MRIalloc(mri_tmp->width, mri_tmp->height, mri_tmp->depth, MRI_FLOAT) ; MRIcopyHeader(mri_tmp, mri_out) ; MRIfree(&mri_tmp); } else /* assume output is in COR format */ { mri_out = MRIalloc(256, 256, 256, MRI_FLOAT) ; /* out_type = MRI_UCHAR; */ /* Who says MRIlinearTransformInterp will change the header?? * I don't think so! */ //E/ set xyzc_ras to coronal ones.. - these'll get zorched //by MRIlinearTransformInterp() - copy again later - is there //any use in having them here now? yes, so we can pass mri_out //to the ras2vox fns. mri_out->imnr0 = 1; /* what's this? */ mri_out->imnr1 = 256; /* what's this? */ mri_out->thick = 1.0; mri_out->ps = 1.0; /* what's this? */ mri_out->xsize = mri_out->ysize = mri_out->zsize = 1.0; mri_out->xstart = mri_out->ystart = mri_out->zstart = -128.0; mri_out->xend = mri_out->yend = mri_out->zend = 128.0; mri_out->x_r =-1; mri_out->y_r = 0; mri_out->z_r = 0; mri_out->x_a = 0; mri_out->y_a = 0; mri_out->z_a = 1; mri_out->x_s = 0; mri_out->y_s =-1; mri_out->z_s = 0; /* In this case, the RAS itself is not fully determined, i.e., c_ras. * It's quite arbitrary, different values just change the final * sitting of the volume inside the RAS system. */ /* NO! The C_RAS has to be set correctly, depending which target * volume the previous Vox_to_Vox transformation assumes! * When a registration is involved, the target volume is either * the src of LTA (direct) or the dst (inverse transform). When * just change format, the target volume is the input itself!! */ if (transform_flag) { if (invert_flag) { mri_out->c_r = lta->xforms[0].src.c_r; mri_out->c_a = lta->xforms[0].src.c_a; mri_out->c_s = lta->xforms[0].src.c_s; } else { mri_out->c_r = lta->xforms[0].dst.c_r; mri_out->c_a = lta->xforms[0].dst.c_a; mri_out->c_s = lta->xforms[0].dst.c_s; } } else { mri_out->c_r = mri_in->c_r; mri_out->c_a = mri_in->c_a; mri_out->c_s = mri_in->c_s; } mri_out->ras_good_flag=1; /* What does this flag mean ? */ /* since output is just transformed input */ MRIcopyPulseParameters(mri_in, mri_out) ; } /* Compute the final input-to-output VOX_to_VOX transformation matrix */ r_to_i_out = extract_r_to_i(mri_out); m_tmp = MatrixMultiply(r_to_i_out, i_to_r_reg, NULL); V_to_V = MatrixMultiply(m_tmp, V_to_V, V_to_V); MatrixFree(&m_tmp); printf("InterpMethod = %d\n", InterpMethod); /* Modify the MyMRIlinearTr... if I want to implement my cubic-B-spline * interpolation method. Otherwise, unnecessary */ /* mri_out = MyMRIlinearTransformInterp(mri_in, mri_out, V_to_V, InterpMethod); */ if (InterpMethod == SAMPLE_BSPLINE) mri_out = MRIlinearTransformInterpBSpline(mri_in, mri_out, V_to_V, SplineDegree); else mri_out = MRIlinearTransformInterp(mri_in, mri_out, V_to_V, InterpMethod); maxV = -10000.0; minV = 10000.0; for (z=0; z < mri_out->depth; z++) for (y=0; y< mri_out->height; y++) for (x=0; x < mri_out->width; x++) { if (MRIFvox(mri_out, x, y, z) > maxV ) maxV = MRIFvox(mri_out, x, y,z) ; if (MRIFvox(mri_out, x, y, z) < minV ) minV = MRIFvox(mri_out, x, y,z) ; } if (autoscale) { noscale = 1; /* compute histogram of output volume */ HISTOGRAM *h, *hsmooth ; float fmin, fmax, val, peak, smooth_peak; int i, nbins, bin; fmin = minV; fmax = maxV; if (fmin < 0) fmin = 0; nbins = 256 ; h = HISTOalloc(nbins) ; hsmooth = HISTOcopy(h, NULL) ; HISTOclear(h, h) ; h->bin_size = (fmax-fmin)/255.0 ; for (i = 0 ; i < nbins ; i++) h->bins[i] = (i+1)*h->bin_size ; for (z=0; z < mri_out->depth; z++) for (y=0; y< mri_out->height; y++) for (x=0; x < mri_out->width; x++) { val = MRIFvox(mri_out, x, y, z); if (val <= 0) continue; bin = nint((val - fmin)/h->bin_size); if (bin >= h->nbins) bin = h->nbins-1; else if (bin < 0) bin = 0; h->counts[bin] += 1.0; } HISTOfillHoles(h) ; HISTOsmooth(h, hsmooth, 5) ; peak = hsmooth->bins[HISTOfindHighestPeakInRegion(h, 1, h->nbins)] ; // smooth_peak = // hsmooth->bins[HISTOfindHighestPeakInRegion(hsmooth, 1, hsmooth->nbins)] ; smooth_peak = hsmooth->bins[HISTOfindLastPeak(hsmooth, 5, 0.8)] ; /* bin = nint((smooth_peak - fmin)/hsmooth->bin_size) ; printf("Highest peak has count = %d\n", (int)hsmooth->counts[bin]); bin = nint((420 - fmin)/hsmooth->bin_size) ; printf("bin at 420 has count = %d\n", (int)hsmooth->counts[bin]); */ scale = 110.0/smooth_peak; printf("peak of output volume is %g, smooth-peak is %g, multiply by %g to scale it to 110\n", peak, smooth_peak, scale); for (z=0; z < mri_out->depth; z++) for (y=0; y< mri_out->height; y++) for (x=0; x < mri_out->width; x++) { val = MRIFvox(mri_out, x, y, z); MRIFvox(mri_out, x, y, z) = val*scale; } } printf("Output volume (before type-conversion) has max = %g, min =%g\n", maxV, minV); /* Finally change type to desired */ if (mri_out->type != out_type) { printf("Change output volume to type %d\n", out_type); /* I need to modify the MIRchangeType function to make sure * it does roundoff instead of simple truncation! */ /* Note if the last flag is set to 1, then it won't do scaling and small float numbers will become zero after convert to BYTE */ if (out_type == 0 && noscale == 1) { //convert data to UCHAR mri_tmp = MRIalloc(mri_out->width, mri_out->height, mri_out->depth, out_type) ; MRIcopyHeader(mri_out, mri_tmp); for (z=0; z < mri_out->depth; z++) for (y=0; y< mri_out->height; y++) for (x=0; x < mri_out->width; x++) { value = floor(MRIgetVoxVal(mri_out, x, y, z, 0) + 0.5); if (value < 0 ) value = 0; if (value > 255) value = 255; MRIvox(mri_tmp,x,y,z) = (unsigned char)value; } } else mri_tmp = MRIchangeType(mri_out, out_type, thred_low, thred_high, noscale); MRIfree(&mri_out); mri_out = mri_tmp; //swap } MRIwrite(mri_out, out_vol) ; MRIfree(&mri_in); MRIfree(&mri_out); if (lta_src) MRIfree(<a_src); if (lta_dst) MRIfree(<a_dst); MatrixFree(&V_to_V); if (!r_to_i_out) MatrixFree(&r_to_i_out); if (!i_to_r_reg) MatrixFree(&i_to_r_reg); return(0) ; /* for ansi */ }
int main(int argc, char *argv[]) { char **av ; int ac, nargs, n ; MRI *mri_src, *mri_dst = NULL, *mri_bias, *mri_orig, *mri_aseg = NULL ; char *in_fname, *out_fname ; int msec, minutes, seconds ; struct timeb start ; char cmdline[CMD_LINE_LEN] ; make_cmd_version_string (argc, argv, "$Id: mri_normalize.c,v 1.80 2012/10/16 21:38:35 nicks Exp $", "$Name: $", cmdline); /* rkt: check for and handle version tag */ nargs = handle_version_option (argc, argv, "$Id: mri_normalize.c,v 1.80 2012/10/16 21:38:35 nicks Exp $", "$Name: $"); if (nargs && argc - nargs == 1) { exit (0); } argc -= nargs; Progname = argv[0] ; ErrorInit(NULL, NULL, NULL) ; DiagInit(NULL, NULL, NULL) ; mni.max_gradient = MAX_GRADIENT ; ac = argc ; av = argv ; for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++) { nargs = get_option(argc, argv) ; argc -= nargs ; argv += nargs ; } if (argc < 3) { usage_exit(0) ; } if (argc < 1) { ErrorExit(ERROR_BADPARM, "%s: no input name specified", Progname) ; } in_fname = argv[1] ; if (argc < 2) { ErrorExit(ERROR_BADPARM, "%s: no output name specified", Progname) ; } out_fname = argv[2] ; if(verbose) { printf( "reading from %s...\n", in_fname) ; } mri_src = MRIread(in_fname) ; if (!mri_src) ErrorExit(ERROR_NO_FILE, "%s: could not open source file %s", Progname, in_fname) ; MRIaddCommandLine(mri_src, cmdline) ; if(nsurfs > 0) { MRI_SURFACE *mris ; MRI *mri_dist=NULL, *mri_dist_sup=NULL, *mri_ctrl, *mri_dist_one ; LTA *lta= NULL ; int i ; TRANSFORM *surface_xform ; if (control_point_fname) // do one pass with only file control points first { MRI3dUseFileControlPoints(mri_src, control_point_fname) ; mri_dst = MRI3dGentleNormalize(mri_src, NULL, DEFAULT_DESIRED_WHITE_MATTER_VALUE, NULL, intensity_above, intensity_below/2,1, bias_sigma, mri_not_control); } else { mri_dst = MRIcopy(mri_src, NULL) ; } for (i = 0 ; i < nsurfs ; i++) { mris = MRISread(surface_fnames[i]) ; if (mris == NULL) ErrorExit(ERROR_NOFILE,"%s: could not surface %s", Progname,surface_fnames[i]); surface_xform = surface_xforms[i] ; TransformInvert(surface_xform, NULL) ; if (surface_xform->type == MNI_TRANSFORM_TYPE || surface_xform->type == TRANSFORM_ARRAY_TYPE || surface_xform->type == REGISTER_DAT) { lta = (LTA *)(surface_xform->xform) ; #if 0 if (invert) { VOL_GEOM vgtmp; LT *lt; MATRIX *m_tmp = lta->xforms[0].m_L ; lta->xforms[0].m_L = MatrixInverse(lta->xforms[0].m_L, NULL) ; MatrixFree(&m_tmp) ; lt = <a->xforms[0]; if (lt->dst.valid == 0 || lt->src.valid == 0) { printf( "WARNING:***************************************************************\n"); printf( "WARNING:dst volume infor is invalid. Most likely produce wrong inverse.\n"); printf( "WARNING:***************************************************************\n"); } copyVolGeom(<->dst, &vgtmp); copyVolGeom(<->src, <->dst); copyVolGeom(&vgtmp, <->src); } #endif } if (stricmp(surface_xform_fnames[i], "identity.nofile") != 0) { MRIStransform(mris, NULL, surface_xform, NULL) ; } mri_dist_one = MRIcloneDifferentType(mri_dst, MRI_FLOAT) ; printf("computing distance transform\n") ; MRIScomputeDistanceToSurface(mris, mri_dist_one, mri_dist_one->xsize) ; if (i == 0) { mri_dist = MRIcopy(mri_dist_one, NULL) ; } else { MRIcombineDistanceTransforms(mri_dist_one, mri_dist, mri_dist) ; } // MRIminAbs(mri_dist_one, mri_dist, mri_dist) ; MRIfree(&mri_dist_one) ; } MRIscalarMul(mri_dist, mri_dist, -1) ; if (nonmax_suppress) { printf("computing nonmaximum suppression\n") ; mri_dist_sup = MRInonMaxSuppress(mri_dist, NULL, 0, 1) ; mri_ctrl = MRIcloneDifferentType(mri_dist_sup, MRI_UCHAR) ; MRIbinarize(mri_dist_sup, mri_ctrl, min_dist, CONTROL_NONE, CONTROL_MARKED) ; } else if (erode) { int i ; mri_ctrl = MRIcloneDifferentType(mri_dist, MRI_UCHAR) ; MRIbinarize(mri_dist, mri_ctrl, min_dist, CONTROL_NONE, CONTROL_MARKED) ; for (i = 0 ; i < erode ; i++) { MRIerode(mri_ctrl, mri_ctrl) ; } } else { mri_ctrl = MRIcloneDifferentType(mri_dist, MRI_UCHAR) ; MRIbinarize(mri_dist, mri_ctrl, min_dist, CONTROL_NONE, CONTROL_MARKED) ; } if (control_point_fname) { MRInormAddFileControlPoints(mri_ctrl, CONTROL_MARKED) ; } if (mask_sigma > 0) { MRI *mri_smooth, *mri_mag, *mri_grad ; mri_smooth = MRIgaussianSmooth(mri_dst, mask_sigma, 1, NULL) ; mri_mag = MRIcloneDifferentType(mri_dst, MRI_FLOAT) ; mri_grad = MRIsobel(mri_smooth, NULL, mri_mag) ; MRIbinarize(mri_mag, mri_mag, mask_thresh, 1, 0) ; MRImask(mri_ctrl, mri_mag, mri_ctrl, 0, CONTROL_NONE) ; MRIfree(&mri_grad) ; MRIfree(&mri_mag) ; MRIfree(&mri_smooth) ; } if (mask_orig_fname) { MRI *mri_orig ; mri_orig = MRIread(mask_orig_fname) ; MRIbinarize(mri_orig, mri_orig, mask_orig_thresh, 0, 1) ; MRImask(mri_ctrl, mri_orig, mri_ctrl, 0, CONTROL_NONE) ; MRIfree(&mri_orig) ; } if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON) { MRIwrite(mri_dist, "d.mgz"); MRIwrite(mri_dist_sup, "dm.mgz"); MRIwrite(mri_ctrl, "c.mgz"); } MRIeraseBorderPlanes(mri_ctrl, 4) ; if (aseg_fname) { mri_aseg = MRIread(aseg_fname) ; if (mri_aseg == NULL) { ErrorExit(ERROR_NOFILE, "%s: could not load aseg from %s", Progname, aseg_fname) ; } remove_nonwm_voxels(mri_ctrl, mri_aseg, mri_ctrl) ; MRIfree(&mri_aseg) ; } else { remove_surface_outliers(mri_ctrl, mri_dist, mri_dst, mri_ctrl) ; } mri_bias = MRIbuildBiasImage(mri_dst, mri_ctrl, NULL, 0.0) ; if (mri_dist) { MRIfree(&mri_dist) ; } if (mri_dist_sup) { MRIfree(&mri_dist_sup) ; } if (bias_sigma> 0) { MRI *mri_kernel = MRIgaussian1d(bias_sigma, -1) ; if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON) { MRIwrite(mri_bias, "b.mgz") ; } printf("smoothing bias field\n") ; MRIconvolveGaussian(mri_bias, mri_bias, mri_kernel) ; if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON) { MRIwrite(mri_bias, "bs.mgz") ; } MRIfree(&mri_kernel); } MRIfree(&mri_ctrl) ; mri_dst = MRIapplyBiasCorrectionSameGeometry (mri_dst, mri_bias, mri_dst, DEFAULT_DESIRED_WHITE_MATTER_VALUE) ; printf("writing normalized volume to %s\n", out_fname) ; MRIwrite(mri_dst, out_fname) ; exit(0) ; } // end if(surface_fname) if (!mriConformed(mri_src) && conform > 0) { printf("unconformed source detected - conforming...\n") ; mri_src = MRIconform(mri_src) ; } if (mask_fname) { MRI *mri_mask ; mri_mask = MRIread(mask_fname) ; if (!mri_mask) ErrorExit(ERROR_NOFILE, "%s: could not open mask volume %s.\n", Progname, mask_fname) ; MRImask(mri_src, mri_mask, mri_src, 0, 0) ; MRIfree(&mri_mask) ; } if (read_flag) { MRI *mri_ctrl ; double scale ; mri_bias = MRIread(bias_volume_fname) ; if (!mri_bias) ErrorExit (ERROR_BADPARM, "%s: could not read bias volume %s", Progname, bias_volume_fname) ; mri_ctrl = MRIread(control_volume_fname) ; if (!mri_ctrl) ErrorExit (ERROR_BADPARM, "%s: could not read control volume %s", Progname, control_volume_fname) ; MRIbinarize(mri_ctrl, mri_ctrl, 1, 0, 128) ; mri_dst = MRImultiply(mri_bias, mri_src, NULL) ; scale = MRImeanInLabel(mri_dst, mri_ctrl, 128) ; printf("mean in wm is %2.0f, scaling by %2.2f\n", scale, 110/scale) ; scale = 110/scale ; MRIscalarMul(mri_dst, mri_dst, scale) ; MRIwrite(mri_dst, out_fname) ; exit(0) ; } if(long_flag) { MRI *mri_ctrl ; double scale ; mri_bias = MRIread(long_bias_volume_fname) ; if (!mri_bias) ErrorExit (ERROR_BADPARM, "%s: could not read bias volume %s", Progname, long_bias_volume_fname) ; mri_ctrl = MRIread(long_control_volume_fname) ; if (!mri_ctrl) ErrorExit (ERROR_BADPARM, "%s: could not read control volume %s", Progname, long_control_volume_fname) ; MRIbinarize(mri_ctrl, mri_ctrl, 1, 0, CONTROL_MARKED) ; if (mri_ctrl->type != MRI_UCHAR) { MRI *mri_tmp ; mri_tmp = MRIchangeType(mri_ctrl, MRI_UCHAR, 0, 1,1); MRIfree(&mri_ctrl) ; mri_ctrl = mri_tmp ; } scale = MRImeanInLabel(mri_src, mri_ctrl, CONTROL_MARKED) ; printf("mean in wm is %2.0f, scaling by %2.2f\n", scale, 110/scale) ; scale = DEFAULT_DESIRED_WHITE_MATTER_VALUE/scale ; mri_dst = MRIscalarMul(mri_src, NULL, scale) ; MRIremoveWMOutliers(mri_dst, mri_ctrl, mri_ctrl, intensity_below/2) ; mri_bias = MRIbuildBiasImage(mri_dst, mri_ctrl, NULL, 0.0) ; MRIsoapBubble(mri_bias, mri_ctrl, mri_bias, 50, 1) ; MRIapplyBiasCorrectionSameGeometry(mri_dst, mri_bias, mri_dst, DEFAULT_DESIRED_WHITE_MATTER_VALUE); // MRIwrite(mri_dst, out_fname) ; // exit(0) ; } // end if(long_flag) if (grad_thresh > 0) { float thresh ; MRI *mri_mag, *mri_grad, *mri_smooth ; MRI *mri_kernel = MRIgaussian1d(.5, -1) ; mri_not_control = MRIcloneDifferentType(mri_src, MRI_UCHAR) ; switch (scan_type) { case MRI_MGH_MPRAGE: thresh = 15 ; break ; case MRI_WASHU_MPRAGE: thresh = 20 ; break ; case MRI_UNKNOWN: default: thresh = 12 ; break ; } mri_smooth = MRIconvolveGaussian(mri_src, NULL, mri_kernel) ; thresh = grad_thresh ; mri_mag = MRIcloneDifferentType(mri_src, MRI_FLOAT) ; mri_grad = MRIsobel(mri_smooth, NULL, mri_mag) ; MRIwrite(mri_mag, "m.mgz") ; MRIbinarize(mri_mag, mri_not_control, thresh, 0, 1) ; MRIwrite(mri_not_control, "nc.mgz") ; MRIfree(&mri_mag) ; MRIfree(&mri_grad) ; MRIfree(&mri_smooth) ; MRIfree(&mri_kernel) ; } #if 0 #if 0 if ((mri_src->type != MRI_UCHAR) || (!(mri_src->xsize == 1 && mri_src->ysize == 1 && mri_src->zsize == 1))) #else if (conform || (mri_src->type != MRI_UCHAR && conform > 0)) #endif { MRI *mri_tmp ; fprintf (stderr, "downsampling to 8 bits and scaling to isotropic voxels...\n") ; mri_tmp = MRIconform(mri_src) ; mri_src = mri_tmp ; } #endif if(aseg_fname) { printf("Reading aseg %s\n",aseg_fname); mri_aseg = MRIread(aseg_fname) ; if (mri_aseg == NULL) ErrorExit (ERROR_NOFILE, "%s: could not read aseg from file %s", Progname, aseg_fname) ; if (!mriConformed(mri_aseg)) { ErrorExit(ERROR_UNSUPPORTED, "%s: aseg volume %s must be conformed", Progname, aseg_fname) ; } } else { mri_aseg = NULL ; } if(verbose) { printf( "normalizing image...\n") ; } fflush(stdout); fflush(stderr); TimerStart(&start) ; if (control_point_fname) { MRI3dUseFileControlPoints(mri_src, control_point_fname) ; } // this just setup writing control-point volume saving if(control_volume_fname) { MRI3dWriteControlPoints(control_volume_fname) ; } /* first do a gentle normalization to get things in the right intensity range */ if(long_flag == 0) // if long, then this will already have been done with base control points { if(control_point_fname != NULL) /* do one pass with only file control points first */ mri_dst = MRI3dGentleNormalize(mri_src, NULL, DEFAULT_DESIRED_WHITE_MATTER_VALUE, NULL, intensity_above, intensity_below/2,1, bias_sigma, mri_not_control); else { mri_dst = MRIcopy(mri_src, NULL) ; } } fflush(stdout); fflush(stderr); if(mri_aseg) { MRI *mri_ctrl, *mri_bias ; int i ; printf("processing with aseg\n"); mri_ctrl = MRIclone(mri_aseg, NULL) ; for (i = 0 ; i < NWM_LABELS ; i++) { MRIcopyLabel(mri_aseg, mri_ctrl, aseg_wm_labels[i]) ; } printf("removing outliers in the aseg WM...\n") ; MRIremoveWMOutliersAndRetainMedialSurface(mri_dst, mri_ctrl, mri_ctrl, intensity_below) ; MRIbinarize(mri_ctrl, mri_ctrl, 1, CONTROL_NONE, CONTROL_MARKED) ; MRInormAddFileControlPoints(mri_ctrl, CONTROL_MARKED) ; if (interior_fname1) { MRIS *mris_interior1, *mris_interior2 ; mris_interior1 = MRISread(interior_fname1) ; if (mris_interior1 == NULL) ErrorExit(ERROR_NOFILE, "%s: could not read white matter surface from %s\n", Progname, interior_fname1) ; mris_interior2 = MRISread(interior_fname2) ; if (mris_interior2 == NULL) ErrorExit(ERROR_NOFILE, "%s: could not read white matter surface from %s\n", Progname, interior_fname2) ; add_interior_points(mri_ctrl, mri_dst, intensity_above, 1.25*intensity_below, mris_interior1, mris_interior2, mri_aseg, mri_ctrl) ; MRISfree(&mris_interior1) ; MRISfree(&mris_interior2) ; } if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON) { MRIwrite(mri_ctrl, "norm_ctrl.mgz") ; } printf("Building bias image\n"); fflush(stdout); fflush(stderr); mri_bias = MRIbuildBiasImage(mri_dst, mri_ctrl, NULL, 0.0) ; fflush(stdout); fflush(stderr); if (bias_sigma> 0) { printf("Smoothing with sigma %g\n",bias_sigma); MRI *mri_kernel = MRIgaussian1d(bias_sigma, -1) ; MRIconvolveGaussian(mri_bias, mri_bias, mri_kernel) ; MRIfree(&mri_kernel); fflush(stdout); fflush(stderr); } MRIfree(&mri_ctrl) ; MRIfree(&mri_aseg) ; printf("Applying bias correction\n"); mri_dst = MRIapplyBiasCorrectionSameGeometry (mri_dst, mri_bias, mri_dst, DEFAULT_DESIRED_WHITE_MATTER_VALUE) ; if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON) { MRIwrite(mri_dst, "norm_1.mgz") ; } fflush(stdout); fflush(stderr); } // if(mri_aseg) else { printf("processing without aseg, no1d=%d\n",no1d); if (!no1d) { printf("MRInormInit(): \n"); MRInormInit(mri_src, &mni, 0, 0, 0, 0, 0.0f) ; printf("MRInormalize(): \n"); mri_dst = MRInormalize(mri_src, NULL, &mni) ; if (!mri_dst) { no1d = 1 ; printf("1d normalization failed - trying no1d...\n") ; // ErrorExit(ERROR_BADPARM, "%s: normalization failed", Progname) ; } } if(no1d) { if ((file_only && nosnr) || ((gentle_flag != 0) && (control_point_fname != NULL))) { if (mri_dst == NULL) { mri_dst = MRIcopy(mri_src, NULL) ; } } else { if (nosnr) { if (interior_fname1) { MRIS *mris_interior1, *mris_interior2 ; MRI *mri_ctrl ; printf("computing initial normalization using surface interiors\n"); mri_ctrl = MRIcloneDifferentType(mri_src, MRI_UCHAR) ; mris_interior1 = MRISread(interior_fname1) ; if (mris_interior1 == NULL) ErrorExit(ERROR_NOFILE, "%s: could not read white matter surface from %s\n", Progname, interior_fname1) ; mris_interior2 = MRISread(interior_fname2) ; if (mris_interior2 == NULL) ErrorExit(ERROR_NOFILE, "%s: could not read white matter surface from %s\n", Progname, interior_fname2) ; add_interior_points(mri_ctrl, mri_dst, intensity_above, 1.25*intensity_below, mris_interior1, mris_interior2, mri_aseg, mri_ctrl) ; MRISfree(&mris_interior1) ; MRISfree(&mris_interior2) ; mri_bias = MRIbuildBiasImage(mri_dst, mri_ctrl, NULL, 0.0) ; if (bias_sigma> 0) { MRI *mri_kernel = MRIgaussian1d(bias_sigma, -1) ; MRIconvolveGaussian(mri_bias, mri_bias, mri_kernel) ; MRIfree(&mri_kernel); } mri_dst = MRIapplyBiasCorrectionSameGeometry (mri_src, mri_bias, mri_dst, DEFAULT_DESIRED_WHITE_MATTER_VALUE) ; MRIfree(&mri_ctrl) ; } else if (long_flag == 0) // no initial normalization specified { mri_dst = MRIcopy(mri_src, NULL) ; } } else { printf("computing initial normalization using SNR...\n") ; mri_dst = MRInormalizeHighSignalLowStd (mri_src, mri_dst, bias_sigma, DEFAULT_DESIRED_WHITE_MATTER_VALUE) ; } } if (!mri_dst) ErrorExit (ERROR_BADPARM, "%s: could not allocate volume", Progname) ; } } // else (not using aseg) fflush(stdout); fflush(stderr); if (file_only == 0) MRI3dGentleNormalize(mri_dst, NULL, DEFAULT_DESIRED_WHITE_MATTER_VALUE, mri_dst, intensity_above, intensity_below/2, file_only, bias_sigma, mri_not_control); mri_orig = MRIcopy(mri_dst, NULL) ; printf("\n"); printf("Iterating %d times\n",num_3d_iter); for (n = 0 ; n < num_3d_iter ; n++) { if(file_only) { break ; } printf( "---------------------------------\n"); printf( "3d normalization pass %d of %d\n", n+1, num_3d_iter) ; if (gentle_flag) MRI3dGentleNormalize(mri_dst, NULL, DEFAULT_DESIRED_WHITE_MATTER_VALUE, mri_dst, intensity_above/2, intensity_below/2, file_only, bias_sigma, mri_not_control); else MRI3dNormalize(mri_orig, mri_dst, DEFAULT_DESIRED_WHITE_MATTER_VALUE, mri_dst, intensity_above, intensity_below, file_only, prune, bias_sigma, scan_type, mri_not_control); } printf( "Done iterating ---------------------------------\n"); // this just setup writing control-point volume saving if(control_volume_fname) { MRI3dWriteControlPoints(control_volume_fname) ; } if(bias_volume_fname) { mri_bias = compute_bias(mri_src, mri_dst, NULL) ; printf("writing bias field to %s....\n", bias_volume_fname) ; MRIwrite(mri_bias, bias_volume_fname) ; MRIfree(&mri_bias) ; } if (verbose) { printf("writing output to %s\n", out_fname) ; } MRIwrite(mri_dst, out_fname) ; msec = TimerStop(&start) ; MRIfree(&mri_src); MRIfree(&mri_dst); seconds = nint((float)msec/1000.0f) ; minutes = seconds / 60 ; seconds = seconds % 60 ; printf( "3D bias adjustment took %d minutes and %d seconds.\n", minutes, seconds) ; exit(0) ; return(0) ; }
int main(int argc, char *argv[]) { char **av; MRI *mri_T1, *mri_tmp, *mri_ctrl, *mri_in, *mri_out; MRI *mri_snr, *mri_bias; MRI *mri_mask1 = NULL; MRI *mri_mask2 = NULL; int ac, nargs; int width, height, depth, x, y, z; int mask1_set = 0; int mask2_set = 0; int i, j, k, cx, cy, cz, count; LTA *lta = 0; int transform_type; double mean, std, value, src, bias, norm; // HISTOGRAM *h; // float bin_size; // int nbins, bin_no; double mean1, std1, mean2, std2, count1, count2, slope, offset; VOL_GEOM vgtmp; LT *lt = NULL; MATRIX *m_tmp = NULL; Progname = argv[0]; nargs = handle_version_option (argc, argv, "$Id: mri_normalize_tp2.c,v 1.8 2011/03/02 00:04:23 nicks Exp $", "$Name: stable5 $"); if (nargs && argc - nargs == 1) exit (0); argc -= nargs ; ac = argc ; av = argv ; for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++) { nargs = get_option(argc, argv) ; argc -= nargs ; argv += nargs ; } if (argc != 3) usage(1); if (tp1_ctrl_fname == NULL || tp1_T1_fname == NULL) { printf("Use options to specify ctrl volume and T1 volume for tp1\n"); usage(1); } mri_in = MRIread(argv[1]) ; if (!mri_in) ErrorExit(ERROR_BADPARM, "%s: could not read input volume %s", Progname, argv[1]) ; mri_T1 = MRIread(tp1_T1_fname) ; if (!mri_T1) ErrorExit(ERROR_BADPARM, "%s: could not read T1 volume for tp1 %s", Progname, tp1_T1_fname) ; mri_ctrl = MRIread(tp1_ctrl_fname) ; if (!mri_ctrl) ErrorExit(ERROR_BADPARM, "%s: could not read control points volume for tp1 %s", Progname, tp1_ctrl_fname) ; if ((mri_in->width != mri_T1->width) || (mri_in->height != mri_T1->height) || (mri_in->depth != mri_T1->depth) || (mri_in->width != mri_ctrl->width) || (mri_in->height != mri_ctrl->height) || (mri_in->depth != mri_ctrl->depth) ) ErrorExit (ERROR_BADPARM, "%s: three input volumes have different sizes \n", Progname); if (mask1_fname) { mri_mask1 = MRIread(mask1_fname) ; if (!mri_mask1) ErrorExit(ERROR_BADPARM, "%s, could not read mask volume for tp1 %s", Progname, mask1_fname); mask1_set = 1; if ((mri_mask1->width != mri_in->width) || (mri_mask1->height != mri_in->height) || (mri_mask1->depth != mri_in->depth)) ErrorExit (ERROR_BADPARM, "%s: mask volumes have different sizes than other volumes \n", Progname); } if (mask2_fname) { mri_mask2 = MRIread(mask2_fname) ; if (!mri_mask2) ErrorExit (ERROR_BADPARM, "%s, could not read mask volume for tp2 %s", Progname, mask2_fname); mask2_set = 1; if ((mri_mask2->width != mri_T1->width) || (mri_mask2->height != mri_T1->height) || (mri_mask2->depth != mri_T1->depth) ) ErrorExit (ERROR_BADPARM, "%s: mask volumes have different sizes than other volumes \n", Progname); } width = mri_in->width ; height = mri_in->height ; depth = mri_in->depth ; //nbins = 200; //h = HISTOalloc(nbins); mri_out = MRIclone(mri_in, NULL) ; /* Read LTA transform and apply it to mri_ctrl */ if (xform_fname != NULL) { // read transform transform_type = TransformFileNameType(xform_fname); if (transform_type == MNI_TRANSFORM_TYPE || transform_type == TRANSFORM_ARRAY_TYPE || transform_type == REGISTER_DAT || transform_type == FSLREG_TYPE ) { printf("Reading transform ...\n"); lta = LTAreadEx(xform_fname) ; if (!lta) ErrorExit(ERROR_NOFILE, "%s: could not read transform file %s", Progname, xform_fname) ; if (transform_type == FSLREG_TYPE) { if (lta_src == 0 || lta_dst == 0) { fprintf (stderr, "ERROR: fslmat does not have information " "on the src and dst volumes\n"); fprintf (stderr, "ERROR: you must give options '-lta_src' and " "'-lta_dst' to specify the src and dst volume infos\n"); } LTAmodifySrcDstGeom (lta, lta_src, lta_dst); // add src and dst information LTAchangeType(lta, LINEAR_VOX_TO_VOX); //this is necessary } if (lta->xforms[0].src.valid == 0) { if (lta_src == 0) { fprintf (stderr, "The transform does not have the valid src volume info.\n"); fprintf (stderr, "Either you give src volume info by option -lta_src or\n"); fprintf(stderr, "make the transform to have the valid src info.\n"); ErrorExit(ERROR_BAD_PARM, "Bailing out...\n"); } else { LTAmodifySrcDstGeom(lta, lta_src, NULL); // add src information // getVolGeom(lta_src, <->src); } } if (lta->xforms[0].dst.valid == 0) { if (lta_dst == 0) { fprintf (stderr, "The transform does not have the valid dst volume info.\n"); fprintf (stderr, "Either you give src volume info by option -lta_dst or\n"); fprintf (stderr, "make the transform to have the valid dst info.\n"); fprintf (stderr, "If the dst was average_305, then you can set\n"); fprintf (stderr, "environmental variable USE_AVERAGE305 true\n"); fprintf (stderr, "without giving the dst volume for RAS-to-RAS transform.\n"); ErrorExit(ERROR_BAD_PARM, "Bailing out...\n"); } else { LTAmodifySrcDstGeom(lta, NULL, lta_dst); // add dst information } } } else { ErrorExit (ERROR_BADPARM, "transform is not of MNI, nor Register.dat, nor FSLMAT type"); } if (invert) { m_tmp = lta->xforms[0].m_L ; lta->xforms[0].m_L = MatrixInverse(lta->xforms[0].m_L, NULL) ; MatrixFree(&m_tmp) ; lt = <a->xforms[0]; if (lt->dst.valid == 0 || lt->src.valid == 0) { fprintf (stderr, "WARNING:***********************************************\n"); fprintf (stderr, "WARNING: dst volume infor is invalid. " "Most likely produce wrong inverse.\n"); fprintf (stderr, "WARNING:***********************************************\n"); } copyVolGeom(<->dst, &vgtmp); copyVolGeom(<->src, <->dst); copyVolGeom(&vgtmp, <->src); } // LTAchangeType(lta, LINEAR_VOX_TO_VOX); /* apply lta to the ctrl volume */ mri_tmp = MRIalloc(mri_ctrl->width, mri_ctrl->height, mri_ctrl->depth, mri_ctrl->type) ; MRIcopyHeader(mri_in, mri_tmp) ; // this function doesn't do NEAREST at all!! // I found the bug, in LTAtransformInterp() mri_tmp = LTAtransformInterp(mri_ctrl, mri_tmp, lta, SAMPLE_NEAREST); MRIfree(&mri_ctrl); mri_ctrl = mri_tmp; if (mask1_fname != NULL && mask2_fname == NULL) { printf("map mask for tp1 to get mask for tp2 ...\n"); mri_mask2 = MRIalloc(mri_in->width, mri_in->height, mri_in->depth, mri_mask1->type) ; MRIcopyHeader(mri_in, mri_mask2) ; mri_mask2 = LTAtransformInterp(mri_mask1, mri_mask2, lta, SAMPLE_NEAREST); mask2_set = 1; if (debug_flag) MRIwrite(mri_mask2, "mri_mask2.mgz"); } else if (mask2_fname != NULL && mask1_fname == NULL) { printf("map mask for tp2 to get mask for tp1 ...\n"); //need to invert lta first m_tmp = lta->xforms[0].m_L ; lta->xforms[0].m_L = MatrixInverse(lta->xforms[0].m_L, NULL) ; MatrixFree(&m_tmp) ; lt = <a->xforms[0]; copyVolGeom(<->dst, &vgtmp); copyVolGeom(<->src, <->dst); copyVolGeom(&vgtmp, <->src); mri_mask1 = MRIalloc(mri_T1->width, mri_T1->height, mri_T1->depth, mri_mask2->type) ; MRIcopyHeader(mri_T1, mri_mask1) ; mri_mask1 = LTAtransformInterp(mri_mask2, mri_mask1, lta, SAMPLE_NEAREST); mask1_set = 1; if (debug_flag) MRIwrite(mri_mask1, "mri_mask1.mgz"); } if (lta_src) MRIfree(<a_src); if (lta_dst) MRIfree(<a_dst); if (lta) LTAfree(<a); } /* if (xform_fname != NULL) */ if (debug_flag) { // MRIwrite(mri_snr, "snr.mgz"); MRIwrite(mri_ctrl, "ctrl.mgz"); } if (mask1_set == 0) { //create mask1 mri_mask1 = MRIalloc(mri_T1->width, mri_T1->height, mri_T1->depth, MRI_UCHAR) ; for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (MRIgetVoxVal(mri_T1, x, y, z, 0) < noise_threshold) { MRIvox(mri_mask1,x,y,z) = 0; } else MRIvox(mri_mask1,x,y,z) = 1; } } if (mask2_set == 0) { //create mask2 mri_mask2 = MRIalloc(mri_in->width, mri_in->height, mri_in->depth, MRI_UCHAR) ; for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (MRIgetVoxVal(mri_in, x, y, z, 0) < noise_threshold) { MRIvox(mri_mask2,x,y,z) = 0; } else MRIvox(mri_mask2,x,y,z) = 1; } } #if 0 /* compute the mean and std of T1 volume */ /* Using only high SNR points */ mri_snr = MRIalloc(mri_T1->width, mri_T1->height, mri_T1->depth, MRI_FLOAT) ; MRIcopyHeader(mri_T1, mri_snr) ; h->bin_size = bin_size = 0.5; for (bin_no = 0; bin_no < nbins; bin_no++) h->bins[bin_no] = (bin_no)*bin_size; for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (MRIgetVoxVal(mri_T1, x, y, z, 0) < noise_threshold) { MRIFvox(mri_snr,x,y,z) = 0; continue; } mean = 0; std = 0; count = 0; for (i=-1; i<=1; i++) for (j=-1; j<=1; j++) for (k=-1;k<=1;k++) { cx = x+i; cy = y+j, cz = z+k; if (cx < 0 || cx >= width || cy < 0 || cy >= height || cz < 0 || cz >= depth) continue; count++; value = MRIgetVoxVal(mri_T1, cx, cy, cz, 0); mean += value; std += value*value; } mean /= (count + 1e-30); std /= (count + 1e-30); std = std - mean *mean; if (std <= 0) std = 0; value = mean/sqrt(std); MRIFvox(mri_snr,x,y,z) = value; bin_no = nint((float)value/(float)bin_size); if (bin_no >= nbins) bin_no = nbins - 1; h->counts[bin_no]++; } for (num = 0.0f, b = h->nbins - 1; b >= 1; b --) { num += h->counts[b]; if (num > 20000) /* this may make me only use WM points, is it good to use only WM to compute scale of intensity?? */ break; } printf("using SNR threshold %2.3f at bin %d\n", h->bins[b], b); mean1 = 0; std1 = 0; count1 = 0; for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (MRIgetVoxVal(mri_T1, x, y, z, 0) < noise_threshold) { continue; } value = MRIFvox(mri_snr,x,y,z); if (value < h->bins[b]) continue; value = MRIgetVoxVal(mri_T1, x, y, z, 0); count1++; mean1 += value; std1 += value*value; } MRIfree(&mri_snr); #else printf("compute mean and std of tp1 volume within masked area...\n"); mean1 = 0; std1 = 0; count1 = 0; for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (MRIgetVoxVal(mri_mask1, x, y, z, 0) <= 1e-30) { continue; } value = MRIgetVoxVal(mri_T1, x, y, z, 0); count1++; mean1 += value; std1 += value*value; } #endif mean1 /= (count1 + 1e-30); std1 /= (count1 + 1e-30); std1 = std1 - mean1*mean1; if (std1 <= 0) printf("warning: negative std for T1 volume. \n"); else printf("mean and variance for tp1 volume are %g and %g\n", mean1, std1); printf("now compute SNR and stats for input volume ... \n"); mri_snr = MRIalloc(mri_in->width, mri_in->height, mri_in->depth, MRI_FLOAT) ; MRIcopyHeader(mri_in, mri_snr) ; //HISTOclear(h,h); //h->bin_size = bin_size = 0.5; //for (bin_no = 0; bin_no < nbins; bin_no++) // h->bins[bin_no] = (bin_no)*bin_size; for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (MRIgetVoxVal(mri_in, x, y, z, 0) < noise_threshold) { MRIFvox(mri_snr,x,y,z) = 0; continue; } mean = 0; std = 0; count = 0; for (i=-1; i<=1; i++) for (j=-1; j<=1; j++) for (k=-1;k<=1;k++) { cx = x+i; cy = y+j, cz = z+k; if (cx < 0 || cx >= width || cy < 0 || cy >= height || cz < 0 || cz >= depth) continue; count++; value = MRIgetVoxVal(mri_in, cx, cy, cz, 0); mean += value; std += value*value; } mean /= (count + 1e-30); std /= (count + 1e-30); std = std - mean *mean; if (std <= 0) std = 0; value = mean/sqrt(std); MRIFvox(mri_snr,x,y,z) = value; //bin_no = nint((float)value/(float)bin_size); //if (bin_no >= nbins) bin_no = nbins - 1; //h->counts[bin_no]++; } #if 0 for (num = 0.0f, b = h->nbins - 1; b >= 1; b --) { num += h->counts[b]; if (num > 20000) /* this may make me only use WM points, is it good to use only WM to compute scale of intensity?? */ break; } printf("using SNR threshold %2.3f at bin %d\n", h->bins[b], b); mean2 = 0; std2 = 0; count2 = 0; for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (MRIgetVoxVal(mri_in, x, y, z, 0) < noise_threshold) { continue; } value = MRIFvox(mri_snr,x,y,z); if (value >= h->bins[b]) { count2++; mean2 += value; std2 += value*value; } } #else printf("compute mean and std of tp2 volume within masked area\n"); /* somehow mri_watershed seems to leave some unzero voxels around image border, so I will skip image boundaries no, that's not a problem of most recent mri_watershed; something wrong previously */ mean2 = 0; std2 = 0; count2 = 0; for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (MRIgetVoxVal(mri_mask2, x, y, z, 0) <= 1e-30) { continue; } value = MRIgetVoxVal(mri_in, x, y, z, 0); count2++; mean2 += value; std2 += value*value; } #endif mean2 /= (count2 + 1e-30); std2 /= (count2 + 1e-30); std2 = std2 - mean2*mean2; if (std2 <= 0) printf("warning: negative std for input volume. \n"); else printf("mean and variance for input tp2 volume are %g and %g\n", mean2, std2); //compute intensity scale slope = sqrt(std1/std2); offset = mean1 - slope*mean2; printf("scale input volume by %g x + %g\n", slope, offset); // first change mri_in to FLOAT type mri_tmp = MRIchangeType(mri_in, MRI_FLOAT, 0, 1.0, 1); MRIfree(&mri_in); mri_in = mri_tmp; for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { value = MRIFvox(mri_in, x, y, z); MRIFvox(mri_in, x, y, z) = value*slope + offset; } // printf("compute SNR map of tp2 volume\n"); //already done above // mri_snr = MRIalloc(mri_ctrl->width, // mri_ctrl->height, mri_ctrl->depth, MRI_FLOAT) ; for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (MRIgetVoxVal(mri_in, x, y, z, 0) < noise_threshold) { // MRIFvox(mri_snr,x,y,z) = 0; continue; } value = MRIFvox(mri_snr,x,y,z); if (value < 20) MRIvox(mri_ctrl, x, y, z) = 0; else if (MRIvox(mri_ctrl, x, y, z) > 0) { MRIvox(mri_ctrl, x, y, z) = 1; } } if (debug_flag) { MRIwrite(mri_snr, "snr.mgz"); // MRIwrite(mri_ctrl, "ctrl.mgz"); } // SNR >= 20 seems a good threshold // Now use ctrl points to normalize tp2 printf("normalize tp2...\n"); mri_bias = MRIbuildBiasImage(mri_in, mri_ctrl, NULL, bias_sigma) ; for (z = 0 ; z < depth ; z++) { for (y = 0 ; y < height ; y++) { for (x = 0 ; x < width ; x++) { src = MRIgetVoxVal(mri_in, x, y, z, 0) ; bias = MRIgetVoxVal(mri_bias, x, y, z, 0) ; if (!bias) /* should never happen */ norm = (float)src ; else norm = (float)src * 110.0 / (float)bias ; if (norm > 255.0f && mri_out->type == MRI_UCHAR) norm = 255.0f ; else if (norm < 0.0f && mri_out->type == MRI_UCHAR) norm = 0.0f ; MRIsetVoxVal(mri_out, x, y, z, 0, norm) ; } } } printf("writing normalized volume to %s...\n", argv[2]) ; MRIwrite(mri_out, argv[2]); MRIfree(&mri_in); MRIfree(&mri_bias); MRIfree(&mri_out); MRIfree(&mri_T1); MRIfree(&mri_ctrl); MRIfree(&mri_snr); //HISTOfree(&h); exit(0); } /* end main() */
int main(int argc, char *argv[]) { char **av, *in_fname; int ac, nargs, i, j, x, y, z, width, height, depth; MRI *mri_flash[MAX_IMAGES], *mri_label, *mri_mask, *mri_tmp; int msec, minutes, seconds, nvolumes, nvolumes_total ; struct timeb start ; float max_val, min_val, value; float *LDAmean1, *LDAmean2, *LDAweight; int label; double sum_white, sum_gray; int count_white, count_gray; /* rkt: check for and handle version tag */ nargs = handle_version_option (argc, argv, "$Id: mri_ms_LDA.c,v 1.4 2011/03/02 00:04:23 nicks Exp $", "$Name: $"); if (nargs && argc - nargs == 1) exit (0); argc -= nargs; Progname = argv[0] ; ErrorInit(NULL, NULL, NULL) ; DiagInit(NULL, NULL, NULL) ; TimerStart(&start) ; ac = argc ; av = argv ; for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++) { nargs = get_option(argc, argv) ; argc -= nargs ; argv += nargs ; } if (argc < 2) usage_exit(1) ; printf("command line parsing finished\n"); if (have_weight == 0 && ldaflag == 0) { printf("Use -lda option to specify two class labels to optimize CNR on \n"); usage_exit(0); } if (have_weight == 0 && label_fname == NULL) { printf("Use -label option to specify file for segmentation \n"); usage_exit(0); } if (have_weight == 1 && weight_fname == NULL) { printf("Use -weight option to specify file for input LDA weights \n") ; usage_exit(0); } if (have_weight == 1 && synth_fname == NULL) { printf("Use -synth option to specify file for output synthesized volume \n") ; usage_exit(0); } ////////////////////////////////////////////////////////////////////////////////// /*** Read in the input multi-echo volumes ***/ nvolumes = 0 ; for (i = 1 ; i < argc; i++) { in_fname = argv[i] ; printf("reading %s...\n", in_fname) ; mri_flash[nvolumes] = MRIread(in_fname) ; if (mri_flash[nvolumes] == NULL) ErrorExit(ERROR_NOFILE, "%s: could not read volume %s", Progname, in_fname) ; /* conform will convert all data to UCHAR, which will reduce data resolution*/ printf("%s read in. \n", in_fname) ; if (conform) { printf("embedding and interpolating volume\n") ; mri_tmp = MRIconform(mri_flash[nvolumes]) ; MRIfree(&mri_flash[nvolumes]); mri_flash[nvolumes] = mri_tmp ; } /* Change all volumes to float type for convenience */ if (mri_flash[nvolumes]->type != MRI_FLOAT) { printf("Volume %d type is %d\n", nvolumes+1, mri_flash[nvolumes]->type); printf("Change data to float type \n"); mri_tmp = MRIchangeType(mri_flash[nvolumes], MRI_FLOAT, 0, 1.0, 1); MRIfree(&mri_flash[nvolumes]); mri_flash[nvolumes] = mri_tmp; //swap } nvolumes++ ; } printf("All data read in\n"); /////////////////////////////////////////////////////////////////////////// nvolumes_total = nvolumes ; /* all volumes read in */ for (i = 0 ; i < nvolumes ; i++) { for (j = i+1 ; j < nvolumes ; j++) { if ((mri_flash[i]->width != mri_flash[j]->width) || (mri_flash[i]->height != mri_flash[j]->height) || (mri_flash[i]->depth != mri_flash[j]->depth)) ErrorExit(ERROR_BADPARM, "%s:\nvolumes %d (type %d) and %d (type %d) don't match (%d x %d x %d) vs (%d x %d x %d)\n", Progname, i, mri_flash[i]->type, j, mri_flash[j]->type, mri_flash[i]->width, mri_flash[i]->height, mri_flash[i]->depth, mri_flash[j]->width, mri_flash[j]->height, mri_flash[j]->depth) ; } } width = mri_flash[0]->width; height = mri_flash[0]->height; depth = mri_flash[0]->depth; if (label_fname != NULL) { mri_label = MRIread(label_fname); if (!mri_label) ErrorExit(ERROR_NOFILE, "%s: could not read input volume %s\n", Progname, label_fname); if ((mri_label->width != mri_flash[0]->width) || (mri_label->height != mri_flash[0]->height) || (mri_label->depth != mri_flash[0]->depth)) ErrorExit(ERROR_BADPARM, "%s: label volume size doesn't match data volumes\n", Progname); /* if(mri_label->type != MRI_UCHAR) ErrorExit(ERROR_BADPARM, "%s: label volume is not UCHAR type \n", Progname); */ } if (mask_fname != NULL) { mri_mask = MRIread(mask_fname); if (!mri_mask) ErrorExit(ERROR_NOFILE, "%s: could not read input volume %s\n", Progname, mask_fname); if ((mri_mask->width != mri_flash[0]->width) || (mri_mask->height != mri_flash[0]->height) || (mri_mask->depth != mri_flash[0]->depth)) ErrorExit(ERROR_BADPARM, "%s: mask volume size doesn't macth data volumes\n", Progname); if (mri_mask->type != MRI_UCHAR) ErrorExit(ERROR_BADPARM, "%s: mask volume is not UCHAR type \n", Progname); } else { if (have_weight == 1) noise_threshold = - 1e20; printf("Threshold input vol1 at %g to create mask \n", noise_threshold); printf("this threshold is useful to process skull-stripped data \n"); mri_mask = MRIalloc(mri_flash[0]->width, mri_flash[0]->height, mri_flash[0]->depth, MRI_UCHAR); MRIcopyHeader(mri_flash[0], mri_mask); /* Simply set mask to be 1 everywhere */ for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if ((float)MRIgetVoxVal(mri_flash[0], x, y,z,0) < noise_threshold) MRIvox(mri_mask, x, y,z) = 0; else MRIvox(mri_mask, x, y,z) = 1; } } /* Normalize input volumes */ if (normflag) { printf("Normalize input volumes to zero mean, variance 1\n"); for (i=0; i <nvolumes_total; i++) { mri_flash[i] = MRInormalizeXH(mri_flash[i], mri_flash[i], mri_mask); } printf("Normalization done.\n"); } if (0) { printf("Using both hemi-sphere by changing rh-labels\n"); for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { label = (int)MRIgetVoxVal(mri_label, x, y,z,0); if (label == 41) /* white matter */ MRIsetVoxVal(mri_label, x, y, z, 0, 2); else if (label == 42) /* gm */ MRIsetVoxVal(mri_label, x, y, z, 0, 3); } } if (debug_flag && window_flag) { /* Limit LDA to a local window */ printf("Local window size = %d\n", window_size); window_size /= 2; for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (MRIvox(mri_mask, x, y,z) == 0) continue; if (z < (Gz - window_size) || z >(Gz + window_size) || y <(Gy - window_size) || y > (Gy + window_size) || x < (Gx - window_size) || x > (Gx + window_size)) MRIvox(mri_mask, x, y,z) = 0; } } LDAmean1 = (float *)malloc(nvolumes_total*sizeof(float)); LDAmean2 = (float *)malloc(nvolumes_total*sizeof(float)); LDAweight = (float *)malloc(nvolumes_total*sizeof(float)); if (have_weight) { printf("Read in LDA weights from weight-file\n"); input_weights_to_file(LDAweight, weight_fname, nvolumes_total); } else { /* compute LDA weights */ printf("Compute LDA weights to maximize CNR for region %d and region %d\n", class1, class2); /* Compute class means */ update_LDAmeans(mri_flash, mri_label, mri_mask, LDAmean1, LDAmean2, nvolumes_total, class1, class2); printf("class means computed \n"); /* Compute Fisher's LDA weights */ computeLDAweights(LDAweight, mri_flash, mri_label, mri_mask, LDAmean1, LDAmean2, nvolumes_total, class1, class2); if (weight_fname != NULL) { output_weights_to_file(LDAweight, weight_fname, nvolumes_total); } } printf("LDA weights are: \n"); for (i=0; i < nvolumes_total; i++) { printf("%g ", LDAweight[i]); } printf("\n"); if (synth_fname != NULL) { /* linear projection of input volumes to a 1D volume */ min_val = 10000.0; max_val = -10000.0; for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (whole_volume == 0 && MRIvox(mri_mask, x, y, z) == 0) continue; value = 0.0; for (i=0; i < nvolumes_total; i++) { value += MRIFvox(mri_flash[i], x, y, z)*LDAweight[i]; } // if(value < 0) value = 0; if (max_val < value) max_val = value; if (min_val > value) min_val = value; /* Borrow mri_flash[0] to store the float values first */ MRIFvox(mri_flash[0], x, y, z) = value; } printf("max_val = %g, min_val = %g \n", max_val, min_val); /* Check to make sure class1 has higher intensity than class2 */ if (have_weight == 0) { sum_white =0; count_white = 0; sum_gray = 0; count_gray = 0; for (z=0; z < depth; z++) { if (count_white > 300 && count_gray > 300) break; for (y=0; y< height; y++) { for (x=0; x < width; x++) { if ((int)MRIgetVoxVal(mri_label, x, y,z,0) == class1) { sum_white += MRIFvox(mri_flash[0], x, y, z); count_white += 1; } else if ((int)MRIgetVoxVal(mri_label, x, y,z,0) == class2) { sum_gray += MRIFvox(mri_flash[0], x, y, z); count_gray += 1; } } } } if (count_white > 1 && count_gray > 1) { if (sum_white *count_gray < sum_gray*count_white) { for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (whole_volume == 0 && MRIvox(mri_mask, x, y, z) == 0) continue; value = MRIFvox(mri_flash[0], x, y, z); MRIFvox(mri_flash[0], x, y, z) = max_val - value; } max_val = max_val - min_val; min_val = 0; } } } /* The following is copied to be consistent with mri_synthesize */ /* Don't know why add min_val, minus should make more sense */ for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (whole_volume == 0 && MRIvox(mri_mask, x, y, z) == 0) { MRIFvox(mri_flash[0], x, y, z) = 0; /*background always set to 0 */ continue; } /* Borrow mri_flash[0] to store the float values first */ if (shift_value > 0) { value = MRIFvox(mri_flash[0], x, y, z) + shift_value; if (value < 0) value = 0; MRIFvox(mri_flash[0], x, y, z) = value; } else if (mask_fname != NULL) MRIFvox(mri_flash[0], x, y, z) -= min_val; } MRIfree(&mri_mask); if (mri_flash[0]->type == out_type) { mri_mask = MRIcopy(mri_flash[0], mri_mask); } else { mri_mask = MRIchangeType(mri_flash[0], out_type, 0.1, 0.99, 0); } /* Scale output to [0, 255] */ if (0) { for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (whole_volume == 0 && MRIvox(mri_mask, x, y, z) == 0) continue; value = (MRIFvox(mri_flash[0], x, y, z) - min_val)*255.0/(max_val - min_val) + 0.5; /* +0.5 for round-off */ if (value > 255.0) value = 255.0; if (value < 0) value = 0; /* Borrow mri_flash[0] to store the float values first */ MRIvox(mri_mask, x, y, z) = (BUFTYPE) value; } } /* Output synthesized volume */ MRIwrite(mri_mask, synth_fname); } free(LDAmean1); free(LDAmean2); free(LDAweight); msec = TimerStop(&start) ; seconds = nint((float)msec/1000.0f) ; minutes = seconds / 60 ; seconds = seconds % 60 ; printf("LDA took %d minutes and %d seconds.\n", minutes, seconds) ; MRIfree(&mri_mask); if (label_fname) MRIfree(&mri_label); for (i=0; i < nvolumes_total; i++) { MRIfree(&mri_flash[i]); } exit(0); }
int main(int argc, char *argv[]) { char **av, *in_fname; int ac, nargs, i, j, x, y, z, width, height, depth; MRI *mri_flash[MAX_IMAGES], *mri_label, *mri_mask; int index; int msec, minutes, seconds, nvolumes, nvolumes_total ; struct timeb start ; float max_val, min_val, value; float *LDAweight = NULL; float **LDAmeans = NULL; /* Centroid for each considered class */ float *classSize =NULL; /* relative size of each class */ MATRIX **SWs; /* Within class scatter-matrix for each considered class */ MATRIX *AdjMatrix; /* Adjacency matrix of all classes */ FILE *fp; int num_classes; double cnr; /* rkt: check for and handle version tag */ nargs = handle_version_option (argc, argv, "$Id: mri_ms_compute_CNR.c,v 1.10 2011/03/02 00:04:55 nicks Exp $", "$Name: $"); if (nargs && argc - nargs == 1) exit (0); argc -= nargs; Progname = argv[0] ; ErrorInit(NULL, NULL, NULL) ; DiagInit(NULL, NULL, NULL) ; TimerStart(&start) ; ac = argc ; av = argv ; for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++) { nargs = get_option(argc, argv) ; argc -= nargs ; argv += nargs ; } if (argc < 2) usage_exit(1) ; printf("command line parsing finished\n"); if (label_fname == NULL) { printf("Use -label option to specify file for segmentation \n"); usage_exit(0); } if (have_weight == 1 && weight_fname == NULL) { printf("Use -weight option to specify file for input LDA weights \n") ; usage_exit(0); } if (have_weight == 1 && synth_fname == NULL) { printf("Use -synth option to specify file for output synthesized volume \n") ; usage_exit(0); } if (ldaflag) { MINLABEL = MIN(class1, class2); MAXLABEL = MAX(class1, class2); } num_classes = MAXLABEL - MINLABEL + 1; printf("Total of %d classes considered in LDA training\n", num_classes); if (num_classes <= 1) { printf("Need to specify at least two classes to evaluate CNR\n"); usage_exit(0); } ////////////////////////////////////////////////////////////////////////////////// /*** Read in the input multi-echo volumes ***/ nvolumes = 0 ; for (i = 1 ; i < argc; i++) { in_fname = argv[i] ; printf("reading %s...\n", in_fname) ; mri_flash[nvolumes] = MRIread(in_fname) ; if (mri_flash[nvolumes] == NULL) ErrorExit(ERROR_NOFILE, "%s: could not read volume %s", Progname, in_fname) ; /* conform will convert all data to UCHAR, which will reduce data resolution*/ printf("%s read in. \n", in_fname) ; if (conform) { MRI *mri_tmp ; printf("embedding and interpolating volume\n") ; mri_tmp = MRIconform(mri_flash[nvolumes]) ; mri_flash[nvolumes] = mri_tmp ; } /* Change all volumes to float type for convenience */ if (mri_flash[nvolumes]->type != MRI_FLOAT) { printf("Volume %d type is %d\n", nvolumes+1, mri_flash[nvolumes]->type); MRI *mri_tmp; printf("Change data to float type \n"); mri_tmp = MRIchangeType(mri_flash[nvolumes], MRI_FLOAT, 0, 1.0, 1); MRIfree(&mri_flash[nvolumes]); mri_flash[nvolumes] = mri_tmp; //swap } nvolumes++ ; } printf("All data read in\n"); /////////////////////////////////////////////////////////////////////////// nvolumes_total = nvolumes ; /* all volumes read in */ for (i = 0 ; i < nvolumes ; i++) { for (j = i+1 ; j < nvolumes ; j++) { if ((mri_flash[i]->width != mri_flash[j]->width) || (mri_flash[i]->height != mri_flash[j]->height) || (mri_flash[i]->depth != mri_flash[j]->depth)) ErrorExit(ERROR_BADPARM, "%s:\nvolumes %d (type %d) and %d (type %d) don't match (%d x %d x %d) vs (%d x %d x %d)\n", Progname, i, mri_flash[i]->type, j, mri_flash[j]->type, mri_flash[i]->width, mri_flash[i]->height, mri_flash[i]->depth, mri_flash[j]->width, mri_flash[j]->height, mri_flash[j]->depth) ; } } width = mri_flash[0]->width; height = mri_flash[0]->height; depth = mri_flash[0]->depth; if (label_fname != NULL) { mri_label = MRIread(label_fname); if (!mri_label) ErrorExit(ERROR_NOFILE, "%s: could not read input volume %s\n", Progname, label_fname); if ((mri_label->width != mri_flash[0]->width) || (mri_label->height != mri_flash[0]->height) || (mri_label->depth != mri_flash[0]->depth)) ErrorExit(ERROR_BADPARM, "%s: label volume size doesn't match data volumes\n", Progname); /* if(mri_label->type != MRI_UCHAR) ErrorExit(ERROR_BADPARM, "%s: label volume is not UCHAR type \n", Progname); */ } if (mask_fname != NULL) { mri_mask = MRIread(mask_fname); if (!mri_mask) ErrorExit(ERROR_NOFILE, "%s: could not read input volume %s\n", Progname, mask_fname); if ((mri_mask->width != mri_flash[0]->width) || (mri_mask->height != mri_flash[0]->height) || (mri_mask->depth != mri_flash[0]->depth)) ErrorExit(ERROR_BADPARM, "%s: mask volume size doesn't macth data volumes\n", Progname); if (mri_mask->type != MRI_UCHAR) ErrorExit(ERROR_BADPARM, "%s: mask volume is not UCHAR type \n", Progname); } else { mri_mask = MRIalloc(mri_flash[0]->width, mri_flash[0]->height, mri_flash[0]->depth, MRI_UCHAR); MRIcopyHeader(mri_flash[0], mri_mask); /* Simply set mask to be 1 everywhere */ for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { MRIvox(mri_mask, x, y,z) = 1; } } if (debug_flag && window_flag) { /* Limit LDA to a local window */ printf("Local window size = %d\n", window_size); window_size /= 2; for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (MRIvox(mri_mask, x, y,z) == 0) continue; if (z < (Gz - window_size) || z >(Gz + window_size) || y <(Gy - window_size) || y > (Gy + window_size) || x < (Gx - window_size) || x > (Gx + window_size)) MRIvox(mri_mask, x, y,z) = 0; } } LDAweight = (float *)calloc(nvolumes_total, sizeof(float)); /* Allocate memory */ LDAmeans = (float **)malloc(num_classes*sizeof(float *)); SWs = (MATRIX **)malloc(num_classes*sizeof(MATRIX *)); classSize = (float *)malloc(num_classes*sizeof(float)); for (i=0; i< num_classes; i++) { LDAmeans[i] = (float *)malloc(nvolumes_total*sizeof(float)); SWs[i] = (MATRIX *)MatrixAlloc(nvolumes_total, nvolumes_total, MATRIX_REAL); if (SWs[i] == NULL || LDAmeans[i] == NULL) ErrorExit(ERROR_BADPARM, "%s: unable to allocate required memory \n", Progname); } if (ldaflag) { AdjMatrix = (MATRIX *)MatrixAlloc(num_classes, num_classes, MATRIX_REAL); /* The diagnoal entries of AdjMatrix is set to zero initially */ for (i=1; i <= num_classes;i++) for (j=i; j <= num_classes; j++) { AdjMatrix->rptr[i][j] = 0.0; AdjMatrix->rptr[j][i] = 0.0; } AdjMatrix->rptr[class1-MINLABEL +1][class2-MINLABEL+1] = 1.0; AdjMatrix->rptr[class1-MINLABEL +1][class1-MINLABEL+1] = 1.0; AdjMatrix->rptr[class2-MINLABEL +1][class2-MINLABEL+1] = 1.0; AdjMatrix->rptr[class2-MINLABEL +1][class1-MINLABEL+1] = 1.0; } else if (MINLABEL <=2 && MAXLABEL >= 76) { printf("Manually set adjacent matrix \n"); AdjMatrix = (MATRIX *)MatrixAlloc(num_classes, num_classes, MATRIX_REAL); /* The diagnoal entries of AdjMatrix is set to zero initially */ for (i=1; i <= num_classes;i++) for (j=i; j <= num_classes; j++) { AdjMatrix->rptr[i][j] = 0.0; AdjMatrix->rptr[j][i] = 0.0; } for (index = 0; index < CNR_pairs; index++) { i = ilist[index] - MINLABEL; j = jlist[index] - MINLABEL; AdjMatrix->rptr[i+1][j+1] = 1.0; AdjMatrix->rptr[j+1][i+1] = 1.0; } /* left-hemisphere */ /* AdjMatrix->rptr[2+1-MINLABEL][17+1-MINLABEL] = 1.0; AdjMatrix->rptr[17+1-MINLABEL][18+1-MINLABEL] = 1.0; AdjMatrix->rptr[3+1-MINLABEL][17+1-MINLABEL] = 1.0; AdjMatrix->rptr[5+1-MINLABEL][17+1-MINLABEL] = 1.0; AdjMatrix->rptr[4+1-MINLABEL][17+1-MINLABEL] = 1.0; AdjMatrix->rptr[18+1-MINLABEL][2+1-MINLABEL] = 1.0; AdjMatrix->rptr[18+1-MINLABEL][3+1-MINLABEL] = 1.0; AdjMatrix->rptr[18+1-MINLABEL][5+1-MINLABEL] = 1.0; AdjMatrix->rptr[18+1-MINLABEL][4+1-MINLABEL] = 1.0; AdjMatrix->rptr[10+1-MINLABEL][11+1-MINLABEL] = 1.0; AdjMatrix->rptr[10+1-MINLABEL][4+1-MINLABEL] = 1.0; AdjMatrix->rptr[10+1-MINLABEL][12+1-MINLABEL] = 1.0; AdjMatrix->rptr[10+1-MINLABEL][2+1-MINLABEL] = 1.0; AdjMatrix->rptr[2+1-MINLABEL][3+1-MINLABEL] = 1.0; */ /* right-hemisphere */ /* AdjMatrix->rptr[53+1-MINLABEL][41+1-MINLABEL] = 1.0; AdjMatrix->rptr[53+1-MINLABEL][54+1-MINLABEL] = 1.0; AdjMatrix->rptr[53+1-MINLABEL][42+1-MINLABEL] = 1.0; AdjMatrix->rptr[53+1-MINLABEL][44+1-MINLABEL] = 1.0; AdjMatrix->rptr[53+1-MINLABEL][43+1-MINLABEL] = 1.0; AdjMatrix->rptr[54+1-MINLABEL][41+1-MINLABEL] = 1.0; AdjMatrix->rptr[54+1-MINLABEL][42+1-MINLABEL] = 1.0; AdjMatrix->rptr[54+1-MINLABEL][44+1-MINLABEL] = 1.0; AdjMatrix->rptr[54+1-MINLABEL][43+1-MINLABEL] = 1.0; AdjMatrix->rptr[49+1-MINLABEL][50+1-MINLABEL] = 1.0; AdjMatrix->rptr[49+1-MINLABEL][43+1-MINLABEL] = 1.0; AdjMatrix->rptr[49+1-MINLABEL][51+1-MINLABEL] = 1.0; AdjMatrix->rptr[49+1-MINLABEL][41+1-MINLABEL] = 1.0; AdjMatrix->rptr[41+1-MINLABEL][42+1-MINLABEL] = 1.0; for(i=1; i < num_classes;i++) for(j=i+1; j <= num_classes; j++){ if(AdjMatrix->rptr[i][j] > 0.5) AdjMatrix->rptr[j][i] = AdjMatrix->rptr[i][j]; else AdjMatrix->rptr[i][j] = AdjMatrix->rptr[j][i]; } */ /* AdjMatrix->rptr[2+1-MINLABEL][3+1-MINLABEL] = 1.0; AdjMatrix->rptr[2+1-MINLABEL][10+1-MINLABEL] = 1.0; AdjMatrix->rptr[2+1-MINLABEL][11+1-MINLABEL] = 1.0; AdjMatrix->rptr[2+1-MINLABEL][12+1-MINLABEL] = 1.0; AdjMatrix->rptr[2+1-MINLABEL][13+1-MINLABEL] = 1.0; AdjMatrix->rptr[2+1-MINLABEL][17+1-MINLABEL] = 1.0; AdjMatrix->rptr[2+1-MINLABEL][18+1-MINLABEL] = 1.0; AdjMatrix->rptr[3+1-MINLABEL][12+1-MINLABEL] = 1.0; AdjMatrix->rptr[3+1-MINLABEL][17+1-MINLABEL] = 1.0; AdjMatrix->rptr[3+1-MINLABEL][18+1-MINLABEL] = 1.0; AdjMatrix->rptr[4+1-MINLABEL][10+1-MINLABEL] = 1.0; AdjMatrix->rptr[4+1-MINLABEL][11+1-MINLABEL] = 1.0; AdjMatrix->rptr[10+1-MINLABEL][11+1-MINLABEL] = 1.0; AdjMatrix->rptr[10+1-MINLABEL][13+1-MINLABEL] = 1.0; AdjMatrix->rptr[12+1-MINLABEL][13+1-MINLABEL] = 1.0; AdjMatrix->rptr[12+1-MINLABEL][26+1-MINLABEL] = 1.0; AdjMatrix->rptr[17+1-MINLABEL][18+1-MINLABEL] = 1.0; */ /* right-hemisphere */ /* AdjMatrix->rptr[41+1-MINLABEL][42+1-MINLABEL] = 1.0; AdjMatrix->rptr[41+1-MINLABEL][49+1-MINLABEL] = 1.0; AdjMatrix->rptr[41+1-MINLABEL][50+1-MINLABEL] = 1.0; AdjMatrix->rptr[41+1-MINLABEL][51+1-MINLABEL] = 1.0; AdjMatrix->rptr[41+1-MINLABEL][52+1-MINLABEL] = 1.0; AdjMatrix->rptr[41+1-MINLABEL][53+1-MINLABEL] = 1.0; AdjMatrix->rptr[41+1-MINLABEL][54+1-MINLABEL] = 1.0; AdjMatrix->rptr[42+1-MINLABEL][51+1-MINLABEL] = 1.0; AdjMatrix->rptr[42+1-MINLABEL][53+1-MINLABEL] = 1.0; AdjMatrix->rptr[42+1-MINLABEL][54+1-MINLABEL] = 1.0; AdjMatrix->rptr[43+1-MINLABEL][49+1-MINLABEL] = 1.0; AdjMatrix->rptr[43+1-MINLABEL][50+1-MINLABEL] = 1.0; AdjMatrix->rptr[49+1-MINLABEL][50+1-MINLABEL] = 1.0; AdjMatrix->rptr[49+1-MINLABEL][52+1-MINLABEL] = 1.0; AdjMatrix->rptr[51+1-MINLABEL][52+1-MINLABEL] = 1.0; AdjMatrix->rptr[51+1-MINLABEL][58+1-MINLABEL] = 1.0; AdjMatrix->rptr[53+1-MINLABEL][54+1-MINLABEL] = 1.0; */ } else AdjMatrix = ComputeAdjMatrix(mri_label, mri_mask, MINLABEL, MAXLABEL); /* AdjMatrix may need manual adjusted to avoid meaningless comparisons * such as computing CNR between left WM and right WM */ for (i=1; i <= num_classes;i++) for (j=1; j <= num_classes; j++) { if (j==i) continue; /* the diagonal term will indicate whether the class is useful or not */ AdjMatrix->rptr[i][i] += AdjMatrix->rptr[i][j] + AdjMatrix->rptr[j][i]; } printf("Compute individual class statistics\n"); /* Compute class means and covariance matrix */ /* Note that here SWs will be covaraince matrix, not scatter matrix */ for (i=0; i < num_classes; i++) { if (AdjMatrix->rptr[i+1][i+1] < 0.5) continue; computeClassStats(LDAmeans[i], SWs[i], &classSize[i], mri_flash, mri_label, mri_mask, nvolumes_total, MINLABEL + i); } printf("class statistics computed \n"); if (fname != NULL) fp = fopen(fname, "w"); else fp = 0; printf("compute pair-wise CNR/Mahalanobis distances \n"); if (ldaflag) { for (i=0; i <num_classes-1;i++) for (j=i+1; j < num_classes; j++) { if (AdjMatrix->rptr[i+1][j+1] < 0.5) continue; cnr = computePairCNR(LDAmeans[i], LDAmeans[j], SWs[i], SWs[j], classSize[i], classSize[j], nvolumes_total, LDAweight, 1); if (fp) fprintf(fp, "%9.4f ", (float)cnr); printf("CNR of class %d and class %d is %g\n", i+MINLABEL, j+MINLABEL, cnr); } if (fp) { fprintf(fp, "\n"); fclose(fp); } } else { for (index = 0; index < CNR_pairs; index++) { i = ilist[index] - MINLABEL; j = jlist[index] - MINLABEL; if (AdjMatrix->rptr[i+1][j+1] < 0.5) continue; if (i== (2-MINLABEL) && j == (3-MINLABEL) && nvolumes_total > 1) cnr = computePairCNR(LDAmeans[i], LDAmeans[j], SWs[i], SWs[j], classSize[i], classSize[j], nvolumes_total, LDAweight, 1); else cnr = computePairCNR(LDAmeans[i], LDAmeans[j], SWs[i], SWs[j], classSize[i], classSize[j], nvolumes_total, 0, 0); if (fp) fprintf(fp, "%9.4f ", (float)cnr); printf("CNR of class %d and class %d is %g\n", i+MINLABEL, j+MINLABEL, cnr); } if (fp) { fprintf(fp, "\n"); fclose(fp); } } /* output weights for optimize CNR for class 2 and class 3 */ if (weight_fname != NULL) { output_weights_to_file(LDAweight, weight_fname, nvolumes_total); } free(classSize); for (i=0; i< num_classes; i++) { free(LDAmeans[i]); MatrixFree(&SWs[i]); } free(LDAmeans); free(SWs); MatrixFree(&AdjMatrix); if (nvolumes_total > 1 && ((MINLABEL <=2 && MAXLABEL >= 3) || ldaflag)) { if (ldaflag) { printf("LDA weights for %d-%d are: \n", class1, class2); } else { printf("LDA weights for 2-3 are: \n"); } for (i=0; i < nvolumes_total; i++) { printf("%g ", LDAweight[i]); } printf("\n"); if (synth_fname != NULL) { /* linear projection of input volumes to a 1D volume */ min_val = 10000.0; max_val = -10000.0; for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (whole_volume == 0 && MRIvox(mri_mask, x, y, z) == 0) continue; value = 0.0; for (i=0; i < nvolumes_total; i++) { value += MRIFvox(mri_flash[i], x, y, z)*LDAweight[i]; } if (max_val < value) max_val = value; if (min_val > value) min_val = value; /* Borrow mri_flash[0] to store the float values first */ MRIFvox(mri_flash[0], x, y, z) = value; } printf("max_val = %g, min_val = %g \n", max_val, min_val); /* Scale output to [0, 255] */ for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (whole_volume == 0 && MRIvox(mri_mask, x, y, z) == 0) continue; value = (MRIFvox(mri_flash[0], x, y, z) - min_val)*255.0/(max_val - min_val) + 0.5; /* +0.5 for round-off */ if (value > 255.0) value = 255.0; if (value < 0) value = 0; /* Borrow mri_flash[0] to store the float values first */ MRIvox(mri_mask, x, y, z) = (BUFTYPE) value; } /* Output synthesized volume */ MRIwrite(mri_mask, synth_fname); } } free(LDAweight); msec = TimerStop(&start) ; seconds = nint((float)msec/1000.0f) ; minutes = seconds / 60 ; seconds = seconds % 60 ; printf("LDA took %d minutes and %d seconds.\n", minutes, seconds) ; MRIfree(&mri_mask); MRIfree(&mri_label); for (i=0; i < nvolumes_total; i++) { MRIfree(&mri_flash[i]); } exit(0); }
/*--------------------------------------------------*/ int main(int argc, char **argv) { int nargs, err, asegid, c, r, s, annot, hemioffset; int annotid; struct utsname uts; char *cmdline, cwd[2000]; /* rkt: check for and handle version tag */ nargs = handle_version_option (argc, argv, vcid, "$Name: stable5 $"); if (nargs && argc - nargs == 1) exit (0); argc -= nargs; cmdline = argv2cmdline(argc,argv); uname(&uts); getcwd(cwd,2000); Progname = argv[0] ; argc --; argv++; ErrorInit(NULL, NULL, NULL) ; DiagInit(NULL, NULL, NULL) ; if (argc == 0) usage_exit(); parse_commandline(argc, argv); check_options(); dump_options(stdout); printf("\n"); printf("%s\n",vcid); printf("cwd %s\n",cwd); printf("cmdline %s\n",cmdline); printf("sysname %s\n",uts.sysname); printf("hostname %s\n",uts.nodename); printf("machine %s\n",uts.machine); SUBJECTS_DIR = getenv("SUBJECTS_DIR"); if (SUBJECTS_DIR==NULL) { printf("ERROR: SUBJECTS_DIR not defined in environment\n"); exit(1); } printf("SUBJECTS_DIR %s\n",SUBJECTS_DIR); printf("subject %s\n",subject); printf("\n"); fflush(stdout); /* ------ Load subject's lh white surface ------ */ sprintf(tmpstr,"%s/%s/surf/lh.white",SUBJECTS_DIR,subject); printf("Reading lh white surface \n %s\n",tmpstr); lhwhite = MRISread(tmpstr); if (lhwhite == NULL) { fprintf(stderr,"ERROR: could not read %s\n",tmpstr); exit(1); } printf("Building hash of lh white\n"); lhwhite_hash = MHTfillVertexTableRes(lhwhite, NULL,CURRENT_VERTICES,16); /* ------ Load lh annotation ------ */ sprintf(annotfile,"%s/%s/label/lh.aparc.annot",SUBJECTS_DIR,subject); printf("Loading lh annotations from %s\n",annotfile); err = MRISreadAnnotation(lhwhite, annotfile); if (err) { printf("ERROR: MRISreadAnnotation() failed %s\n",annotfile); exit(1); } /* ------ Load subject's rh surface ------ */ sprintf(tmpstr,"%s/%s/surf/rh.white",SUBJECTS_DIR,subject); printf("Reading rh white surface \n %s\n",tmpstr); rhwhite = MRISread(tmpstr); if (rhwhite == NULL) { fprintf(stderr,"ERROR: could not read %s\n",tmpstr); exit(1); } if (debug) printf("Building hash of rh white\n"); rhwhite_hash = MHTfillVertexTableRes(rhwhite, NULL,CURRENT_VERTICES,16); /* ------ Load rh annotation ------ */ sprintf(annotfile,"%s/%s/label/rh.aparc.annot",SUBJECTS_DIR,subject); printf("Loading rh annotations from %s\n",annotfile); err = MRISreadAnnotation(rhwhite, annotfile); if (err) { printf("ERROR: MRISreadAnnotation() failed %s\n",annotfile); exit(1); } if (debug && lhwhite->ct) printf("Have color table for annotation\n"); if (debug) print_annotation_table(stdout); /* ------ Load ASeg ------ */ sprintf(tmpstr,"%s/%s/mri/aseg.mgz",SUBJECTS_DIR,subject); if (!fio_FileExistsReadable(tmpstr)) { sprintf(tmpstr,"%s/%s/mri/aseg.mgh",SUBJECTS_DIR,subject); if (!fio_FileExistsReadable(tmpstr)) { sprintf(tmpstr,"%s/%s/mri/aseg/COR-.info",SUBJECTS_DIR,subject); if (!fio_FileExistsReadable(tmpstr)) { printf("ERROR: cannot find aseg\n"); exit(1); } else sprintf(tmpstr,"%s/%s/mri/aseg/",SUBJECTS_DIR,subject); } } printf("Loading aseg from %s\n",tmpstr); ASeg = MRIread(tmpstr); if (ASeg == NULL) { printf("ERROR: loading aseg %s\n",tmpstr); exit(1); } mritmp = MRIchangeType(ASeg,MRI_INT,0,0,0); MRIfree(&ASeg); ASeg = mritmp; WMSeg = MRIclone(ASeg,NULL); Vox2RAS = MRIxfmCRS2XYZtkreg(ASeg); if (debug) { printf("ASeg Vox2RAS: -----------\n"); MatrixPrint(stdout,Vox2RAS); printf("-------------------------\n"); } CRS = MatrixAlloc(4,1,MATRIX_REAL); CRS->rptr[4][1] = 1; RAS = MatrixAlloc(4,1,MATRIX_REAL); RAS->rptr[4][1] = 1; // Go through each voxel in the aseg printf("\n"); printf("Labeling WM\n"); for (c=0; c < ASeg->width; c++) { if (debug) printf("%3d ",c); if (debug && c%20 ==19) printf("\n"); for (r=0; r < ASeg->height; r++) { for (s=0; s < ASeg->depth; s++) { // If it's not labeled as white matter in the aseg, set // seg value to that from the aseg and skip the rest asegid = MRIgetVoxVal(ASeg,c,r,s,0); if (asegid != 2 && asegid != 41) { MRIsetVoxVal(WMSeg,c,r,s,0,asegid); continue; } // Convert the CRS to RAS CRS->rptr[1][1] = c; CRS->rptr[2][1] = r; CRS->rptr[3][1] = s; RAS = MatrixMultiply(Vox2RAS,CRS,RAS); vtx.x = RAS->rptr[1][1]; vtx.y = RAS->rptr[2][1]; vtx.z = RAS->rptr[3][1]; // Get the index of the closest vertex in the // lh.white, rh.white lhwvtx = MHTfindClosestVertexNo(lhwhite_hash,lhwhite,&vtx,&dlhw); rhwvtx = MHTfindClosestVertexNo(rhwhite_hash,rhwhite,&vtx,&drhw); if ( (lhwvtx < 0) && (rhwvtx < 0) ) { printf("ERROR: could not map to any surface.\n"); printf("crs = %d %d %d, ras = %6.4f %6.4f %6.4f \n", c,r,s,vtx.x,vtx.y,vtx.z); exit(1); } if (lhwvtx < 0) dlhw = 1000000000000000.0; if (rhwvtx < 0) drhw = 1000000000000000.0; if (dlhw < drhw) { // Left hemi is closer than the right annot = lhwhite->vertices[lhwvtx].annotation; hemioffset = 1000; if (lhwhite->ct) CTABfindAnnotation(lhwhite->ct, annot, &annotid); else annotid = annotation_to_index(annot); } else { // Right hemi is closer than the left annot = rhwhite->vertices[rhwvtx].annotation; hemioffset = 2000; if (rhwhite->ct) CTABfindAnnotation(lhwhite->ct, annot, &annotid); else annotid = annotation_to_index(annot); } MRIsetVoxVal(WMSeg,c,r,s,0,annotid+hemioffset); } } } printf("\nWriting output wmseg to %s\n",WMSegFile); MRIwrite(WMSeg,WMSegFile); printf("mri_aparc2wmseg done\n"); return(0); }
int main(int argc, char *argv[]) { MRI *mri_src, *mri_dst, *mri_tmp, *mri_labeled, *mri_labels; char *input_file_name, *output_file_name ; int nargs, i, msec ; struct timeb then ; float white_mean, white_sigma, gray_mean, gray_sigma ; char cmdline[CMD_LINE_LEN] ; TAGmakeCommandLineString(argc, argv, cmdline) ; /* rkt: check for and handle version tag */ nargs = handle_version_option (argc, argv, "$Id: mri_segment.c,v 1.40 2011/03/02 00:04:24 nicks Exp $", "$Name: stable5 $"); if (nargs && argc - nargs == 1) { exit (0); } argc -= nargs; Progname = argv[0] ; DiagInit(NULL, NULL, NULL) ; ErrorInit(NULL, NULL, NULL) ; for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++) { nargs = get_option(argc, argv) ; argc -= nargs ; argv += nargs ; } if (argc < 3) { usage_exit(1); } TimerStart(&then) ; input_file_name = argv[1] ; output_file_name = argv[2] ; mri_src = MRIread(input_file_name) ; if (!mri_src) ErrorExit(ERROR_NOFILE, "%s: could not read source volume from %s", Progname, input_file_name) ; MRIaddCommandLine(mri_src, cmdline) ; if (mri_src->type != MRI_UCHAR) { MRI *mri_tmp ; printf("changing input type from %d to UCHAR\n", mri_src->type) ; mri_tmp = MRIchangeType(mri_src, MRI_UCHAR, 0, 1000, 1) ; MRIfree(&mri_src) ; mri_src = mri_tmp ; } if (thicken > 1) { mri_dst = MRIcopy(mri_src, NULL) ; /* MRIfilterMorphology(mri_dst, mri_dst) ;*/ fprintf(stderr, "removing 1-dimensional structures...\n") ; MRIremove1dStructures(mri_dst, mri_dst, 10000, 2, NULL) ; #if 0 MRIcheckRemovals(mri_src, mri_dst, mri_labels, 5) ; fprintf(stderr, "thickening thin strands....\n") ; MRIthickenThinWMStrands(mri_src, mri_dst, mri_dst, thickness, nsegments, wm_hi) ; #endif MRIwrite(mri_dst, output_file_name) ; exit(0) ; } mri_labels = MRIclone(mri_src, NULL) ; if (auto_detect_stats && !wm_low_set) /* widen range to allow for more variability */ { wm_low -= 10 ; } fprintf(stderr, "doing initial intensity segmentation...\n") ; mri_tmp = MRIintensitySegmentation(mri_src, NULL, wm_low, wm_hi, gray_hi); if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON) { MRIwrite(mri_tmp, "tmp1.mgz") ; } fprintf(stderr, "using local statistics to label ambiguous voxels...\n") ; MRIhistoSegment(mri_src, mri_tmp, wm_low, wm_hi, gray_hi, wsize, 3.0f) ; if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON) { MRIwrite(mri_tmp, "tmp2.mgz") ; } if (auto_detect_stats) { fprintf(stderr, "computing class statistics for intensity windows...\n") ; MRIcomputeClassStatistics(mri_src, mri_tmp, gray_low, WHITE_MATTER_MEAN, &white_mean, &white_sigma, &gray_mean, &gray_sigma) ; if (!finite(white_mean) || !finite(white_sigma) || !finite(gray_mean) || !finite(gray_sigma)) ErrorExit (ERROR_BADPARM, "%s: class statistics not finite - check input volume!", Progname); if (!wm_low_set) { if (FZERO(gray_sigma)) { wm_low = (white_mean+gray_mean) / 2 ; } else { wm_low = gray_mean + gray_sigma ; } } if (!gray_hi_set) { gray_hi = gray_mean + 2*gray_sigma ; #if 1 if (gray_hi >= white_mean) { gray_hi = white_mean-1 ; } #endif } fprintf(stderr, "setting bottom of white matter range to %2.1f\n",wm_low); fprintf(stderr, "setting top of gray matter range to %2.1f\n", gray_hi) ; if (log_stats) { FILE *fp ; fp = fopen("segment.dat", "w") ; if (fp) { fprintf(fp, "WM: %2.1f +- %2.1f\n",white_mean, white_sigma) ; fprintf(fp, "GM: %2.1f +- %2.1f\n",gray_mean, gray_sigma) ; fprintf(fp, "setting bottom of white matter range to %2.1f\n",wm_low); fprintf(fp, "setting top of gray matter range to %2.1f\n", gray_hi) ; fclose(fp) ; } } fprintf(stderr, "doing initial intensity segmentation...\n") ; mri_tmp = MRIintensitySegmentation(mri_src, NULL, wm_low, wm_hi, gray_hi); fprintf(stderr, "using local statistics to label ambiguous voxels...\n") ; MRIhistoSegment(mri_src, mri_tmp, wm_low, wm_hi, gray_hi, wsize, 3.0f) ; } else { /* just some not-too-dopey defaults - won't really be used */ white_mean = 110 ; white_sigma = 5.0 ; gray_mean = 65 ; gray_sigma = 12 ; } fprintf(stderr, "using local geometry to label remaining ambiguous voxels...\n") ; mri_labeled = MRIcpolvMedianCurveSegment(mri_src, mri_tmp, NULL, 5, 3, gray_hi, wm_low); fprintf(stderr, "\nreclassifying voxels using Gaussian border classifier...\n") ; /* now use the gray and white matter border voxels to build a Gaussian classifier at each point in space and reclassify all voxels in the range [wm_low-5,gray_hi]. */ for (i = 0 ; i < niter ; i++) { MRIreclassify(mri_src, mri_labeled, mri_labeled, wm_low-5,gray_hi,wsize); } MRIfree(&mri_tmp) ; mri_dst = MRImaskLabels(mri_src, mri_labeled, NULL) ; MRIfree(&mri_labeled) ; MRIrecoverBrightWhite(mri_src, mri_dst,mri_dst,wm_low,wm_hi,white_sigma,.33); fprintf(stderr, "\nremoving voxels with positive offset direction...\n") ; #if 0 MRIremoveWrongDirection(mri_dst, mri_dst, 3, wm_low-5, gray_hi, mri_labels) ; #else MRIremoveWrongDirection(mri_dst, mri_dst, 3, wm_low-5, gray_hi, NULL) ; #endif if (thicken) { /* MRIfilterMorphology(mri_dst, mri_dst) ;*/ fprintf(stderr, "removing 1-dimensional structures...\n") ; MRIremove1dStructures(mri_dst, mri_dst, 10000, 2, mri_labels) ; #if 0 MRIcheckRemovals(mri_src, mri_dst, mri_labels, 5) ; #endif fprintf(stderr, "thickening thin strands....\n") ; MRIthickenThinWMStrands(mri_src, mri_dst, mri_dst, thickness, nsegments, wm_hi) ; } mri_tmp = MRIfindBrightNonWM(mri_src, mri_dst) ; MRIbinarize(mri_tmp, mri_tmp, WM_MIN_VAL, 255, 0) ; MRImaskLabels(mri_dst, mri_tmp, mri_dst) ; MRIfilterMorphology(mri_dst, mri_dst) ; if (fill_bg) { fprintf(stderr, "filling basal ganglia....\n") ; MRIfillBasalGanglia(mri_src, mri_dst) ; } if (fill_ventricles) { fprintf(stderr, "filling ventricles....\n") ; MRIfillVentricles(mri_dst, mri_dst) ; } MRIfree(&mri_src) ; msec = TimerStop(&then) ; fprintf(stderr, "white matter segmentation took %2.1f minutes\n", (float)msec/(1000.0f*60.0f)); fprintf(stderr, "writing output to %s...\n", output_file_name) ; if (keep_edits) { MRI *mri_old ; mri_old = MRIread(output_file_name) ; if (!mri_old) { ErrorPrintf (ERROR_NOFILE, "%s: could not read file %s to preserve edits", Progname, output_file_name) ; exit(1); } else { MRIcopyLabel(mri_old, mri_dst, WM_EDITED_ON_VAL) ; MRIcopyLabel(mri_old, mri_dst, WM_EDITED_OFF_VAL) ; MRIfree(&mri_old) ; } } MRIwrite(mri_dst, output_file_name) ; MRIfree(&mri_dst) ; exit(0) ; return(0) ; }
int main(int argc, char *argv[]) { char **av, fname[STRLEN], *out_fname, *subject_name, *cp, *tp1_name, *tp2_name ; char s1_name[STRLEN], s2_name[STRLEN], *sname ; int ac, nargs, i, n, options, max_index ; int msec, minutes, seconds, nsubjects, input ; struct timeb start ; MRI *mri_seg, *mri_tmp, *mri_in ; TRANSFORM *transform ; // int counts ; int t; RANDOM_FOREST *rf = NULL ; GCA *gca = NULL ; Progname = argv[0] ; ErrorInit(NULL, NULL, NULL) ; DiagInit(NULL, NULL, NULL) ; TimerStart(&start) ; parms.width = parms.height = parms.depth = DEFAULT_VOLUME_SIZE ; parms.ntrees = 10 ; parms.max_depth = 10 ; parms.wsize = 1 ; parms.training_size = 100 ; parms.training_fraction = .5 ; parms.feature_fraction = 1 ; /* rkt: check for and handle version tag */ nargs = handle_version_option (argc, argv, "$Id: mri_rf_long_train.c,v 1.5 2012/06/15 12:22:28 fischl Exp $", "$Name: $"); if (nargs && argc - nargs == 1) exit (0); argc -= nargs; // parse command line args ac = argc ; av = argv ; for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++) { nargs = get_option(argc, argv) ; argc -= nargs ; argv += nargs ; } if (!strlen(subjects_dir)) /* hasn't been set on command line */ { cp = getenv("SUBJECTS_DIR") ; if (!cp) ErrorExit(ERROR_BADPARM, "%s: SUBJECTS_DIR not defined in environment", Progname); strcpy(subjects_dir, cp) ; } if (argc < 3) usage_exit(1) ; // options parsed. subjects, tp1 and tp2 and rf name remaining out_fname = argv[argc-1] ; nsubjects = (argc-2)/3 ; for (options = i = 0 ; i < nsubjects ; i++) { if (argv[i+1][0] == '-') { nsubjects-- ; options++ ; } } printf("training on %d subject and writing results to %s\n", nsubjects, out_fname) ; // rf_inputs can be T1, PD, ...per subject if (parms.nvols == 0) parms.nvols = ninputs ; /* gca reads same # of inputs as we read from command line - not the case if we are mapping to flash */ n = 0 ; ////////////////////////////////////////////////////////////////// // set up gca direction cosines, width, height, depth defaults gca = GCAread(gca_name) ; if (gca == NULL) ErrorExit(ERROR_NOFILE, "%s: could not read GCA from %s", Progname, gca_name) ; ///////////////////////////////////////////////////////////////////////// // weird way options and subject name are mixed here ///////////////////////////////////////////////////////// // first calculate mean //////////////////////////////////////////////////////// // going through the subject one at a time max_index = nsubjects+options ; nargs = 0 ; mri_in = NULL ; #ifdef HAVE_OPENMP subject_name = NULL ; sname = NULL ; t = 0 ; // counts = 0 ; would be private input = 0 ; transform = NULL ; tp1_name = tp2_name = NULL ; mri_tmp = mri_seg = NULL ; #pragma omp parallel for firstprivate(tp1_name, tp2_name, mri_in,mri_tmp, input, xform_name, transform, subjects_dir, force_inputs, conform, Progname, mri_seg, subject_name, s1_name, s2_name, sname, t, fname) shared(mri_inputs, transforms, mri_segs,argv) schedule(static,1) #endif for (i = 0 ; i < max_index ; i++) { subject_name = argv[3*i+1] ; tp1_name = argv[3*i+2] ; tp2_name = argv[3*i+3] ; sprintf(s1_name, "%s_%s.long.%s_base", subject_name, tp1_name, subject_name) ; sprintf(s2_name, "%s_%s.long.%s_base", subject_name, tp2_name, subject_name) ; ////////////////////////////////////////////////////////////// printf("***************************************" "************************************\n"); printf("processing subject %s, %d of %d (%s and %s)...\n", subject_name,i+1-nargs, nsubjects, s1_name,s2_name); for (t = 0 ; t < 2 ; t++) { sname = t == 0 ? s1_name : s2_name; // reading this subject segmentation sprintf(fname, "%s/%s/mri/%s", subjects_dir, sname, seg_dir) ; if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON) fprintf(stderr, "Reading segmentation from %s...\n", fname) ; mri_seg = MRIread(fname) ; if (!mri_seg) ErrorExit(ERROR_NOFILE, "%s: could not read segmentation file %s", Progname, fname) ; if ((mri_seg->type != MRI_UCHAR) && (make_uchar != 0)) { MRI *mri_tmp ; mri_tmp = MRIchangeType(mri_seg, MRI_UCHAR, 0, 1,1); MRIfree(&mri_seg) ; mri_seg = mri_tmp ; } if (wmsa_fname) { MRI *mri_wmsa ; sprintf(fname, "%s/%s/mri/%s", subjects_dir, sname, wmsa_fname) ; printf("reading WMSA labels from %s...\n", fname) ; mri_wmsa = MRIread(fname) ; if (mri_wmsa == NULL) ErrorExit(ERROR_NOFILE, "%s: could not read WMSA file %s", fname) ; MRIbinarize(mri_wmsa, mri_wmsa, 1, 0, WM_hypointensities) ; MRIcopyLabel(mri_wmsa, mri_seg, WM_hypointensities) ; lateralize_hypointensities(mri_seg) ; if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON ) { char s[STRLEN] ; sprintf(s, "%s/%s/mri/seg_%s", subjects_dir, subject_name, wmsa_fname) ; MRIwrite(mri_seg, s) ; } } if (binarize) { int j ; for (j = 0 ; j < 256 ; j++) { if (j == binarize_in) MRIreplaceValues(mri_seg, mri_seg, j, binarize_out) ; else MRIreplaceValues(mri_seg, mri_seg, j, 0) ; } } if (insert_fname) { MRI *mri_insert ; sprintf(fname, "%s/%s/mri/%s", subjects_dir, subject_name, insert_fname) ; mri_insert = MRIread(fname) ; if (mri_insert == NULL) ErrorExit(ERROR_NOFILE, "%s: could not read volume from %s for insertion", Progname, insert_fname) ; MRIbinarize(mri_insert, mri_insert, 1, 0, insert_label) ; MRIcopyLabel(mri_insert, mri_seg, insert_label) ; MRIfree(&mri_insert) ; } replaceLabels(mri_seg) ; MRIeraseBorderPlanes(mri_seg, 1) ; //////////////////////////////////////////////////////////// if (DIAG_VERBOSE_ON) fprintf(stderr, "Gather all input volumes for the subject %s.\n", subject_name); // inputs must be coregistered // note that inputs are T1, PD, ... per subject (same TE, TR, FA) for (input = 0 ; input < ninputs ; input++) { //////////// set the gca type ////////////////////////////// // is this T1/PD training? // how can we allow flash data training ??????? // currently checks the TE, TR, FA to be the same for all inputs // thus we cannot allow flash data training. //////////////////////////////////////////////////////////// sprintf(fname, "%s/%s/mri/%s", subjects_dir, sname,input_names[input]); if (DIAG_VERBOSE_ON) printf("reading co-registered input from %s...\n", fname) ; fprintf(stderr, " reading input %d: %s\n", input, fname); mri_tmp = MRIread(fname) ; if (!mri_tmp) ErrorExit (ERROR_NOFILE, "%s: could not read image from file %s", Progname, fname) ; // input check 1 if (getSliceDirection(mri_tmp) != MRI_CORONAL) { ErrorExit (ERROR_BADPARM, "%s: must be in coronal direction, but it is not\n", fname); } // input check 2 if (conform && (mri_tmp->xsize != 1 || mri_tmp->ysize != 1 || mri_tmp->zsize != 1)) { ErrorExit (ERROR_BADPARM, "%s: must have 1mm voxel size, but have (%f, %f, %f)\n", fname, mri_tmp->xsize, mri_tmp->ysize, mri_tmp->ysize); } // input check 3 is removed. now we can handle c_(ras) != 0 case // input check 4 if (i == 0) { TRs[input] = mri_tmp->tr ; FAs[input] = mri_tmp->flip_angle ; TEs[input] = mri_tmp->te ; } else if ((force_inputs == 0) && (!FEQUAL(TRs[input],mri_tmp->tr) || !FEQUAL(FAs[input],mri_tmp->flip_angle) || !FEQUAL(TEs[input], mri_tmp->te))) ErrorExit (ERROR_BADPARM, "%s: subject %s input volume %s: sequence parameters " "(%2.1f, %2.1f, %2.1f)" "don't match other inputs (%2.1f, %2.1f, %2.1f)", Progname, subject_name, fname, mri_tmp->tr, DEGREES(mri_tmp->flip_angle), mri_tmp->te, TRs[input], DEGREES(FAs[input]), TEs[input]) ; // first time do the following if (input == 0) { int nframes = ninputs ; /////////////////////////////////////////////////////////// mri_in = MRIallocSequence(mri_tmp->width, mri_tmp->height, mri_tmp->depth, mri_tmp->type, nframes) ; if (!mri_in) ErrorExit (ERROR_NOMEMORY, "%s: could not allocate input volume %dx%dx%dx%d", mri_tmp->width, mri_tmp->height, mri_tmp->depth,nframes) ; MRIcopyHeader(mri_tmp, mri_in) ; } // -mask option //////////////////////////////////////////// if (mask_fname) { MRI *mri_mask ; sprintf(fname, "%s/%s/mri/%s", subjects_dir, subject_name, mask_fname); printf("reading volume %s for masking...\n", fname) ; mri_mask = MRIread(fname) ; if (!mri_mask) ErrorExit(ERROR_NOFILE, "%s: could not open mask volume %s.\n", Progname, fname) ; MRImask(mri_tmp, mri_mask, mri_tmp, 0, 0) ; MRIfree(&mri_mask) ; } MRIcopyFrame(mri_tmp, mri_in, 0, input) ; MRIfree(&mri_tmp) ; }// end of inputs per subject ///////////////////////////////////////////////////////// // xform_name is given, then we can use the consistent c_(r,a,s) for gca ///////////////////////////////////////////////////////// if (xform_name) { // we read talairach.xfm which is a RAS-to-RAS sprintf(fname, "%s/%s/mri/transforms/%s", subjects_dir, sname, xform_name) ; if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON) printf("INFO: reading transform file %s...\n", fname); if (!FileExists(fname)) { fprintf(stderr,"ERROR: cannot find transform file %s\n",fname); exit(1); } transform = TransformRead(fname); if (!transform) ErrorExit(ERROR_NOFILE, "%s: could not read transform from file %s", Progname, fname); // modify_transform(transform, mri_in, gca); // Here we do 2 things // 1. modify gca direction cosines to // that of the transform destination (both linear and non-linear) // 2. if ras-to-ras transform, // then change it to vox-to-vox transform (linear case) // modify transform to store inverse also TransformInvert(transform, mri_in) ; } else { // GCAreinit(mri_in, gca); // just use the input value, since dst = src volume transform = TransformAlloc(LINEAR_VOXEL_TO_VOXEL, NULL) ; } ///////////////////////////////////////////////////////// if (do_sanity_check) { // conduct a sanity check of particular labels, most importantly // hippocampus, that such labels do not exist in talairach coords // where they are known not to belong (indicating a bad manual edit) int errs = check(mri_seg, subjects_dir, subject_name); if (errs) { printf( "ERROR: mri_ca_train: possible bad training data! subject:\n" "\t%s/%s\n\n", subjects_dir, subject_name); fflush(stdout) ; sanity_check_badsubj_count++; } } mri_segs[i][t] = mri_seg ; mri_inputs[i][t] = mri_in ; transforms[i][t] = transform ; } } rf = train_rforest(mri_inputs, mri_segs, transforms, nsubjects, gca, &parms, wm_thresh,wmsa_whalf, 2) ; printf("writing random forest to %s\n", out_fname) ; if (RFwrite(rf, out_fname) != NO_ERROR) ErrorExit (ERROR_BADFILE, "%s: could not write rf to %s", Progname, out_fname) ; msec = TimerStop(&start) ; seconds = nint((float)msec/1000.0f) ; minutes = seconds / 60 ; seconds = seconds % 60 ; printf("classifier array training took %d minutes and %d seconds.\n", minutes, seconds) ; exit(0) ; return(0) ; }
int main(int argc, char *argv[]) { char *ref_fname, *in_fname, *out_fname, fname[STRLEN], **av ; MRI *mri_ref, *mri_in, *mri_orig, *mri_in_red, *mri_ref_red, *mri_in_tmp, *mri_ref_tmp, *mri_ref_orig, *mri_in_orig ; int ac, nargs, i, msec, minutes, seconds ; struct timeb start ; MATRIX *m_L ; /* rkt: check for and handle version tag */ nargs = handle_version_option (argc, argv, "$Id: mri_linear_register.c,v 1.13 2011/03/02 00:04:22 nicks Exp $", "$Name: stable5 $"); if (nargs && argc - nargs == 1) exit (0); argc -= nargs; parms.mri_crop = NULL ; parms.l_intensity = 1.0f ; parms.niterations = 100 ; parms.levels = -1 ; /* use default */ parms.dt = 1e-6 ; /* was 5e-6 */ parms.tol = INTEGRATION_TOL*5 ; parms.dt = 5e-6 ; /* was 5e-6 */ parms.tol = 1e-3 ; parms.momentum = 0.8 ; parms.max_levels = MAX_LEVELS ; parms.factor = 1.0 ; parms.niterations = 25 ; Progname = argv[0] ; DiagInit(NULL, NULL, NULL) ; ErrorInit(NULL, NULL, NULL) ; ac = argc ; av = argv ; for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++) { nargs = get_option(argc, argv) ; argc -= nargs ; argv += nargs ; } if (argc < 4) ErrorExit(ERROR_BADPARM, "usage: %s <in brain> <template> <output file name>\n", Progname) ; in_fname = argv[1] ; ref_fname = argv[2] ; if (xform_mean_fname) { int sno, nsubjects ; FILE *fp ; parms.m_xform_mean = MatrixAsciiRead(xform_mean_fname, NULL) ; if (!parms.m_xform_mean) ErrorExit(Gerror, "%s: could not read parameter means from %s", Progname, xform_mean_fname) ; fp = fopen(xform_covariance_fname, "r") ; if (!fp) ErrorExit(ERROR_NOFILE, "%s: could not read covariances from %s", Progname, xform_covariance_fname) ; fscanf(fp, "nsubjects=%d", &nsubjects) ; printf("reading %d transforms...\n", nsubjects) ; parms.m_xforms = (MATRIX **)calloc(nsubjects, sizeof(MATRIX *)) ; if (!parms.m_xforms) ErrorExit(ERROR_NOMEMORY, "%s: could not allocate array of %d xforms", Progname, nsubjects) ; for (sno = 0 ; sno < nsubjects ; sno++) { parms.m_xforms[sno] = MatrixAsciiReadFrom(fp, NULL) ; if (!parms.m_xforms[sno]) ErrorExit(ERROR_NOMEMORY, "%s: could not allocate %dth xform", Progname, sno) ; } parms.m_xform_covariance = MatrixAsciiReadFrom(fp, NULL) ; if (!parms.m_xform_covariance) ErrorExit(Gerror, "%s: could not read parameter covariance from %s", Progname, xform_covariance_fname) ; fclose(fp) ; parms.l_priors = l_priors ; parms.nxforms = nsubjects ; } out_fname = argv[3] ; FileNameOnly(out_fname, fname) ; FileNameRemoveExtension(fname, fname) ; strcpy(parms.base_name, fname) ; fprintf(stderr, "logging results to %s.log\n", parms.base_name) ; TimerStart(&start) ; fprintf(stderr, "reading '%s'...\n", ref_fname) ; fflush(stderr) ; mri_ref = MRIread(ref_fname) ; if (!mri_ref) ErrorExit(ERROR_NOFILE, "%s: could not open reference volume %s.\n", Progname, ref_fname) ; if (mri_ref->type != MRI_UCHAR) { MRI *mri_tmp ; mri_tmp = MRIchangeType(mri_ref, MRI_UCHAR, 0.0, 0.999, FALSE) ; MRIfree(&mri_ref) ; mri_ref = mri_tmp ; } if (var_fname) /* read in a volume of standard deviations */ { MRI *mri_var, *mri_tmp ; fprintf(stderr, "reading '%s'...\n", var_fname) ; mri_var = MRIread(var_fname) ; if (!mri_var) ErrorExit(ERROR_NOFILE, "%s: could not open variance volume %s.\n", Progname, var_fname) ; mri_tmp = MRIconcatenateFrames(mri_ref, mri_var, NULL) ; MRIfree(&mri_var) ; MRIfree(&mri_ref) ; mri_ref = mri_tmp ; } fprintf(stderr, "reading '%s'...\n", in_fname) ; fflush(stderr) ; mri_orig = mri_in = MRIread(in_fname) ; if (!mri_in) ErrorExit(ERROR_NOFILE, "%s: could not open input volume %s.\n", Progname, in_fname) ; if (mri_in->type != MRI_UCHAR) { MRI *mri_tmp ; mri_orig = mri_tmp = MRIchangeType(mri_in, MRI_UCHAR, 0.0, 0.999, FALSE) ; MRIfree(&mri_in) ; mri_in = mri_tmp ; } /* make sure they are the same size */ if (mri_in->width != mri_ref->width || mri_in->height != mri_ref->height || mri_in->depth != mri_ref->depth) { int width, height, depth ; MRI *mri_tmp ; width = MAX(mri_in->width, mri_ref->width) ; height = MAX(mri_in->height, mri_ref->height) ; depth = MAX(mri_in->depth, mri_ref->depth) ; mri_tmp = MRIalloc(width, height, depth, MRI_UCHAR) ; MRIextractInto(mri_in, mri_tmp, 0, 0, 0, mri_in->width, mri_in->height, mri_in->depth, 0, 0, 0) ; #if 0 MRIfree(&mri_in) ; #else parms.mri_in = mri_in ; #endif mri_in = mri_orig = mri_tmp ; mri_tmp = MRIallocSequence(width, height,depth,MRI_UCHAR,mri_ref->nframes); MRIextractInto(mri_ref, mri_tmp, 0, 0, 0, mri_ref->width, mri_ref->height, mri_ref->depth, 0, 0, 0) ; #if 0 MRIfree(&mri_ref) ; #else parms.mri_in = mri_in ; #endif mri_ref = mri_tmp ; } if (!FZERO(tx) || !FZERO(ty) || !FZERO(tz)) { MRI *mri_tmp ; fprintf(stderr, "translating second volume by (%2.1f, %2.1f, %2.1f)\n", tx, ty, tz) ; mri_tmp = MRItranslate(mri_in, NULL, tx, ty, tz) ; MRIfree(&mri_in) ; mri_in = mri_tmp ; } if (!FZERO(rzrot)) { MRI *mri_tmp ; fprintf(stderr, "rotating second volume by %2.1f degrees around Z axis\n", (float)DEGREES(rzrot)) ; mri_tmp = MRIrotateZ_I(mri_in, NULL, rzrot) ; MRIfree(&mri_in) ; mri_in = mri_tmp ; } if (!FZERO(rxrot)) { MRI *mri_tmp ; fprintf(stderr, "rotating second volume by %2.1f degrees around X axis\n", (float)DEGREES(rxrot)) ; mri_tmp = MRIrotateX_I(mri_in, NULL, rxrot) ; MRIfree(&mri_in) ; mri_in = mri_tmp ; } if (!FZERO(ryrot)) { MRI *mri_tmp ; fprintf(stderr, "rotating second volume by %2.1f degrees around Y axis\n", (float)DEGREES(ryrot)) ; mri_tmp = MRIrotateY_I(mri_in, NULL, ryrot) ; MRIfree(&mri_in) ; mri_in = mri_tmp ; } if (!transform_loaded) /* wasn't preloaded */ parms.lta = LTAalloc(1, mri_in) ; if (!FZERO(blur_sigma)) { MRI *mri_kernel, *mri_tmp ; mri_kernel = MRIgaussian1d(blur_sigma, 100) ; mri_tmp = MRIconvolveGaussian(mri_in, NULL, mri_kernel) ; mri_in = mri_tmp ; MRIfree(&mri_kernel) ; } MRIscaleMeanIntensities(mri_in, mri_ref, mri_in); mri_ref_orig = mri_ref ; mri_in_orig = mri_in ; if (nreductions > 0) { mri_in_red = mri_in_tmp = MRIcopy(mri_in, NULL) ; mri_ref_red = mri_ref_tmp = MRIcopy(mri_ref, NULL) ; for (i = 0 ; i < nreductions ; i++) { mri_in_red = MRIreduceByte(mri_in_tmp, NULL) ; mri_ref_red = MRIreduceMeanAndStdByte(mri_ref_tmp,NULL); MRIfree(&mri_in_tmp); MRIfree(&mri_ref_tmp) ; mri_in_tmp = mri_in_red ; mri_ref_tmp = mri_ref_red ; } mri_in = mri_in_red ; mri_ref = mri_ref_red ; } /* for diagnostics */ if (full_res) { parms.mri_ref = mri_ref ; parms.mri_in = mri_in ; } else { parms.mri_ref = mri_ref_orig ; parms.mri_in = mri_in_orig ; } m_L = initialize_transform(mri_in, mri_ref, &parms) ; if (use_gradient) { MRI *mri_in_mag, *mri_ref_mag, *mri_grad, *mri_mag ; printf("computing gradient magnitude of input image...\n") ; mri_mag = MRIalloc(mri_in->width, mri_in->height, mri_in->depth,MRI_FLOAT); MRIcopyHeader(mri_in, mri_mag) ; mri_grad = MRIsobel(mri_in, NULL, mri_mag) ; MRIfree(&mri_grad) ; /* convert it to ubytes */ MRIvalScale(mri_mag, mri_mag, 0.0f, 255.0f) ; mri_in_mag = MRIclone(mri_in, NULL) ; MRIcopy(mri_mag, mri_in_mag) ; MRIfree(&mri_mag) ; /* now compute gradient of ref image */ printf("computing gradient magnitude of reference image...\n") ; mri_mag = MRIalloc(mri_ref->width, mri_ref->height, mri_ref->depth,MRI_FLOAT); MRIcopyHeader(mri_ref, mri_mag) ; mri_grad = MRIsobel(mri_ref, NULL, mri_mag) ; MRIfree(&mri_grad) ; /* convert it to ubytes */ MRIvalScale(mri_mag, mri_mag, 0.0f, 255.0f) ; mri_ref_mag = MRIclone(mri_ref, NULL) ; MRIcopy(mri_mag, mri_ref_mag) ; MRIfree(&mri_mag) ; register_mri(mri_in_mag, mri_ref_mag, &parms, m_L) ; MRIfree(&mri_in_mag) ; MRIfree(&mri_ref_mag) ; } register_mri(mri_in, mri_ref, &parms, m_L) ; if (check_crop_flag) /* not working yet! */ { printf("searching for cropped regions in the input image...\n") ; parms.mri_crop = find_cropping(mri_orig, mri_ref, &parms) ; MRIwrite(parms.mri_crop, "crop.mgh") ; register_mri(mri_in, mri_ref, &parms, m_L) ; } if (voxel_coords) { printf("transforming xform to voxel coordinates...\n") ; MRIrasXformToVoxelXform(mri_in_orig, mri_ref_orig, parms.lta->xforms[0].m_L, parms.lta->xforms[0].m_L); if (Gdiag & DIAG_WRITE) { MRI *mri_tmp ; mri_tmp = MRIlinearTransform(mri_in_orig, NULL,parms.lta->xforms[0].m_L); MRIwriteImageViews(mri_tmp, "morphed", IMAGE_SIZE) ; MRIfree(&mri_tmp) ; } } // save src and target info in lta getVolGeom(mri_in_orig, &parms.lta->xforms[0].src); getVolGeom(mri_ref_orig, &parms.lta->xforms[0].dst); fprintf(stderr, "writing output transformation to %s...\n", out_fname) ; if (invert_flag) { MATRIX *m_tmp ; m_tmp = MatrixInverse(parms.lta->xforms[0].m_L, NULL) ; MatrixFree(&parms.lta->xforms[0].m_L) ; // change src and dst getVolGeom(mri_in_orig, &parms.lta->xforms[0].dst); getVolGeom(mri_ref_orig, &parms.lta->xforms[0].src); parms.lta->xforms[0].m_L = m_tmp ; } // LTAwriteEx(parms.lta, out_fname) ; // if (mri_ref) MRIfree(&mri_ref) ; if (mri_in) MRIfree(&mri_in) ; msec = TimerStop(&start) ; seconds = nint((float)msec/1000.0f) ; minutes = seconds / 60 ; seconds = seconds % 60 ; fprintf(stderr, "registration took %d minutes and %d seconds.\n", minutes, seconds) ; exit(0) ; return(0) ; }