//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; }
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 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); }
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++); } } } }
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; }
//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); }
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); }
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; }