From b8eec68ade0f1edb0d6ad54761f10010acf3a5bb Mon Sep 17 00:00:00 2001 From: Mark Jenkinson <mark@fmrib.ox.ac.uk> Date: Fri, 5 Nov 2004 17:54:24 +0000 Subject: [PATCH] Added executables for Geoff --- Makefile | 21 +++++- cylsamp.cc | 196 ++++++++++++++++++++++++++++++++++++++++++++++++ surface_norm.cc | 167 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 380 insertions(+), 4 deletions(-) create mode 100644 cylsamp.cc create mode 100644 surface_norm.cc diff --git a/Makefile b/Makefile index 922a516..3a63bd4 100644 --- a/Makefile +++ b/Makefile @@ -2,21 +2,34 @@ include $(FSLCONFDIR)/default.mk PROJNAME = siena -USRINCFLAGS = -I${INC_ZLIB} -USRLDFLAGS = -L${LIB_ZLIB} +USRINCFLAGS = -I${INC_NEWMAT} -I${INC_ZLIB} +USRLDFLAGS = -L${LIB_NEWMAT} -L${LIB_ZLIB} LIBS = -lss_32R -lfslio -lniftiio -lznz -lm -lz +LIBCC = -lnewimage -lmiscmaths -lfslio -lniftiio -lznz -lnewmat -lutils -lm -lz -XFILES = siena_diff +SN_OBJS = surface_norm.o +CS_OBJS = cylsamp.o + +XFILES = siena_diff surface_norm cylsamp SCRIPTS = siena siena_flirt siena_cal sienax siena_flow2tal OPTFLAGS= -all: siena_diff docscripts +MJOPTFLAGS=-O3 + +all: ${XFILES} docscripts siena_diff: siena_diff.c $(CC) $(CFLAGS) -DFDT="float" -o siena_diff siena_diff.c $(LDFLAGS) $(LIBS) +surface_norm: ${SN_OBJS} + ${CXX} ${CXXFLAGS} ${MJOPTFLAGS} ${LDFLAGS} -o $@ ${SN_OBJS} ${LIBCC} + +cylsamp: ${CS_OBJS} + ${CXX} ${CXXFLAGS} ${MJOPTFLAGS} ${LDFLAGS} -o $@ ${CS_OBJS} ${LIBCC} + docscripts: ./makedoc + diff --git a/cylsamp.cc b/cylsamp.cc new file mode 100644 index 0000000..f4acc23 --- /dev/null +++ b/cylsamp.cc @@ -0,0 +1,196 @@ +/* cylsamp.cc + + Mark Jenkinson, FMRIB Image Analysis Group + + Copyright (C) 2004 University of Oxford */ + +/* CCOPYRIGHT */ + +// Performs cylindrical sampling over a surface. That is, averaging +// all values within a cylindrical region centred at each surface +// point on a mask. + + +#define _GNU_SOURCE 1 +#define POSIX_SOURCE 1 + +#include "newimage/newimageall.h" +#include "miscmaths/miscmaths.h" +#include "utils/options.h" + +using namespace MISCMATHS; +using namespace NEWIMAGE; +using namespace Utilities; + +// The two strings below specify the title and example usage that is +// printed out as the help or usage message + +string title="cylsamp (Version 1.0)\nCopyright(c) 2004, University of Oxford (Mark Jenkinson)"; +string examples="cylsamp [options] -i <input mask image> -s <smoothing in mm> -o <output surface normal image>"; + +// Each (global) object below specificies as option and can be accessed +// anywhere in this file (since they are global). The order of the +// arguments needed is: name(s) of option, default value, help message, +// whether it is compulsory, whether it requires arguments +// Note that they must also be included in the main() function or they +// will not be active. + +Option<bool> verbose(string("-v,--verbose"), false, + string("switch on diagnostic messages"), + false, no_argument); +Option<bool> help(string("-h,--help"), false, + string("display this message"), + false, no_argument); +Option<float> radius(string("-r"),5.0, + string("radius of cylinder in mm (default is 5.0)"), + false, requires_argument); +Option<float> height(string("-h"),10.0, + string("height of cylinder in mm (default is 10.0)"), + false, requires_argument); +Option<string> maskname(string("-m"), string(""), + string("input mask image filename"), + true, requires_argument); +Option<string> normname(string("-n"), string(""), + string("input surface normal image filename"), + true, requires_argument); +Option<string> edgemaskname(string("-e"), string(""), + string("input edge mask image filename"), + true, requires_argument); +Option<string> flowname(string("-f"), string(""), + string("input flow image filename"), + true, requires_argument); +Option<string> outname(string("-o"), string(""), + string("output surface normal filename"), + true, requires_argument); +int nonoptarg; + +//////////////////////////////////////////////////////////////////////////// + +// Local functions + +int do_work(int argc, char* argv[]) +{ + volume<float> vflow, vmask, vedgemask, vsamp; + volume4D<float> snorm; + read_volume(vflow,flowname.value()); + read_volume(vmask,maskname.value()); + read_volume(vedgemask,edgemaskname.value()); + read_volume4D(snorm,normname.value()); + + // force input to be a binary mask + if (verbose.value()) print_info(vmask,"vmask"); + vsamp = vmask; + + float r=radius.value(); + float r2 = r*r; + float h=height.value(); + int len=(int) (sqrt(r*r + h*h)) + 1; + + bool atedge; + if (verbose.value()) { cerr << "Performing Cylindrical Sampling" << endl; } + for (int z=vmask.minz(); z<=vmask.maxz(); z++) { + for (int y=vmask.miny(); y<=vmask.maxy(); y++) { + for (int x=vmask.minx(); x<=vmask.maxx(); x++) { + atedge = false; + // check to see if it is an edge point + if ( (vmask(x,y,z)>0.5) ) { + if (vmask(x,y,z-1)<0.5) atedge=true; + else { + if (vmask(x,y-1,z)<0.5) atedge=true; + else { + if (vmask(x-1,y,z)<0.5) atedge=true; + else { + if (vmask(x+1,y,z)<0.5) atedge=true; + else { + if (vmask(x,y+1,z)<0.5) atedge=true; + else { + if (vmask(x,y,z+1)<0.5) atedge=true; + } + } + } + } + } + } + if (atedge) { + // OK, now do the cylindrical sampling + float tot=0.0; + int num=0; + for (int z1=Max(z-len,vmask.minz()); z1<=Min(z+len,vmask.maxz()); z1++) { + for (int y1=Max(y-len,vmask.miny()); y1<=Min(y+len,vmask.maxy()); y1++) { + for (int x1=Max(x-len,vmask.minx()); x1<=Min(x+len,vmask.maxx()); x1++) { + if (vedgemask(x1,y1,z1)>0.5) { + float yy = snorm(x1,y1,z1,0) * (x1 - x) + + snorm(x1,y1,z1,1) * (y1 - y) + + snorm(x1,y1,z1,2) * (z1 - z); + if (fabs(yy)<=h) { + float xx2 = ( Sqr(x1-x) + Sqr(y1-y) + Sqr(z1-z) ) - Sqr(yy); + if (xx2 <= r2) { + // inside cylinder + num++; + tot += vflow(x1,y1,z1); + } + } + } + } + } + } + vsamp(x,y,z) = tot / Max(num,1); // prevent divide by zero + } else { + vsamp(x,y,z) = 0.0; + } + } + } + if (verbose.value()) { cerr << "."; } + } + if (verbose.value()) { cerr << endl; } + + // save the results + save_volume(vsamp,outname.value()); + + return 0; +} + +//////////////////////////////////////////////////////////////////////////// + +int main(int argc,char *argv[]) +{ + + Tracer tr("main"); + OptionParser options(title, examples); + + try { + // must include all wanted options here (the order determines how + // the help message is printed) + options.add(flowname); + options.add(edgemaskname); + options.add(maskname); + options.add(normname); + options.add(outname); + options.add(radius); + options.add(height); + options.add(verbose); + options.add(help); + + nonoptarg = options.parse_command_line(argc, argv); + + // line below stops the program if the help was requested or + // a compulsory option was not set + if ( (help.value()) || (!options.check_compulsory_arguments(true)) ) + { + options.usage(); + exit(EXIT_FAILURE); + } + + } catch(X_OptionError& e) { + options.usage(); + cerr << endl << e.what() << endl; + exit(EXIT_FAILURE); + } catch(std::exception &e) { + cerr << e.what() << endl; + } + + // Call the local functions + + return do_work(argc,argv); +} + diff --git a/surface_norm.cc b/surface_norm.cc new file mode 100644 index 0000000..bdb1aba --- /dev/null +++ b/surface_norm.cc @@ -0,0 +1,167 @@ +/* surface_norm.cc + + Mark Jenkinson, FMRIB Image Analysis Group + + Copyright (C) 2004 University of Oxford */ + +/* CCOPYRIGHT */ + +// Calculates the surface normals for a mask, using a smoothed +// gradient calculation (all non-surface points get zero ouput) + +#define _GNU_SOURCE 1 +#define POSIX_SOURCE 1 + +#include "newimage/newimageall.h" +#include "miscmaths/miscmaths.h" +#include "utils/options.h" + +using namespace MISCMATHS; +using namespace NEWIMAGE; +using namespace Utilities; + +// The two strings below specify the title and example usage that is +// printed out as the help or usage message + +string title="surface_norm (Version 1.0)\nCopyright(c) 2004, University of Oxford (Mark Jenkinson)"; +string examples="surface_norm [options] -i <input mask image> -s <smoothing in mm> -o <output surface normal image>"; + +// Each (global) object below specificies as option and can be accessed +// anywhere in this file (since they are global). The order of the +// arguments needed is: name(s) of option, default value, help message, +// whether it is compulsory, whether it requires arguments +// Note that they must also be included in the main() function or they +// will not be active. + +Option<bool> verbose(string("-v,--verbose"), false, + string("switch on diagnostic messages"), + false, no_argument); +Option<bool> help(string("-h,--help"), false, + string("display this message"), + false, no_argument); +Option<float> smoothing(string("-s"),3.0, + string("smoothing in mm (default is 3.0)"), + false, requires_argument); +Option<string> inname(string("-i"), string(""), + string("input mask filename"), + true, requires_argument); +Option<string> outname(string("-o"), string(""), + string("output surface normal filename"), + true, requires_argument); +int nonoptarg; + +//////////////////////////////////////////////////////////////////////////// + +// Local functions + +int do_work(int argc, char* argv[]) +{ + volume<float> vin; + volume4D<float> snorm; + read_volume(vin,inname.value()); + + // force input to be a binary mask + vin.binarise(0.5); + if (verbose.value()) print_info(vin,"vin"); + + // smooth the mask volume and calculate the gradient + if (verbose.value()) { cerr << "Performing smoothing" << endl; } + { + volume<float> smoothv; + smoothv = smooth(vin,smoothing.value()); + if (verbose.value()) print_info(smoothv,"smoothv"); + if (verbose.value()) { cerr << "Calculating the gradient" << endl; } + gradient(smoothv,snorm); + } + + if (verbose.value()) print_info(snorm,"snorm"); + + bool atedge; + if (verbose.value()) { cerr << "Normalising gradients" << endl; } + // zero all non-surface values and normalise vectors at the surface + for (int z=vin.minz(); z<=vin.maxz(); z++) { + for (int y=vin.miny(); y<=vin.maxy(); y++) { + for (int x=vin.minx(); x<=vin.maxx(); x++) { + atedge = false; + if ( (vin(x,y,z)>0.5) ) { + if (vin(x,y,z-1)<0.5) atedge=true; + else { + if (vin(x,y-1,z)<0.5) atedge=true; + else { + if (vin(x-1,y,z)<0.5) atedge=true; + else { + if (vin(x+1,y,z)<0.5) atedge=true; + else { + if (vin(x,y+1,z)<0.5) atedge=true; + else { + if (vin(x,y,z+1)<0.5) atedge=true; + } + } + } + } + } + } + if (atedge) { + float norm; + norm = 1.0 / sqrt(Sqr(snorm(x,y,z,0)) + Sqr(snorm(x,y,z,1)) + + Sqr(snorm(x,y,z,2)) ); + snorm(x,y,z,0) *= norm; + snorm(x,y,z,1) *= norm; + snorm(x,y,z,2) *= norm; + } else { + snorm(x,y,z,0) = 0.0; + snorm(x,y,z,1) = 0.0; + snorm(x,y,z,2) = 0.0; + } + } + } + if (verbose.value()) { cerr << "."; } + } + if (verbose.value()) { cerr << endl; } + + // save the results + save_volume4D(snorm,outname.value()); + + return 0; +} + +//////////////////////////////////////////////////////////////////////////// + +int main(int argc,char *argv[]) +{ + + Tracer tr("main"); + OptionParser options(title, examples); + + try { + // must include all wanted options here (the order determines how + // the help message is printed) + options.add(inname); + options.add(outname); + options.add(smoothing); + options.add(verbose); + options.add(help); + + nonoptarg = options.parse_command_line(argc, argv); + + // line below stops the program if the help was requested or + // a compulsory option was not set + if ( (help.value()) || (!options.check_compulsory_arguments(true)) ) + { + options.usage(); + exit(EXIT_FAILURE); + } + + } catch(X_OptionError& e) { + options.usage(); + cerr << endl << e.what() << endl; + exit(EXIT_FAILURE); + } catch(std::exception &e) { + cerr << e.what() << endl; + } + + // Call the local functions + + return do_work(argc,argv); +} + -- GitLab