// transforms a 4D Volume in a SVM samples file, based on a mask void saveSVMFile(volume4D <float> &volSamples, volume<float> &mask, const char *outputFileName, float minValue, vector <int > &indexes, vector <int> &classes) { FILE *f; f = fopen(outputFileName, "wt+"); if (f != NULL) { int i, t; for (int h = 0; h < indexes.size(); h++) { // picking the right indexes t = indexes[h] - 1; i = 0; // saving the class value. Remember indexes size is different from classes. classes has the same sime of the number of volumes fprintf(f, "%d ", classes[t]); for (int z = 0; z < mask.zsize(); z++) for (int y = 0; y < mask.ysize(); y++) for (int x = 0; x < mask.xsize(); x++) if (mask.value(x, y, z) > minValue) { i++; // writing each voxel value in svm format fprintf(f, "%d:%f ", i, volSamples.value(x, y, z, t)); } fprintf(f, "\n"); } fclose(f); } }
FnirtFileWriter::FnirtFileWriter(const string& fname, const volume<float>& fieldx, const volume<float>& fieldy, const volume<float>& fieldz) { volume<float> tmp(fieldx.xsize(),fieldx.ysize(),fieldx.zsize()); tmp.copyproperties(fieldx); Matrix aff = IdentityMatrix(4); common_field_construction(fname,tmp,fieldx,fieldy,fieldz,aff); }
volume<float> inside_mesh(const volume<float> & image, const Mesh& m) { volume<float> res = image; int xsize = image.xsize(); int ysize = image.ysize(); int zsize = image.zsize(); volume<short> inside = make_mask_from_mesh(image, m); for (int k=0; k<zsize; k++) for (int j=0; j<ysize; j++) for (int i=0; i<xsize; i++) res.value(i, j, k) = (1-inside.value(i, j, k)) * image.value(i, j, k); return res; }
//calculates the mask from the mesh by spreading an initial point outside the mesh, and stopping it when the mesh is reached. volume<short> make_mask_from_mesh(const volume<float> & image, const Mesh& m) { // cout<<"make_mask_from_mesh begins"<<endl; double xdim = (double) image.xdim(); double ydim = (double) image.ydim(); double zdim = (double) image.zdim(); volume<short> mask; copyconvert(image,mask); int xsize = mask.xsize(); int ysize = mask.ysize(); int zsize = mask.zsize(); mask = 1; mask = draw_mesh(mask, m); vector<Pt> current; current.clear(); Pt c(0., 0., 0.); for (vector<Mpoint *>::const_iterator it=m._points.begin(); it!=m._points.end(); it++) c+=(*it)->get_coord(); c*=(1./m._points.size()); c.X/=xdim; c.Y/=ydim; c.Z/=zdim; current.push_back(c); while (!current.empty()) { Pt pc = current.back(); int x, y, z; x=(int) pc.X; y=(int) pc.Y; z=(int) pc.Z; //current.remove(pc); current.pop_back(); mask.value(x, y, z) = 0; if (0<=x-1 && mask.value(x-1, y, z)==1) current.push_back(Pt(x-1, y, z)); if (0<=y-1 && mask.value(x, y-1, z)==1) current.push_back(Pt(x, y-1, z)); if (0<=z-1 && mask.value(x, y, z-1)==1) current.push_back(Pt(x, y, z-1)); if (xsize>x+1 && mask.value(x+1, y, z)==1) current.push_back(Pt(x+1, y, z)); if (ysize>y+1 && mask.value(x, y+1, z)==1) current.push_back(Pt(x, y+1, z)); if (zsize>z+1 && mask.value(x, y, z+1)==1) current.push_back(Pt(x, y, z+1)); } // cout<<"make_mask_from_mesh ends"<<endl; return mask; }
// calculates the mean for each roi void RoiMeanCalculation::calculateMeans(volume<float> &actualvolume) { if (means.size()) { for (int i = 0; i < means.size(); i++) means[i] = 0; for (int z = 0; z < reference.zsize(); z++) for (int y = 0; y < reference.ysize(); y++) for (int x = 0; x < reference.xsize(); x++) { float value = reference.value(x, y, z); if (value != 0) { int idx = mapping[value]; if (idx >= -1) means[idx] += actualvolume.value(x, y, z); } } for (int i = 0; i < means.size(); i++) { if (counts[i]) means[i] = means[i] / (float)counts[i]; } } }
//extracts profiles in the area around the eyes vector<double> t1only_special_extract(const volume<float> & t1, const Pt & point, const Vec & n) { vector<double> resul; resul.clear(); bool output = true; const double INNER_DEPTH = 3; const double OUTER_DEPTH = 100; Profile pt1; for (double d = -INNER_DEPTH; d < OUTER_DEPTH; d+=.5) { Pt c = point + d * n; double tmp1 = t1.interpolate(c.X, c.Y, c.Z); pt1.add (d, tmp1); } pt1.init_roi(); //outer skin double outskin = pt1.last_point_over(pt1.end(), .2); double check = pt1.last_point_over(outskin - 1.5, .2); if (outskin - check > 2) output = false; pt1.set_rroi(outskin); double inskull = pt1.next_point_under(-INNER_DEPTH, .25); if (inskull > 5) inskull = 0; double outskull = pt1.next_point_over(inskull, .35); resul.push_back(inskull); resul.push_back(outskull); resul.push_back(outskin); return resul; }
void _volume2Sample(svm_model *model, volume<float> &volSample, volume<float> &mask, int sampleSize, float minValue, svm_node * &sample) { sample=(struct svm_node *) malloc((sampleSize+1)*sizeof(struct svm_node)); int i=0; for(int z=0; z < volSample.zsize();z++) for(int y=0; y < volSample.ysize();y++) for(int x=0; x < volSample.xsize();x++) if (mask.value(x,y,z) > minValue) { sample[i].index = (i+1); sample[i].value = volSample.value(x,y,z); i++; } sample[i].index = -1; }
void draw_segment(volume<short>& image, const Pt& p1, const Pt& p2) { double xdim = (double) image.xdim(); double ydim = (double) image.ydim(); double zdim = (double) image.zdim(); double mininc = min(xdim,min(ydim,zdim)) * .5; Vec n = p1 - p2; double d = n.norm(); n.normalize(); for (double i=0; i<=d; i+=mininc) { Pt p = p2 + i* n; image((int) floor((p.X)/xdim +.5),(int) floor((p.Y)/ydim +.5),(int) floor((p.Z)/zdim +.5)) = 1; } }
void draw_mesh(volume<short>& image, const Mesh &m) { double xdim = (double) image.xdim(); double ydim = (double) image.ydim(); double zdim = (double) image.zdim(); double mininc = min(xdim,min(ydim,zdim)) * .5; for (list<Triangle*>::const_iterator i = m._triangles.begin(); i!=m._triangles.end(); i++) { Vec n = (*(*i)->get_vertice(0) - *(*i)->get_vertice(1)); double d = n.norm(); n.normalize(); for (double j=0; j<=d; j+=mininc) { Pt p = (*i)->get_vertice(1)->get_coord() + j* n; draw_segment(image, p, (*i)->get_vertice(2)->get_coord()); } } }
void check_integral(fields &f, linear_integrand_data &d, const volume &v, component cgrid) { double x1 = v.in_direction_min(d.dx); double x2 = v.in_direction_max(d.dx); double y1 = v.in_direction_min(d.dy); double y2 = v.in_direction_max(d.dy); double z1 = v.in_direction_min(d.dz); double z2 = v.in_direction_max(d.dz); master_printf("Check %d-dim. %s integral in %s cell with %s integrand...", (x2 - x1 > 0) + (y2 - y1 > 0) + (z2 - z1 > 0), component_name(cgrid), v.dim == D3 ? "3d" : (v.dim == D2 ? "2d" : (v.dim == Dcyl ? "cylindrical" : "1d")), (d.c == 1.0 && !d.axy && !d.ax && !d.ay && !d.az && !d.axy && !d.ayz && !d.axz) ? "unit" : "linear"); if (0) master_printf("\n... grid_volume (%g,%g,%g) at (%g,%g,%g) with integral (%g, %g,%g,%g, %g,%g,%g, %g)...\n", x2 - x1, y2 - y1, z2 - z1, (x1+x2)/2, (y1+y2)/2, (z1+z2)/2, d.c, d.ax,d.ay,d.az, d.axy,d.ayz,d.axz, d.axyz); double sum = real(f.integrate(0, 0, linear_integrand, (void *) &d, v)); if (fabs(sum - correct_integral(v, d)) > 1e-9 * fabs(sum)) abort("FAILED: %0.16g instead of %0.16g\n", (double) sum, correct_integral(v, d)); master_printf("...PASSED.\n"); }
volume<float> draw_mesh_bis(const volume<float>& image, const Mesh &m) { double xdim = (double) image.xdim(); double ydim = (double) image.ydim(); double zdim = (double) image.zdim(); double mininc = min(xdim,min(ydim,zdim)) * .5; volume<float> res = image; double max = image.max(); for (list<Triangle*>::const_iterator i = m._triangles.begin(); i!=m._triangles.end(); i++) { Vec n = (*(*i)->get_vertice(0) - *(*i)->get_vertice(1)); double d = n.norm(); n.normalize(); for (double j=0; j<=d; j+=mininc) { Pt p = (*i)->get_vertice(1)->get_coord() + j* n; draw_segment_bis(res, p, (*i)->get_vertice(2)->get_coord(), max); } } return res; }
// transforms an array in a volume void array2Volume(const char *maskFile, float minValue, vector <double> &weightVector, volume<float> &weightVolume) { volume<float> mask; if (maskFile != NULL) { string Maskfile = maskFile; read_volume(mask, Maskfile); } weightVolume.reinitialize(mask.xsize(), mask.ysize(), mask.zsize(), 0, true); weightVolume.copyproperties(mask); int i = 0; for(int z=0;z < mask.zsize();z++) for(int y=0;y < mask.ysize();y++) for(int x=0;x < mask.xsize();x++) if (mask.value(x,y,z) > minValue) { weightVolume.value(x,y,z) = (float) weightVector[i]; i++; } else weightVolume.value(x,y,z) = (float) 0.0; }
void vega::data::hexagonal_prismatic_lattice::fill_volume_cell( volume& v, const prismatic_hexagon_node & node ) { static const int hex_pixel_offset[8][2] = { {1, 0}, {2, 0}, {0, 1}, {1, 1}, {2, 1}, {3, 1}, {1, 2}, {2, 2}}; math::vector3d vertex = node.get_vertex(); for(size_t h=0;h<8;++h) { math::vector3d pixel; int xx = (int)vertex.x + hex_pixel_offset[h][0]; int yy = (int)vertex.y + hex_pixel_offset[h][1]; int zz = (int)vertex.z; if( xx >= 0 && yy >= 0 && zz >= 0 && xx < v.get_width() && yy < v.get_height() && zz < v.get_depth() ) { #ifndef USE_COLOR_MAP v.set_voxel(xx, yy, zz, (voxel)(node.density * 255.f)); #else v.set_voxel(xx, yy, zz, (voxel)(node.color.A)); #endif } } }
void basisfield::AsVolume(volume<float>& vol, FieldIndex fi) { if (int(FieldSz_x()) != vol.xsize() || int(FieldSz_y()) != vol.ysize() || int(FieldSz_z()) != vol.zsize()) { throw BasisfieldException("basisfield::AsVolume:: Matrix size mismatch beween field and volume"); } if (Vxs_x() != vol.xdim() || Vxs_y() != vol.ydim() || Vxs_z() != vol.zdim()) { throw BasisfieldException("basisfield::AsVolume:: Voxel size mismatch beween field and volume"); } if (!coef) {throw BasisfieldException("basisfield::AsVolume: Coefficients undefined");} if (!UpToDate(fi)) {Update(fi);} const boost::shared_ptr<NEWMAT::ColumnVector> tmptr = Get(fi); int vindx=0; for (unsigned int k=0; k<FieldSz_z(); k++) { for (unsigned int j=0; j<FieldSz_y(); j++) { for (unsigned int i=0; i<FieldSz_x(); i++) { vol(i,j,k) = tmptr->element(vindx++); } } } }
void basisfield::Set(const volume<float>& pfield) { if (int(FieldSz_x()) != pfield.xsize() || int(FieldSz_y()) != pfield.ysize() || int(FieldSz_z()) != pfield.zsize()) { throw BasisfieldException("basisfield::Set:: Matrix size mismatch beween basisfield class and supplied field"); } if (Vxs_x() != pfield.xdim() || Vxs_y() != pfield.ydim() || Vxs_z() != pfield.zdim()) { throw BasisfieldException("basisfield::Set:: Voxel size mismatch beween basisfield class and supplied field"); } volume<float> volume_of_ones(pfield.xsize(),pfield.ysize(),pfield.zsize()); volume_of_ones.copyproperties(pfield); volume_of_ones = 1.0; double lambda = 0.001; ColumnVector y = Jte(pfield,0); boost::shared_ptr<MISCMATHS::BFMatrix> XtX = JtJ(volume_of_ones); boost::shared_ptr<MISCMATHS::BFMatrix> BeEn = BendEnergyHess(); XtX->AddToMe(*BeEn,lambda); ColumnVector coef_roof = XtX->SolveForx(y,SYM_POSDEF,1e-6,500); SetCoef(coef_roof); }
// returns in `output` the best voxels of `region` void RegionExtraction::regionBestVoxels(RoiMeanCalculation &reference, volume<float>&values, volume<float>&output, int region, int regionSize, float percentage) { vector<roiPoint> roi; roi.resize(regionSize); greaterRoiPoint greaterFirst; int index=0; // Filter the voxels of the region `region` for(int z=0;z<values.zsize();z++) for(int y=0;y<values.ysize();y++) for(int x=0;x<values.xsize();x++) { // get the voxel intensity in reference int voxelRegion = (int) reference.voxelValues(x,y,z); // if is the chosen region, records the voxel values (T values or other voxel value) if (region == voxelRegion) { roi[index].value = values.value(x,y,z); roi[index].roiValue = region; roi[index].x=x; roi[index].y=y; roi[index].z=z; index++; } else values.value(x,y,z)=(float)0.0; } // sorts the vector of values in descending order std::sort(roi.begin(), roi.end(), greaterFirst); // calculates the cut Index. Remember the voxels descending order int cutIndex = (int) (roi.size() * percentage + 0.5); // recording the result in `output` for (int j=0; j<=cutIndex;j++) { output.value(roi[j].x, roi[j].y, roi[j].z) = roi[j].roiValue; } }
static double correct_integral(const volume &v, const linear_integrand_data &data) { direction x = data.dx, y = data.dy, z = data.dz; double x1 = v.in_direction_min(x); double x2 = v.in_direction_max(x); double y1 = v.in_direction_min(y); double y2 = v.in_direction_max(y); double z1 = v.in_direction_min(z); double z2 = v.in_direction_max(z); return (data.c * integral1(x1,x2,x) * integral1(y1,y2,y) * integral1(z1,z2,z) + data.ax * integralx(x1,x2,x) * integral1(y1,y2,y) * integral1(z1,z2,z) + data.ay * integral1(x1,x2,x) * integralx(y1,y2,y) * integral1(z1,z2,z) + data.az * integral1(x1,x2,x) * integral1(y1,y2,y) * integralx(z1,z2,z) + data.axy * integralx(x1,x2,x) * integralx(y1,y2,y) * integral1(z1,z2,z) + data.ayz * integral1(x1,x2,x) * integralx(y1,y2,y) * integralx(z1,z2,z) + data.axz * integralx(x1,x2,x) * integral1(y1,y2,y) * integralx(z1,z2,z) + data.axyz * integralx(x1,x2,x) * integralx(y1,y2,y) * integralx(z1,z2,z) ); }
vector<double> t1only_co_ext(const volume<float> & t1, const Pt & point, const Vec & n) { vector<double> resul; resul.clear(); bool output = true; bool alloutput = true; const double INNER_DEPTH = 3; const double OUTER_DEPTH = 60; Profile pt1; for (double d = -INNER_DEPTH; d < OUTER_DEPTH; d+=.5) { Pt c = point + d * n; double tmp1 = t1.interpolate(c.X, c.Y, c.Z); pt1.add (d, tmp1); } pt1.init_roi(); //outer skin double outskin = pt1.last_point_over(pt1.end(), .2); double check = pt1.last_point_over(outskin - 1.5, .2); if (outskin - check > 2) outskin = check; const double OUTER_SKIN = outskin; pt1.set_rroi(OUTER_SKIN); double inskull = pt1.next_point_under(pt1.begin(), .25); pt1.set_lroi(inskull); if (alloutput) { //outer skull //starting from the skin double outskull2 = 0; outskull2 = pt1.last_point_over(outskin, .75); outskull2 = pt1.last_point_under(outskull2, .20); //starting from the brain double minabs = pt1.next_point_under(pt1.begin(), .30); if (minabs == -500) output = false; minabs = Max(minabs, -INNER_DEPTH); double localminabs = minabs;//0 if (output) { bool stop = false; const double lowthreshold = pt1.threshold(.15); const double upthreshold = pt1.threshold(.60); int test = 0; for (vector<pro_pair>::const_iterator i = pt1.v.begin(); i != pt1.v.end(); i++) { if (!stop && (*i).abs>=minabs && i!=pt1.v.end() && i!=pt1.v.begin()) { if ((*i).val>upthreshold) stop = true; //avoid climbing skin if ((*i).val>lowthreshold) test++; if ((*i).val<lowthreshold) test--; if (test < 0) test=0; if (test == 12) {stop = true;} if ((*i).val<lowthreshold) { localminabs = (*i).abs; } } } } double outskull = pt1.next_point_over(localminabs, .15);//.20 if (outskull2 - outskull < -2 || outskull2 - outskull >= 2) {output = false;} if (outskin - outskull2 < 2) output = false; if (output) { resul.push_back(inskull); resul.push_back(outskull2); resul.push_back(outskin); } else resul.push_back(outskin); } return resul; }
//writes externall skull computed from image on output. void t1only_write_ext_skull(volume<float> & output_inskull, volume<float> & output_outskull, volume<float> & output_outskin, const volume<float> & t1, const Mesh & m, const trMatrix & M) { int glob_counter = 0; int rem_counter = 0; const double xdim = t1.xdim(); const double ydim = t1.ydim(); const double zdim = t1.zdim(); double imax = t1.max(); if (imax == 0) imax = 1; volume<short> meshimage; copyconvert(t1, meshimage); meshimage = 0; draw_mesh(meshimage, m); for (vector<Mpoint*>::const_iterator i = m._points.begin(); i != m._points.end(); i++) { (*i)->data.clear(); double max_neighbour = 0; const Vec normal = (*i)->local_normal(); const Vec n = Vec(normal.X/xdim, normal.Y/ydim, normal.Z/zdim); for (list<Mpoint*>::const_iterator nei = (*i)->_neighbours.begin(); nei != (*i)->_neighbours.end(); nei++) max_neighbour = Max(((**i) - (**nei)).norm(), max_neighbour); max_neighbour = ceil((max_neighbour)/2); const Pt mpoint((*i)->get_coord().X/xdim,(*i)->get_coord().Y/ydim,(*i)->get_coord().Z/zdim); for (int ck = (int)floor(mpoint.Z - max_neighbour/zdim); ck <= (int)floor(mpoint.Z + max_neighbour/zdim); ck++) for (int cj = (int)floor(mpoint.Y - max_neighbour/ydim); cj <= (int)floor(mpoint.Y + max_neighbour/ydim); cj++) for (int ci = (int)floor(mpoint.X - max_neighbour/xdim); ci <= (int)floor(mpoint.X + max_neighbour/xdim); ci++) { bool compute = false; const Pt point(ci, cj, ck); const Pt realpoint(ci*xdim, cj*ydim, ck*zdim); if (meshimage(ci, cj, ck) == 1) { double mindist = 10000; for (list<Mpoint*>::const_iterator nei = (*i)->_neighbours.begin(); nei != (*i)->_neighbours.end(); nei++) mindist = Min(((realpoint) - (**nei)).norm(), mindist); if (mindist >= ((realpoint) - (**i)).norm()) compute = true; } if (compute) { glob_counter ++; vector<double> val; if (!special_case(realpoint, normal, M)) val = t1only_co_ext(t1, point, n); else { val = t1only_special_extract(t1, point, n); } if (val.size() == 3) { Pt opoint(point.X, point.Y, point.Z); Vec on(n.X, n.Y, n.Z); Pt c0 = opoint + val[0]*on; Pt c1 = opoint + val[1]*on; Pt c2 = opoint + val[2]*on; output_inskull((int)floor(c0.X + .5) + infxm,(int) floor(c0.Y + .5) + infym,(int) floor(c0.Z + .5) + infzm) +=1; output_outskull((int)floor(c1.X + .5) + infxm,(int) floor(c1.Y + .5) + infym,(int) floor(c1.Z + .5) + infzm)+=1; output_outskin((int)floor(c2.X + .5) + infxm,(int) floor(c2.Y + .5) + infym,(int) floor(c2.Z + .5) + infzm) +=1; } else { rem_counter++; if (val.size()==1) { Pt opoint(point.X, point.Y, point.Z); Vec on(n.X, n.Y, n.Z); Pt c0 = opoint + val[0]*on; output_outskin((int)floor(c0.X + .5) + infxm,(int) floor(c0.Y + .5) + infym,(int) floor(c0.Z + .5) + infzm) +=1; } } } } } if (verbose.value()) { cout<<" nb of profiles : "<<glob_counter<<endl; cout<<" removed profiles : "<<100. * rem_counter/(double) glob_counter<<"%"<<endl; } }
double standard_step_of_computation(const volume<float> & image, Mesh & m, const int iteration_number, const double E,const double F, const float addsmooth, const float speed, const int nb_iter, const int id, const int od, const bool vol, const volume<short> & mask){ double xdim = image.xdim(); double ydim = image.ydim(); double zdim = image.zdim(); if (nb_iter % 50 == 0) { double l2 = 0; int counter = 0; for (vector<Mpoint*>::iterator i = m._points.begin(); i!=m._points.end(); i++ ) { counter++; l2 += (*i)->medium_distance_of_neighbours(); } l = l2/counter; } if (nb_iter % 100 == 0) { for (vector<Mpoint*>::iterator i = m._points.begin(); i!=m._points.end(); i++) { Vec n = (*i)->local_normal(); Pt point = (*i)->get_coord(); Pt ipoint(point.X/xdim, point.Y/ydim, point.Z/zdim); Vec in(n.X/xdim, n.Y/ydim, n.Z/zdim); double max = 0; Pt c_m1 = ipoint + (-1) * in; double current = image.interpolate((c_m1.X),(c_m1.Y),(c_m1.Z)); for (double i2 = 1; i2 < 150; i2+=2) { if (max > .1) break; Pt c_p = ipoint + i2 * in; double tmpp = image.interpolate((c_p.X),(c_p.Y),(c_p.Z)); double tmp = (tmpp - current) * 100; max = Max(max, tmp); current = tmpp; if (tmpp > .1) {max = 1; break;} } if (max < .1) { //There is a problem here for precision mode, since with the copy, no guarantee that data is non-zero size //even if mesh.cpp operator = is modified to copy data, after retesselate "new" points will have zero size data member if ( (*i)->data.size() ) (*i)->data.pop_back(); (*i)->data.push_back(1); } else { if ( (*i)->data.size() ) (*i)->data.pop_back(); (*i)->data.push_back(0); } } } for (vector<Mpoint*>::iterator i = m._points.begin(); i!=m._points.end(); i++) { Vec sn, st, u1, u2, u3, u; double f2, f3=0; Vec n = (*i)->local_normal(); Vec dv = (*i)->difference_vector(); double tmp = dv|n; sn = n * tmp; st = dv - sn; u1 = st*.5; double rinv = (2 * fabs(sn|n))/(l*l); f2 = (1+tanh(F*(rinv - E)))*0.5; u2 = f2 * sn * addsmooth; if ((*i)->data.back() == 0) { //main term of skull_extraction { Pt point = (*i)->get_coord(); Pt ipoint(point.X/xdim, point.Y/ydim, point.Z/zdim); Vec in(n.X/xdim, n.Y/ydim, n.Z/zdim); Pt c_m = ipoint + (-1.) * in; Pt c_p = ipoint + 1. * in; double tmp = image.interpolate((c_p.X ),( c_p.Y),(c_p.Z)); double gradient = tmp - image.interpolate((c_m.X),(c_m.Y), (c_m.Z)); double tmp2 = gradient*100; f3 = max(-1., min(tmp2, 1.)); if (tmp2 >= 0 && tmp2 < .1 && tmp < .1 ) f3 = speed; if (vol) { double tmpvol = mask.interpolate((ipoint.X ),(ipoint.Y),(ipoint.Z)); if (tmpvol > .0) { f3 = Max(Max(tmpvol*.5, .1), f3); f2 = 0; } } } } else { f3 = 0; Pt point = (*i)->get_coord(); Pt ipoint(point.X/xdim, point.Y/ydim, point.Z/zdim); double tmpvol = mask.interpolate((ipoint.X ),(ipoint.Y),(ipoint.Z)); if (tmpvol > .0) { f3 = Max(tmpvol*.5, .1); f2 = 0; } } u3 = .05 * f3 * n; u = u1 + u2 + u3; (*i)->_update_coord = (*i)->get_coord() + u; } m.update(); return (0); }
bet_parameters adjust_initial_mesh(const volume<float> & image, Mesh& m, const double & rad = 0., const double xpara=0., const double ypara=0., const double zpara=0.) { bet_parameters bp; double xdim = image.xdim(); double ydim = image.ydim(); double zdim = image.zdim(); double t2, t98, t; //computing t2 && t98 // cout<<"computing robust min && max begins"<<endl; bp.min = image.min(); bp.max = image.max(); t2 = image.robustmin(); t98 = image.robustmax(); //t2=32.; //t98=16121.; // cout<<"computing robust min && max ends"<<endl; t = t2 + .1*(t98 - t2); bp.t98 = t98; bp.t2 = t2; bp.t = t; // cout<<"t2 "<<t2<<" t98 "<<t98<<" t "<<t<<endl; // cout<<"computing center && radius begins"<<endl; //finds the COG Pt center(0, 0, 0); double counter = 0; if (xpara == 0. & ypara==0. & zpara==0.) { double tmp = t - t2; for (int k=0; k<image.zsize(); k++) for (int j=0; j<image.ysize(); j++) for (int i=0; i<image.xsize(); i++) { double c = image(i, j, k ) - t2; if (c > tmp) { c = min(c, t98 - t2); counter+=c; center += Pt(c*i*xdim, c*j*ydim, c*k*zdim); } } center=Pt(center.X/counter, center.Y/counter, center.Z/counter); //cout<<counter<<endl; // cout<<"cog "<<center.X<<" "<<center.Y<<" "<<center.Z<<endl; } else center=Pt(xpara, ypara, zpara); bp.cog = center; if (rad == 0.) { double radius=0; counter=0; double scale=xdim*ydim*zdim; for (int k=0; k<image.zsize(); k++) for (int j=0; j<image.ysize(); j++) for (int i=0; i<image.xsize(); i++) { double c = image(i, j, k); if (c > t) { counter+=1; } } radius = pow (.75 * counter*scale/M_PI, 1.0/3.0); // cout<<radius<<endl; bp.radius = radius; } else (bp.radius = rad); m.translation(center.X, center.Y, center.Z); m.rescale (bp.radius/2, center); // cout<<"computing center && radius ends"<<endl; //computing tm // cout<<"computing tm begins"<<endl; vector<double> vm; for (int k=0; k<image.zsize(); k++) for (int j=0; j<image.ysize(); j++) for (int i=0; i<image.xsize(); i++) { double d = image.value(i, j, k); Pt p(i*xdim, j*ydim, k*zdim); if (d > t2 && d < t98 && ((p - center)|(p - center)) < bp.radius * bp.radius) vm.push_back(d); } int med = (int) floor(vm.size()/2.); // cout<<"before sort"<<endl; nth_element(vm.begin(), vm.begin() + med - 1, vm.end()); //partial_sort(vm.begin(), vm.begin() + med + 1, vm.end()); //double tm = vm[med]; double tm=(*max_element(vm.begin(), vm.begin() + med)); // cout<<"tm "<<tm<<endl; bp.tm = tm; // cout<<"computing tm ends"<<endl; return bp; }
double step_of_computation(const volume<float> & image, Mesh & m, const double bet_main_parameter, const int pass, const double increase_smoothing, const int iteration_number, double & l, const double t2, const double tm, const double t, const double E,const double F, const double zcog, const double radius, const double local_th=0., const int d1=7, const int d2=3){ double xdim = image.xdim(); double ydim = image.ydim(); double zdim = image.zdim(); if (iteration_number==50 || iteration_number%100 == 0 ) { l = 0; int counter = 0; for (vector<Mpoint*>::iterator i = m._points.begin(); i!=m._points.end(); i++ ) { counter++; l += (*i)->medium_distance_of_neighbours(); } l/=counter; } for (vector<Mpoint*>::iterator i = m._points.begin(); i!=m._points.end(); i++) { Vec sn, st, u1, u2, u3, u; double f2, f3=0; Vec n = (*i)->local_normal(); Vec dv = (*i)->difference_vector(); double tmp = dv|n; sn = n * tmp; st = dv - sn; u1 = st*.5; double rinv = (2 * fabs(sn|n))/(l*l); f2 = (1+tanh(F*(rinv - E)))*0.5; if (pass > 0) if (tmp > 0) { f2*=increase_smoothing; f2 = Min(f2, 1.); } u2 = f2 * sn; //main term of bet { double local_t = bet_main_parameter; if (local_th != 0.0) { local_t = Min(1., Max(0., bet_main_parameter + local_th*((*i)->get_coord().Z - zcog)/radius)); } double Imin = tm; double Imax = t; Pt p = (*i)->get_coord() + (-1)*n; double iv = p.X/xdim + .5, jv = p.Y/ydim +.5, kv = p.Z/zdim +.5; if (image.in_bounds((int)iv,(int) jv,(int) kv)) { double im=image.value((int)iv,(int)jv,(int)kv); Imin = Min(Imin, im); Imax = Max(Imax,im); double nxv=n.X/xdim, nyv=n.Y/ydim, nzv=n.Z/zdim; int i2=(int)(iv-(d1-1)*nxv), j2 =(int) (jv-(d1-1)*nyv), k2 =(int)(kv-(d1-1)*nzv); if (image.in_bounds(i2, j2, k2)) { im=image.value(i2,j2,k2); Imin = Min(Imin, im); for (int gi=2; gi<d1; gi++) { // the following is a quick calc of Pt p = (*i)->get_coord() + (-gi)*n; iv-=nxv; jv-=nyv; kv-=nzv; im = image.value((int) (iv), (int) (jv), (int) (kv)); Imin = Min(Imin, im); if (gi<d2) Imax = Max(Imax,im); } Imin = Max (t2, Imin); Imax = Min (tm, Imax); const double tl = (Imax - t2) * local_t + t2; if (Imax - t2 > 0) f3=2*(Imin - tl)/(Imax - t2); else f3=(Imin - tl)*2; } } } f3 *= (normal_max_update_fraction * lambda_fit * l); u3 = f3 * n; u = u1 + u2 + u3; //cout<<"l "<<l<<"u1 "<<((u1*n).norm())<<"u2 "<<(u2|n)<<"u3 "<<(u3|n)<<endl; (*i)->_update_coord = (*i)->get_coord() + u; } m.update(); return (0); }
volume<float> find_skull (volume<float> & image, const Mesh & m, const double t2, double t, double t98) { const double skull_search = 30; const double skull_start = -3; volume<float> result = image; result=0; volume<short> volmesh; copyconvert(image,volmesh); int xsize = volmesh.xsize(); int ysize = volmesh.ysize(); int zsize = volmesh.zsize(); double xdim = volmesh.xdim(); double ydim = volmesh.ydim(); double zdim = volmesh.zdim(); double scale = Min(xdim, Min(ydim, zdim)); volmesh = 1; volmesh = draw_mesh(volmesh, m); image.setinterpolationmethod(trilinear); for (vector<Mpoint*>::const_iterator i = m._points.begin(); i != m._points.end(); i++) { double max_neighbour = 0; const Vec normal = (*i)->local_normal(); const Vec n = Vec(normal.X/xdim, normal.Y/ydim, normal.Z/zdim); for (list<Mpoint*>::const_iterator nei = (*i)->_neighbours.begin(); nei != (*i)->_neighbours.end(); nei++) max_neighbour = Max(((**i) - (**nei)).norm(), max_neighbour); max_neighbour = ceil((max_neighbour)/2); const Pt mpoint((*i)->get_coord().X/xdim,(*i)->get_coord().Y/ydim,(*i)->get_coord().Z/zdim); for (int ck = (int)floor(mpoint.Z - max_neighbour/zdim); ck <= (int)floor(mpoint.Z + max_neighbour/zdim); ck++) for (int cj = (int)floor(mpoint.Y - max_neighbour/ydim); cj <= (int)floor(mpoint.Y + max_neighbour/ydim); cj++) for (int ci = (int)floor(mpoint.X - max_neighbour/xdim); ci <= (int)floor(mpoint.X + max_neighbour/xdim); ci++) { bool compute = false; const Pt point(ci, cj, ck); const Pt realpoint(ci*xdim, cj*ydim, ck*zdim); if (volmesh(ci, cj, ck) == 0) { double mindist = 10000; for (list<Mpoint*>::const_iterator nei = (*i)->_neighbours.begin(); nei != (*i)->_neighbours.end(); nei++) mindist = Min(((realpoint) - (**nei)).norm(), mindist); if (mindist >= ((realpoint) - (**i)).norm()) compute = true; } if (compute) { double maxval = t; double minval = image.interpolate(point.X, point.Y, point.Z); double d_max = 0; for (double d=0; d<skull_search; d+=scale*.5) { Pt current = point + d * n; double val = image.interpolate(current.X, current.Y, current.Z); if (val>maxval) { maxval=val; d_max=d; } if (val<minval) minval=val; } if (maxval > t) { double d_min=skull_start; double maxJ =-1000000; double lastJ=-2000000; for(double d=skull_start; d<d_max; d+=scale*0.5) { Pt current = point + d * n; if (current.X >= 0 && current.Y >= 0 && current.Z >= 0 && current.X<xsize && current.Y<ysize && current.Z<zsize) { double tmpf = d/30 - image.interpolate(current.X, current.Y, current.Z) / (t98 - t2); if (tmpf > maxJ) { maxJ=tmpf; d_min = d; } lastJ=tmpf; } } double maxgrad = 0; double d_skull; Pt current2 = point + d_min * n; if (current2.X >= 0 && current2.Y >= 0 && current2.Z >= 0 && current2.X<xsize && current2.Y<ysize && current2.Z<zsize) { double val2 = image.interpolate(current2.X, current2.Y, current2.Z); for(double d=d_min + scale; d<d_max; d+=0.5*scale) { Pt current = point + d * n; if (current.X >= 0 && current.Y >= 0 && current.Z >= 0 && current.X<xsize && current.Y<ysize && current.Z<zsize) { double val = image.interpolate(current.X, current.Y, current.Z); double grad = val - val2; val2 = val; if (grad > 0) { if (grad > maxgrad) { maxgrad=grad; d_skull=d; } else d = d_max; } } } } if (maxgrad > 0) { Pt current3 = point + d_skull * n; if (current3.X >= 0 && current3.Y >= 0 && current3.Z >= 0 && current3.X<xsize && current3.Y<ysize && current3.Z<zsize) result ((int)current3.X, (int)current3.Y, (int)current3.Z) = 100/*max*/; } } } } } return result; }
void FnirtFileWriter::common_field_construction(const string& fname, const volume<float>& ref, const volume<float>& fieldx, const volume<float>& fieldy, const volume<float>& fieldz, const Matrix& aff) { volume4D<float> fields(ref.xsize(),ref.ysize(),ref.zsize(),3); fields.copyproperties(ref); Matrix M; bool add_affine = false; if (add_affine = ((aff-IdentityMatrix(4)).MaximumAbsoluteValue() > 1e-6)) { // Add affine part to fields M = (aff.i() - IdentityMatrix(4))*ref.sampling_mat(); } if (samesize(ref,fieldx,true)) { // If ref is same size as the original field fields[0] = fieldx; fields[1] = fieldy; fields[2] = fieldz; fields.copyproperties(ref); // Put qform/sform and stuff back. if (add_affine) { ColumnVector xv(4), xo(4); int zs = ref.zsize(), ys = ref.ysize(), xs = ref.xsize(); xv(4) = 1.0; for (int z=0; z<zs; z++) { xv(3) = double(z); for (int y=0; y<ys; y++) { xv(2) = double(y); for (int x=0; x<xs; x++) { xv(1) = double(x); xo = M*xv; fields(x,y,z,0) += xo(1); fields(x,y,z,1) += xo(2); fields(x,y,z,2) += xo(3); } } } } } else { fieldx.setextrapolationmethod(extraslice); fieldy.setextrapolationmethod(extraslice); fieldz.setextrapolationmethod(extraslice); Matrix R2F = fieldx.sampling_mat().i() * ref.sampling_mat(); ColumnVector xv(4), xo(4), xr(4); int zs = ref.zsize(), ys = ref.ysize(), xs = ref.xsize(); xv(4) = 1.0; for (int z=0; z<zs; z++) { xv(3) = double(z); for (int y=0; y<ys; y++) { xv(2) = double(y); for (int x=0; x<xs; x++) { xv(1) = double(x); xr = R2F*xv; fields(x,y,z,0) = fieldx.interpolate(xr(1),xr(2),xr(3)); fields(x,y,z,1) = fieldy.interpolate(xr(1),xr(2),xr(3)); fields(x,y,z,2) = fieldz.interpolate(xr(1),xr(2),xr(3)); if (add_affine) { xo = M*xv; fields(x,y,z,0) += xo(1); fields(x,y,z,1) += xo(2); fields(x,y,z,2) += xo(3); } } } } } fields.set_intent(FSL_FNIRT_DISPLACEMENT_FIELD,fields.intent_param(0),fields.intent_param(1),fields.intent_param(2)); fields.setDisplayMaximum(0.0); fields.setDisplayMinimum(0.0); // Save resulting field save_volume4D(fields,fname); }
void volume::inset(double x_inset, double y_inset, double z_inset, volume& dst) const { dst = *this; dst.inset(x_inset, y_inset, z_inset); }
vega::data::hexagonal_prismatic_lattice::hexagonal_prismatic_lattice( const volume& v ) { VEGA_LOG_FN; // Lattice L = {Lx, Ly, Lz}; static const int Lx[3] = {2, -1, 0}; static const int Ly[3] = {0, 2, 0}; static const int Lz[3] = {0, 0, 1}; myWidth = v.get_width() / 2; myHeight = v.get_height() / 2; myDepth = v.get_depth(); assert(myWidth > 0 && myHeight > 0 && myDepth > 0); myLatticeCells.reserve(myWidth * myHeight * myDepth); for(uint16 k=0;k<myDepth;++k) { for(uint16 i=0;i<myHeight;++i) { for(uint16 j=0;j<myWidth;++j) { prismatic_hexagon_node cell; cell.x = j; cell.y = i + j/2 + j%2; cell.z = k; static const int hex_neighbor_offset[NEIGHBOR_COUNT][3] = { {1, 1, 0}, {0, 1, 0}, {-1, 0, 0}, {-1, -1, 0}, {0, -1, 0}, {1, 0, 0}, {0, 0,-1}, #if NEIGHBOR_COUNT==20 {1, 1,-1}, {0, 1,-1}, {-1, 0,-1}, {-1, -1,-1}, {0, -1,-1}, {1, 0,-1}, #endif {0, 0, 1}, #if NEIGHBOR_COUNT==20 {1, 1, 1}, {0, 1, 1}, {-1, 0, 1}, {-1, -1, 1}, {0, -1, 1}, {1, 0, 1} #endif }; for(int h=0; h<NEIGHBOR_COUNT; ++h) { int hj = cell.x + hex_neighbor_offset[h][0]; int hi = cell.y + hex_neighbor_offset[h][1] - hj/2 - hj%2; int hk = cell.z + hex_neighbor_offset[h][2]; if( hi >= 0 && hi < myHeight && hj >= 0 && hj < myWidth && hk >=0 && hk < myDepth ) cell.hex[h] = hk * myWidth * myHeight + hi * myWidth + hj; else cell.hex[h] = -1; } // the hexagon pixel offsets from the upper left corner // // x 1-2 o // / \ // 3-4-5-6 // \ / // o 7-8 o // static const int hex_pixel_offset[8][2] = { {1, 0}, {2, 0}, {0, 1}, {1, 1}, {2, 1}, {3, 1}, {1, 2}, {2, 2}}; math::vector3d vertex = cell.get_vertex(); #ifndef USE_COLOR_MAP cell.density = 0.f; #else cell.color.RGBA = 0; #endif // compute average density int k = 0; for(size_t h=0;h<8;++h) { math::vector3d pixel; int xx = (int)vertex.x + hex_pixel_offset[h][0]; int yy = (int)vertex.y + hex_pixel_offset[h][1]; int zz = (int)vertex.z; if( xx >= 0 && yy >= 0 && zz >= 0 && xx < v.get_width() && yy < v.get_height() && zz < v.get_depth() ) { #ifndef USE_COLOR_MAP float vx = v.get_voxel(xx, yy, zz); cell.density = (cell.density * k + vx) * (1.f/(++k)); #else r8g8b8a8 vx = v.get_voxel_color(xx, yy, zz); cell.color.A = (cell.color.A * k + vx.A) / ++k; cell.color.R = (cell.color.R * k + vx.R) / ++k; cell.color.G = (cell.color.G * k + vx.G) / ++k; cell.color.B = (cell.color.B * k + vx.B) / ++k; #endif } } myLatticeCells.push_back(cell); } } } }
void reflect_z(volume &dst) const { dst = *this; dst.reflect_z(); }
/* default: simple numerical integration of surfaces/cubes, relative tolerance 'tol'. This is superseded by the routines in the libctl interface, which either use a semi-analytical average or can use a proper adaptive cubature. */ void material_function::eff_chi1inv_row(component c, double chi1inv_row[3], const volume &v, double tol, int maxeval) { field_type ft = type(c); if (!maxeval) { trivial: chi1inv_row[0] = chi1inv_row[1] = chi1inv_row[2] = 0.0; chi1inv_row[component_direction(c) % 3] = 1/chi1p1(ft,v.center()); return; } vec gradient(normal_vector(ft, v)); if (abs(gradient) < 1e-8) goto trivial; double meps=1, minveps=1; vec d = v.get_max_corner() - v.get_min_corner(); int ms = 10; double old_meps=0, old_minveps=0; int iter = 0; switch(v.dim) { case D3: while ((fabs(meps - old_meps) > tol*fabs(old_meps)) && (fabs(minveps - old_minveps) > tol*fabs(old_minveps))) { old_meps=meps; old_minveps=minveps; meps = minveps = 0; for (int k=0; k < ms; k++) for (int j=0; j < ms; j++) for (int i=0; i < ms; i++) { double ep = chi1p1(ft,v.get_min_corner() + vec(i*d.x()/ms, j*d.y()/ms, k*d.z()/ms)); if (ep < 0) goto trivial; meps += ep; minveps += 1/ep; } meps /= ms*ms*ms; minveps /= ms*ms*ms; ms *= 2; if (maxeval && (iter += ms*ms*ms) >= maxeval) goto done; } break; case D2: while ((fabs(meps-old_meps) > tol*old_meps) && (fabs(minveps-old_minveps) > tol*old_minveps)) { old_meps=meps; old_minveps=minveps; meps = minveps = 0; for (int j=0; j < ms; j++) for (int i=0; i < ms; i++) { double ep = chi1p1(ft,v.get_min_corner() + vec(i*d.x()/ms, j*d.y()/ms)); if (ep < 0) goto trivial; meps += ep; minveps += 1/ep; } meps /= ms*ms; minveps /= ms*ms; ms *= 2; if (maxeval && (iter += ms*ms) >= maxeval) goto done; } break; case Dcyl: while ((fabs(meps-old_meps) > tol*old_meps) && (fabs(minveps-old_minveps) > tol*old_minveps)) { old_meps=meps; old_minveps=minveps; meps = minveps = 0; double sumvol = 0; for (int j=0; j < ms; j++) for (int i=0; i < ms; i++) { double r = v.get_min_corner().r() + i*d.r()/ms; double ep = chi1p1(ft,v.get_min_corner() + veccyl(i*d.r()/ms, j*d.z()/ms)); if (ep < 0) goto trivial; sumvol += r; meps += ep * r; minveps += r/ep; } meps /= sumvol; minveps /= sumvol; ms *= 2; if (maxeval && (iter += ms*ms) >= maxeval) goto done; } break; case D1: while ((fabs(meps-old_meps) > tol*old_meps) && (fabs(minveps-old_minveps) > tol*old_minveps)) { old_meps=meps; old_minveps=minveps; meps = minveps = 0; for (int i=0; i < ms; i++) { double ep = chi1p1(ft,v.get_min_corner() + vec(i*d.z()/ms)); if (ep < 0) { meps = chi1p1(ft,v.center()); minveps = 1/meps; goto done; } meps += ep; minveps += 1/ep; } meps /= ms; minveps /= ms; ms *= 2; if (maxeval && (iter += ms*ms) >= maxeval) goto done; } break; } done: { double n[3] = {0,0,0}; double nabsinv = 1.0/abs(gradient); LOOP_OVER_DIRECTIONS(gradient.dim, k) n[k%3] = gradient.in_direction(k) * nabsinv; /* get rownum'th row of effective tensor P * minveps + (I-P) * 1/meps = P * (minveps-1/meps) + I * 1/meps where I is the identity and P is the projection matrix P_{ij} = n[i] * n[j]. */ int rownum = component_direction(c) % 3; for (int i=0; i<3; ++i) chi1inv_row[i] = n[rownum] * n[i] * (minveps - 1/meps); chi1inv_row[rownum] += 1/meps; } }