#include <processor.h>
Inheritance diagram for EMAN::KmeansSegmentProcessor:


Public Member Functions | |
| string | get_name () const |
| Get the processor's name. | |
| virtual EMData * | process (const EMData *const image) |
| To proccess an image out-of-place. | |
| void | process_inplace (EMData *image) |
| To process an image in-place. | |
| TypeDict | get_param_types () const |
| Get processor parameter information in a dictionary. | |
| string | get_desc () const |
| Get the descrition of this specific processor. | |
Static Public Member Functions | |
| Processor * | NEW () |
Static Public Attributes | |
| const string | NAME = "segment.kmeans" |
| ctf[in] | A Ctf object to use |
Definition at line 720 of file processor.h.
|
|
Get the descrition of this specific processor. This function must be overwritten by a subclass.
Implements EMAN::Processor. Definition at line 750 of file processor.h. 00751 {
00752 return "Performs K-means segmentation on a volume. Note that this method uses random seeds, and thus will return different results each time it is run. Returned map contains number of segment for each voxel (or 0 for unsegmented voxels). Segmentation centers are stored in 'segmentcenters' attribute, consisting of a list of 3n floats in x,y,z triples.";
00753 }
|
|
|
Get the processor's name. Each processor is identified by a unique name.
Implements EMAN::Processor. Definition at line 723 of file processor.h. 00724 {
00725 return NAME;
00726 }
|
|
|
Get processor parameter information in a dictionary. Each parameter has one record in the dictionary. Each record contains its name, data-type, and description.
Reimplemented from EMAN::Processor. Definition at line 731 of file processor.h. References EMAN::TypeDict::put(). 00732 {
00733 TypeDict d ;
00734 d.put("nseg", EMObject::INT, "Number of segments to divide the image into. default=12" );
00735 d.put("thr",EMObject::FLOAT,"Isosurface threshold value. Pixels below this will not be segmented");
00736 d.put("ampweight",EMObject::INT,"If set, will weight centers by voxel amplitude. default = 1");
00737 d.put("maxsegsize",EMObject::FLOAT,"Maximum radial distance from segment center to member voxel. Default=10000");
00738 d.put("minsegsep",EMObject::FLOAT,"Minimum segment separation. Segments too close will trigger a reseed");
00739 d.put("maxiter",EMObject::FLOAT,"Maximum number of iterations to run before stopping. Default=100");
00740 d.put("maxvoxmove",EMObject::FLOAT,"Maximum number of voxels that can move before quitting. Default=25");
00741 d.put("verbose",EMObject::INT,"Be verbose while running");
00742 return d;
00743 }
|
|
|
Definition at line 745 of file processor.h. 00746 {
00747 return new KmeansSegmentProcessor();
00748 }
|
|
|
To proccess an image out-of-place. For those processors which can only be processed out-of-place, override this function to give the right behavior.
Reimplemented from EMAN::Processor. Definition at line 938 of file processor.cpp. References EMAN::EMData::copy(), EMAN::Util::get_frand(), EMAN::EMData::get_value_at(), EMAN::EMData::get_xsize(), EMAN::EMData::get_ysize(), EMAN::EMData::get_zsize(), EMAN::Util::hypot3(), nx, ny, EMAN::EMData::set_attr(), EMAN::Dict::set_default(), EMAN::EMData::set_value_at(), x, and y. 00939 {
00940 EMData * result = image->copy();
00941
00942 int nseg = params.set_default("nseg",12);
00943 float thr = params.set_default("thr",-1.0e30f);
00944 int ampweight = params.set_default("ampweight",1);
00945 float maxsegsize = params.set_default("maxsegsize",10000.0f);
00946 float minsegsep = params.set_default("minsegsep",0.0f);
00947 int maxiter = params.set_default("maxiter",100);
00948 int maxvoxmove = params.set_default("maxvoxmove",25);
00949 int verbose = params.set_default("verbose",0);
00950
00951 vector<float> centers(nseg*3);
00952 vector<float> count(nseg);
00953 int nx=image->get_xsize();
00954 int ny=image->get_ysize();
00955 int nz=image->get_zsize();
00956 // int nxy=nx*ny;
00957
00958 // seed
00959 for (int i=0; i<nseg*3; i+=3) {
00960 centers[i]= Util::get_frand(0.0f,(float)nx);
00961 centers[i+1]=Util::get_frand(0.0f,(float)ny);
00962 centers[i+2]=Util::get_frand(0.0f,(float)nz);
00963 }
00964
00965 for (int iter=0; iter<maxiter; iter++) {
00966 // **** classify
00967 size_t pixmov=0; // count of moved pixels
00968 for (int z=0; z<nz; z++) {
00969 for (int y=0; y<ny; y++) {
00970 for (int x=0; x<nz; x++) {
00971 if (image->get_value_at(x,y,z)<thr) {
00972 result->set_value_at(x,y,z,-1.0); //below threshold -> -1 (unclassified)
00973 continue;
00974 }
00975 int bcls=-1; // best matching class
00976 float bdist=(float)(nx+ny+nz); // distance for best class
00977 for (int c=0; c<nseg; c++) {
00978 float d=Util::hypot3(x-centers[c*3],y-centers[c*3+1],z-centers[c*3+2]);
00979 if (d<bdist) { bdist=d; bcls=c; }
00980 }
00981 if ((int)result->get_value_at(x,y,z)!=bcls) pixmov++;
00982 if (bdist>maxsegsize) result->set_value_at(x,y,z,-1); // pixel is too far from any center
00983 else result->set_value_at(x,y,z,(float)bcls); // set the pixel to the class number
00984 }
00985 }
00986 }
00987
00988 // **** adjust centers
00989 for (int i=0; i<nseg*3; i++) centers[i]=0;
00990 for (int i=0; i<nseg; i++) count[i]=0;
00991
00992 // weighted sums
00993 for (int z=0; z<nz; z++) {
00994 for (int y=0; y<ny; y++) {
00995 for (int x=0; x<nz; x++) {
00996 int cls = (int)result->get_value_at(x,y,z);
00997 if (cls==-1) continue;
00998 float w=1.0;
00999 if (ampweight) w=image->get_value_at(x,y,z);
01000
01001 centers[cls*3]+=x*w;
01002 centers[cls*3+1]+=y*w;
01003 centers[cls*3+2]+=z*w;
01004 count[cls]+=w;
01005 }
01006 }
01007 }
01008
01009 // now each becomes center of mass, or gets randomly reseeded
01010 int nreseed=0;
01011 for (int c=0; c<nseg; c++) {
01012 // reseed
01013 if (count[c]==0) {
01014 nreseed++;
01015 do {
01016 centers[c*3]= Util::get_frand(0.0f,(float)nx);
01017 centers[c*3+1]=Util::get_frand(0.0f,(float)ny);
01018 centers[c*3+2]=Util::get_frand(0.0f,(float)nz);
01019 } while (image->get_value_at((int)centers[c*3],(int)centers[c*3+1],(int)centers[c*3+2])<thr); // This makes sure the new point is inside density
01020 }
01021 // center of mass
01022 else {
01023 centers[c*3]/=count[c];
01024 centers[c*3+1]/=count[c];
01025 centers[c*3+2]/=count[c];
01026 }
01027 }
01028
01029 // with minsegsep, check separation
01030 if (minsegsep>0) {
01031 for (int c1=0; c1<nseg-1; c1++) {
01032 for (int c2=c1+1; c2<nseg; c2++) {
01033 if (Util::hypot3(centers[c1*3]-centers[c2*3],centers[c1*3+1]-centers[c2*3+1],centers[c1*3+2]-centers[c2*3+2])<=minsegsep) {
01034 nreseed++;
01035 do {
01036 centers[c1*3]= Util::get_frand(0.0f,(float)nx);
01037 centers[c1*3+1]=Util::get_frand(0.0f,(float)ny);
01038 centers[c1*3+2]=Util::get_frand(0.0f,(float)nz);
01039 } while (image->get_value_at((int)centers[c1*3],(int)centers[c1*3+1],(int)centers[c1*3+2])<thr);
01040 }
01041 }
01042 }
01043 }
01044
01045
01046 if (verbose) printf("Iteration %3d: %6ld voxels moved, %3d classes reseeded\n",iter,pixmov,nreseed);
01047 if (nreseed==0 && pixmov<(size_t)maxvoxmove) break; // termination conditions met
01048 }
01049
01050 result->set_attr("segment_centers",centers);
01051
01052 return result;
01053 }
|
|
|
To process an image in-place. For those processors which can only be processed out-of-place, override this function to just print out some error message to remind user call the out-of-place version.
Implements EMAN::Processor. Definition at line 1055 of file processor.cpp. 01056 {
01057 printf("Process inplace not implemented. Please use process.\n");
01058 return;
01059 }
|
|
|
Definition at line 78 of file processor.cpp. |
1.3.9.1