Exemple #1
0
void TubeDetection::allocateEigenvectorImage()
{
    FloatImageType::IndexType start;
    FloatImageType::SizeType size;
    FloatImageType::RegionType region;

    start[0] = 0;
    start[1] = 0;
    start[2] = 0;

    size[0] = imagePyramid.back()->GetLargestPossibleRegion().GetSize(0);
    size[1] = imagePyramid.back()->GetLargestPossibleRegion().GetSize(1);
    size[2] = imagePyramid.back()->GetLargestPossibleRegion().GetSize(2);

    eigenvector[0] = FloatImageType::New();
    eigenvector[1] = FloatImageType::New();
    eigenvector[2] = FloatImageType::New();


    region.SetSize(size);
    region.SetIndex(start);



    eigenvector[0]->SetRegions(region);
    eigenvector[1]->SetRegions(region);
    eigenvector[2]->SetRegions(region);


    eigenvector[0]->Allocate();
    eigenvector[1]->Allocate();
    eigenvector[2]->Allocate();
}
Exemple #2
0
void Focus::MakeVarianceImage()
{

	UCharImageType::Pointer img;
	if(imgIn)
		img = imgIn;
	else
	{
		typedef itk::RGBToLuminanceImageFilter< RGBImageType, UCharImageType > ConvertFilterType;
		ConvertFilterType::Pointer convert = ConvertFilterType::New();
		convert->SetInput( imgInColor );
		convert->Update();
		img = convert->GetOutput();
	}

	typedef itk::VarianceImageFunction< UCharImageType2D > VarianceFunctionType;
	typedef itk::ExtractImageFilter< UCharImageType, UShortImageType2D > ExtractFilterType;

	std::cout << "Making Variance Image";

	int size1 = (int)img->GetLargestPossibleRegion().GetSize()[0];
	int size2 = (int)img->GetLargestPossibleRegion().GetSize()[1];
	int size3 = (int)img->GetLargestPossibleRegion().GetSize()[2];

	varImg = FloatImageType::New();

	FloatImageType::PointType origin;
	origin[0] = 0;
	origin[1] = 0;
	origin[2] = 0;
	varImg->SetOrigin( origin );

	FloatImageType::IndexType start = {{ 0,0,0 }};
	FloatImageType::SizeType  size = {{ size1, size2, size3 }};
	FloatImageType::RegionType region;
	region.SetSize( size );
	region.SetIndex( start );

	varImg->SetRegions( region ); 
	varImg->Allocate();

	for(int z = 0; z < size3; ++z)
	{
		std::cout << ".";
		UCharImageType::IndexType index = { {0,0,z} };
		UCharImageType::SizeType size = { {size1, size2, 0} };
		UCharImageType::RegionType region;
		region.SetSize(size);
		region.SetIndex(index);

		ExtractFilterType::Pointer extract = ExtractFilterType::New();
		extract->SetInput( img );
		extract->SetExtractionRegion( region );
		extract->Update();

		UShortImageType2D::Pointer im2 = extract->GetOutput();

		typedef itk::MeanImageFilter<UShortImageType2D,UShortImageType2D> MeanFilterType;
		typedef itk::SquareImageFilter<UShortImageType2D,UShortImageType2D> SquareFilterType;
		typedef itk::SubtractImageFilter<UShortImageType2D,UShortImageType2D> SubtractFilterType;

		UShortImageType2D::SizeType radiussize = {{radius, radius}};
		MeanFilterType::Pointer mean1 = MeanFilterType::New();
		mean1->SetInput(im2);
		mean1->SetRadius(radiussize);

		SquareFilterType::Pointer sq1 = SquareFilterType::New();
		sq1->SetInput(mean1->GetOutput());

		SquareFilterType::Pointer sq2 = SquareFilterType::New();
		sq2->SetInput(im2);

		MeanFilterType::Pointer mean2 = MeanFilterType::New();
		mean2->SetInput(sq2->GetOutput());
		mean2->SetRadius(radiussize);

		SubtractFilterType::Pointer sb1 = SubtractFilterType::New();
		sb1->SetInput1(mean2->GetOutput());
		sb1->SetInput2(sq1->GetOutput());

		sb1->Update();

		typedef itk::ImageRegionIterator<FloatImageType> FloatIteratorType;
		typedef itk::ImageRegionIterator<UShortImageType2D> UShortIteratorType;

		FloatIteratorType fit(varImg,region);
		UShortIteratorType uit(sb1->GetOutput(),sb1->GetOutput()->GetLargestPossibleRegion());
		for(fit.GoToBegin(),uit.GoToBegin();!uit.IsAtEnd(); ++fit, ++uit)
		{
			//printf("%d ", int(uit.Get()));
			fit.Set(uit.Get());
		}


		/* // DONT USE THIS BECAUSE IT IS VERY SLOW
		VarianceFunctionType::Pointer varFunction = VarianceFunctionType::New();
		varFunction->SetInputImage( im2 );
		varFunction->SetNeighborhoodRadius( radius );

		for(int x=0; x<size1; ++x)
		{
		for(int y=0; y<size2; ++y)
		{
		UCharImageType2D::IndexType ind;
		ind[0] = x;
		ind[1] = y;
		float var = (float)varFunction->EvaluateAtIndex( ind );

		FloatImageType::IndexType ind3;
		ind3[0] = x;
		ind3[1] = y;
		ind3[2] = z;
		varImg->SetPixel(ind3, var);
		}
		}
		*/

	}

	typedef itk::ImageFileWriter<FloatImageType> FloatWriter;
	FloatWriter::Pointer fwriter = FloatWriter::New();
	fwriter->SetInput(varImg);
	fwriter->SetFileName("test_fwriter.mhd");
	fwriter->Update();
	/*
	//Rescale:
	typedef itk::RescaleIntensityImageFilter< FloatImageType, UCharImageType > RescaleType;
	RescaleType::Pointer rescale = RescaleType::New();
	rescale->SetOutputMaximum( 255 );
	rescale->SetOutputMinimum( 0 );
	rescale->SetInput( varImg );
	rescale->Update();
	*/
	std::cout << "done\n";
}
std::vector<float> compute_ec_features( USImageType::Pointer input_image,  USImageType::Pointer inp_labeled, int number_of_rois, unsigned short thresh, int surr_dist, int inside_dist ){

	std::vector< float > qfied_num;
	std::vector< USImageType::PixelType > labelsList;
	std::vector< double > quantified_numbers_cell;

	typedef itk::ExtractImageFilter< USImageType, UShortImageType > LabelExtractType;
	typedef itk::ImageRegionConstIterator< UShortImageType > ConstIteratorType;
	typedef itk::ImageRegionIteratorWithIndex< USImageType > IteratorType;
	typedef itk::SignedDanielssonDistanceMapImageFilter<FloatImageType, FloatImageType > DTFilter;
	typedef itk::ImageRegionIteratorWithIndex< FloatImageType > IteratorTypeFloat;
	typedef itk::LabelGeometryImageFilter< USImageType > GeometryFilterType;
	typedef GeometryFilterType::LabelIndicesType labelindicestype;

	itk::SizeValueType sz_x, sz_y, sz_z;
	sz_x = input_image->GetLargestPossibleRegion().GetSize()[0];
	sz_y = input_image->GetLargestPossibleRegion().GetSize()[1];
	sz_z = input_image->GetLargestPossibleRegion().GetSize()[2];

	if( sz_x==1 || sz_y==1 || sz_z==1 ){
		LabelExtractType::Pointer deFilter = LabelExtractType::New();
		USImageType::RegionType dRegion = inp_labeled->GetLargestPossibleRegion();
		dRegion.SetSize(2,0);
		deFilter->SetExtractionRegion(dRegion);
		deFilter->SetInput( inp_labeled );
		deFilter->SetDirectionCollapseToIdentity();
		try{
			deFilter->Update();
		}
		catch( itk::ExceptionObject & excep ){
			std::cerr << "Exception caught !" << std::endl;
			std::cerr << excep << std::endl;
		}
		//Dialate input first
		WholeCellSeg *dialate_filter = new WholeCellSeg;
		dialate_filter->set_nuc_img( deFilter->GetOutput() );
		dialate_filter->set_radius( surr_dist );
		dialate_filter->RunSegmentation();
		UShortImageType::Pointer input_lab = dialate_filter->getSegPointer();

		USImageType::Pointer input_labeled = USImageType::New();
		USImageType::PointType origint;
		origint[0] = 0;
		origint[1] = 0;
		origint[2] = 0;
		input_labeled->SetOrigin( origint );
		USImageType::IndexType startt;
		startt[0] = 0;  // first index on X
		startt[1] = 0;  // first index on Y
		startt[2] = 0;  // first index on Z
		USImageType::SizeType  sizet;
		sizet[0] = inp_labeled->GetLargestPossibleRegion().GetSize()[0];  // size along X
		sizet[1] = inp_labeled->GetLargestPossibleRegion().GetSize()[1];  // size along Y
		sizet[2] = inp_labeled->GetLargestPossibleRegion().GetSize()[2];  // size along Z
		USImageType::RegionType regiont;
		regiont.SetSize( sizet );
		regiont.SetIndex( startt );
		input_labeled->SetRegions( regiont );
		input_labeled->Allocate();
		input_labeled->FillBuffer(0);
		input_labeled->Update();

		ConstIteratorType pix_buf1( input_lab, input_lab->GetRequestedRegion() );
		IteratorType iterator2 ( input_labeled, input_labeled->GetRequestedRegion() );
		iterator2.GoToBegin();
		for ( pix_buf1.GoToBegin(); !pix_buf1.IsAtEnd(); ++pix_buf1 ){
			iterator2.Set( pix_buf1.Get() );
			++iterator2;
		}

		std::vector< float > quantified_numbers;

		typedef itk::LabelGeometryImageFilter< USImageType > GeometryFilterType;
		typedef GeometryFilterType::LabelIndicesType labelindicestype;

		GeometryFilterType::Pointer geomfilt1 = GeometryFilterType::New();

		geomfilt1->SetInput( input_labeled );
		geomfilt1->SetCalculatePixelIndices( true );
		geomfilt1->Update();
		labelsList = geomfilt1->GetLabels();

		bool zp=false;
		for( USImageType::PixelType i=0; i < labelsList.size(); ++i ){
			if( labelsList[i] == 0 ){ zp=true; continue; }
			std::vector<float> quantified_numbers_cell;
			for( unsigned j=0; j<number_of_rois; ++j ) quantified_numbers_cell.push_back((float)0.0);
			double centroid_x = geomfilt1->GetCentroid(labelsList[i])[0];
			double centroid_y = geomfilt1->GetCentroid(labelsList[i])[1];
			labelindicestype indices1;
			indices1 = geomfilt1->GetPixelIndices(labelsList[i]);
			for( labelindicestype::iterator itPixind = indices1.begin(); itPixind!=indices1.end(); ++itPixind ){
				IteratorType iterator1 ( input_image, input_image->GetRequestedRegion() );
				iterator1.SetIndex( *itPixind );
				if( iterator1.Get() < thresh )
					continue;
				double x = iterator1.GetIndex()[0];
				double y = iterator1.GetIndex()[1];
				double angle = atan2((centroid_y-y),fabs(centroid_x-x));
				if( (centroid_x-x)>0 )
					angle += M_PI_2;
				else
					angle = M_PI+M_PI-(angle+M_PI_2);
				angle = ((number_of_rois-1)*angle)/(2*M_PI);
				double angle_fraction[1];
				unsigned angular_index;
				if( modf( angle, angle_fraction ) > 0.5 )
					angular_index = ceil( angle );
				else
					angular_index = floor( angle );
				
				quantified_numbers_cell[angular_index] += iterator1.Get();
			}
			for( unsigned j=0; j<number_of_rois; ++j ) quantified_numbers.push_back(quantified_numbers_cell[j]);
		}
		unsigned qnum_sz = zp? (labelsList.size()-1) : (labelsList.size());
		for( unsigned i=0; i<qnum_sz; ++i ){
			unsigned counter=0;
			for( unsigned j=0; j<number_of_rois; ++j ){
				if( quantified_numbers[(i*number_of_rois+j)] > (255.0*surr_dist) )
					++counter;
			}
			qfied_num.push_back(counter);
		}
	}
	else{
		GeometryFilterType::Pointer geomfilt1 = GeometryFilterType::New();
		geomfilt1->SetInput( inp_labeled );
		geomfilt1->SetCalculatePixelIndices( true );
		geomfilt1->Update();
		labelsList = geomfilt1->GetLabels();
		std::cout<<std::endl<<"The size is: "<<labelsList.size();
		if( labelsList.size() == 1 )
		{
			qfied_num.clear();
			return qfied_num;
		}
		bool zp=false; USPixelType zero;
		//Check if the background is also included
		for( USPixelType i=0; i<labelsList.size(); ++i ) if( labelsList[i] == 0 ){ zp=true; zero = i; }

		USImageType::SizeType  sizee;
		sizee[0] = inp_labeled->GetLargestPossibleRegion().GetSize()[0];  // size along X
		sizee[1] = inp_labeled->GetLargestPossibleRegion().GetSize()[1];  // size along Y
		sizee[2] = inp_labeled->GetLargestPossibleRegion().GetSize()[2];  // size along Z

		itk::SizeValueType roi_list_size = zp ?
					((itk::SizeValueType)number_of_rois*(labelsList.size()-1)*2) : 
					((itk::SizeValueType)number_of_rois*labelsList.size()*2);
		std::vector<double> quantified_numbers_cell((roi_list_size),0.0
			);
		std::cout<<"Bounding boxes computed"<<std::endl;

#ifdef _OPENMP
itk::MultiThreader::SetGlobalDefaultNumberOfThreads(1);
#pragma omp parallel for
#if _OPENMP < 200805L
		for( int i=0; i<labelsList.size(); ++i )
#else
		for( USImageType::PixelType i=0; i<labelsList.size(); ++i )
#endif
#else
		for( USImageType::PixelType i=0; i<labelsList.size(); ++i )
#endif
		{
			itk::SizeValueType ind;
			if( zp && (zero==i) ) continue;
			if( zp && (i>zero)  ) ind = i-1;
			else ind = i;
			//Get label indices
			labelindicestype indices1;
			double centroid_x,centroid_y,centroid_z;
			GeometryFilterType::BoundingBoxType boundbox;
			#pragma omp critical
			{
				indices1 = geomfilt1->GetPixelIndices(labelsList[i]);
				//Get Centroid
				centroid_x = geomfilt1->GetCentroid(labelsList[i])[0];
				centroid_y = geomfilt1->GetCentroid(labelsList[i])[1];
				centroid_z = geomfilt1->GetCentroid(labelsList[i])[2];
				//Create an image with bounding box + 2 * outside distance + 2
				//and get distance map for the label
				boundbox = geomfilt1->GetBoundingBox(labelsList[i]);
			}
			//Create vnl array 3xN( label indicies )
			vnl_matrix<double> B(3,indices1.size());

			FloatImageType::Pointer inp_lab = FloatImageType::New();
			FloatImageType::PointType origint; origint[0] = 0; origint[1] = 0; origint[2] = 0;
			inp_lab->SetOrigin( origint );
			FloatImageType::IndexType startt;
			startt[0] = 0;  // first index on X
			startt[1] = 0;  // first index on Y
			startt[2] = 0;  // first index on Z
			FloatImageType::SizeType  sizet;
			sizet[0] = boundbox[1]-boundbox[0]+2*surr_dist+2;  // size along X
			sizet[1] = boundbox[3]-boundbox[2]+2*surr_dist+2;  // size along Y
			sizet[2] = boundbox[5]-boundbox[4]+2*surr_dist+2;  // size along Z
			FloatImageType::RegionType regiont;
			regiont.SetSize( sizet );
			regiont.SetIndex( startt );
			inp_lab->SetRegions( regiont );
			inp_lab->Allocate();
			inp_lab->FillBuffer(0.0);
			inp_lab->Update();
			IteratorTypeFloat iterator444 ( inp_lab, inp_lab->GetRequestedRegion() );

			//Populate matrix with deviations from the centroid for principal axes and
			//at the same time set up distance-transform computation
			itk::SizeValueType ind1=0;
			for( labelindicestype::iterator itPixind = indices1.begin(); itPixind!=indices1.end(); ++itPixind ){
				IteratorType iterator3( input_image, input_image->GetRequestedRegion() );
				iterator3.SetIndex( *itPixind );
				B(0,(ind1)) = iterator3.GetIndex()[0]-centroid_x;
				B(1,(ind1)) = iterator3.GetIndex()[1]-centroid_y;
				B(2,(ind1)) = iterator3.GetIndex()[2]-centroid_z;
				FloatImageType::IndexType cur_in;
				cur_in[0] = iterator3.GetIndex()[0]-boundbox[0]+1+surr_dist;
				cur_in[1] = iterator3.GetIndex()[1]-boundbox[2]+1+surr_dist;
				cur_in[2] = iterator3.GetIndex()[2]-boundbox[4]+1+surr_dist;
				iterator444.SetIndex( cur_in );
				iterator444.Set( 255.0 );
				++ind1;
			}

			//Compute distance transform for the current object
			DTFilter::Pointer dt_obj= DTFilter::New() ;
			dt_obj->SetInput( inp_lab );
			dt_obj->SquaredDistanceOff();
			dt_obj->InsideIsPositiveOff();
			try{
				dt_obj->Update() ;
			} catch( itk::ExceptionObject & err ){
				std::cerr << "Error in Distance Transform: " << err << std::endl;
			}
			FloatImageType::Pointer dist_im = dt_obj->GetOutput();

			//Use KLT to compute pricipal axes
			vnl_matrix<double> B_transp((int)indices1.size(),3);
			B_transp = B.transpose();
			vnl_matrix<double>  COV(3,3);
			COV = B * B_transp;
			double norm = 1.0/(double)indices1.size();
			COV = COV * norm;
			//Eigen decomposition
			vnl_real_eigensystem Eyegun( COV );
			vnl_matrix<vcl_complex<double> > EVals = Eyegun.D;
			double Eval1 = vnl_real(EVals)(0,0); double Eval2 = vnl_real(EVals)(1,1); double Eval3 = vnl_real(EVals)(2,2);
			vnl_double_3x3 EVectMat = Eyegun.Vreal;
			double V1[3],V2[3],EP_norm[3];
			if( Eval1 >= Eval3 && Eval2 >= Eval3 ){
				if( Eval1 >= Eval2 ){
					V1[0] = EVectMat(0,0); V1[1] = EVectMat(1,0); V1[2] = EVectMat(2,0);
					V2[0] = EVectMat(0,1); V2[1] = EVectMat(1,1); V2[2] = EVectMat(2,1);
				} else {
					V2[0] = EVectMat(0,0); V2[1] = EVectMat(1,0); V2[2] = EVectMat(2,0);
					V1[0] = EVectMat(0,1); V1[1] = EVectMat(1,1); V1[2] = EVectMat(2,1);
				}
			} else if( Eval1 >= Eval2 && Eval3 >= Eval2 ) {
				if( Eval1 >= Eval3 ){
					V1[0] = EVectMat(0,0); V1[1] = EVectMat(1,0); V1[2] = EVectMat(2,0);
					V2[0] = EVectMat(0,2); V2[1] = EVectMat(1,2); V2[2] = EVectMat(2,2);
				} else {
					V2[0] = EVectMat(0,0); V2[1] = EVectMat(1,0); V2[2] = EVectMat(2,0);
					V1[0] = EVectMat(0,2); V1[1] = EVectMat(1,2); V1[2] = EVectMat(2,2);
				}
			} else {
				if( Eval2 >= Eval3 ){
					V1[0] = EVectMat(0,1); V1[1] = EVectMat(1,1); V1[2] = EVectMat(2,1);
					V2[0] = EVectMat(0,2); V2[1] = EVectMat(1,2); V2[2] = EVectMat(2,2);
				} else {
					V2[0] = EVectMat(0,1); V2[1] = EVectMat(1,1); V2[2] = EVectMat(2,1);
					V1[0] = EVectMat(0,2); V1[1] = EVectMat(1,2); V1[2] = EVectMat(2,2);
				}
			}
			double n_sum = sqrt( V1[0]*V1[0]+V1[1]*V1[1]+V1[2]*V1[2] );
			V1[0] /= n_sum; V1[1] /= n_sum; V1[2] /= n_sum;
			n_sum = sqrt( V2[0]*V2[0]+V2[1]*V2[1]+V2[2]*V2[2] );
			V2[0] /= n_sum; V2[1] /= n_sum; V2[2] /= n_sum;
			//Get the normal to the plane formed by the biggest two EVs
			EP_norm[0] = V1[1]*V2[2]-V1[2]*V2[1];
			EP_norm[1] = V1[2]*V2[0]-V1[0]*V2[2];
			EP_norm[2] = V1[0]*V2[1]-V1[1]*V2[0];
			//Reassign V2 so that it is orthogonal to both EP_norm and V1
			V2[0] = V1[1]*EP_norm[2]-V1[2]*EP_norm[1];
			V2[1] = V1[2]*EP_norm[0]-V1[0]*EP_norm[2];
			V2[2] = V1[0]*EP_norm[1]-V1[1]*EP_norm[0];
			//Now we have the point normal form; EP_norm is the normal and
			//centroid_x, centroid_y, centroid_z is the point
			//The equation to the plane is EP_norm[0](x-centroid_x)+EP_norm[1](y-centroid_y)+EP_norm[2](z-centroid_z)=0
			double dee = (centroid_x*EP_norm[0]+centroid_y*EP_norm[1]+centroid_z*EP_norm[2])*(-1.00);

			//Iterate through and assign values to each region
			typedef itk::ImageRegionConstIterator< FloatImageType > ConstIteratorTypeFloat;
			ConstIteratorTypeFloat pix_buf2( dist_im, dist_im->GetRequestedRegion() );
			IteratorType iterator44( input_image, input_image->GetRequestedRegion() );

			for ( pix_buf2.GoToBegin(); !pix_buf2.IsAtEnd(); ++pix_buf2 ){
				//Use pixels that are only within the defined radius from the nucleus
				double current_distance = pix_buf2.Get();
				if( (current_distance <= (double)surr_dist) && (current_distance>=(-1*inside_dist)) ){
					USImageType::IndexType cur_in;//,cur_in_cpy;
					double n_vec[3];
					cur_in[0] = pix_buf2.GetIndex()[0]+boundbox[0]-1-surr_dist;
					cur_in[1] = pix_buf2.GetIndex()[1]+boundbox[2]-1-surr_dist;
					cur_in[2] = pix_buf2.GetIndex()[2]+boundbox[4]-1-surr_dist;
					//cur_in_cpy[0] = cur_in[0]; cur_in_cpy[1] = cur_in[1]; cur_in_cpy[2] = cur_in[2];
					if( cur_in[0] < 0 || cur_in[1] < 0 || cur_in[2] < 0 ) continue;
					if( cur_in[0] >= sizee[0] || cur_in[1] >= sizee[1] || cur_in[2] >= sizee[2] ) continue;
					iterator44.SetIndex( cur_in );
					USImageType::PixelType pixel_intensity;
					pixel_intensity = iterator44.Get();
					if( pixel_intensity < thresh ) continue;

					//The projection of the point on the plane formed by the fist two major axes
					double xxx, yyy, zzz;
					xxx = cur_in[0] - EP_norm[0]*((EP_norm[0]*cur_in[0]+EP_norm[1]*cur_in[1]+EP_norm[2]*cur_in[2]+dee)
									/(EP_norm[0]*EP_norm[0]+EP_norm[1]*EP_norm[1]+EP_norm[2]*EP_norm[2]));
					yyy = cur_in[1] - EP_norm[1]*((EP_norm[0]*cur_in[0]+EP_norm[1]*cur_in[1]+EP_norm[2]*cur_in[2]+dee)
									/(EP_norm[0]*EP_norm[0]+EP_norm[1]*EP_norm[1]+EP_norm[2]*EP_norm[2]));
					zzz = cur_in[2] - EP_norm[2]*((EP_norm[0]*cur_in[0]+EP_norm[1]*cur_in[1]+EP_norm[2]*cur_in[2]+dee)
									/(EP_norm[0]*EP_norm[0]+EP_norm[1]*EP_norm[1]+EP_norm[2]*EP_norm[2]));
					//The vector from the centroid to the projected point
					n_vec[0] = centroid_x-xxx;
					n_vec[1] = centroid_y-yyy;
					n_vec[2] = centroid_z-zzz;
					n_sum = sqrt( n_vec[0]*n_vec[0] + n_vec[1]*n_vec[1] + n_vec[2]*n_vec[2] );
					n_vec[0] /= n_sum; n_vec[1] /= n_sum; n_vec[2] /= n_sum;
					//n_vec is the normalized vect in the direction of the projected point
					//V1 is the largest eigenvector
					//Get the dot and cross product between the two
					double doooot, crooos,fin_est_angle;
					doooot = n_vec[0]*V1[0]+n_vec[1]*V1[1]+n_vec[2]*V1[2];
					crooos = n_vec[0]*V2[0]+n_vec[1]*V2[1]+n_vec[2]*V2[2];

					fin_est_angle = atan2( crooos, doooot );
					USPixelType bin_num;
					//Compute bin num
					if( fin_est_angle<0 )
						fin_est_angle += (2*M_PI);
					bin_num = floor(fin_est_angle*number_of_rois/(2*M_PI));

					//Check which side of the plane the point lies on
					double v_norm = (cur_in[0]-centroid_x)*(cur_in[0]-centroid_x)
									+(cur_in[1]-centroid_y)*(cur_in[1]-centroid_y)
									+(cur_in[2]-centroid_z)*(cur_in[2]-centroid_z);
					v_norm = sqrt( v_norm );
					double doot   = (cur_in[0]-centroid_x)*EP_norm[0]/v_norm + (cur_in[1]-centroid_y)*EP_norm[1]/v_norm + (cur_in[2]-centroid_z)*EP_norm[2]/v_norm;

					if( doot<0 )
						bin_num += number_of_rois;
					quantified_numbers_cell.at((ind*(2*number_of_rois)+bin_num)) += pixel_intensity;
				}
			}
		}
		number_of_rois = number_of_rois*2;
		if( labelsList.size() == 1 )
		{
			qfied_num.clear();
			return qfied_num;
		}
		std::vector<double> quantified_numbers_cell_cpy(roi_list_size);
		std::copy(quantified_numbers_cell.begin(), quantified_numbers_cell.end(), quantified_numbers_cell_cpy.begin() );
		//Run k-means
		//Most of the code is adapted from mul/mbl/mbl_k_means.cxx
		std::sort(quantified_numbers_cell.begin(), quantified_numbers_cell.end());
	
		bool skipKmeans;
		double Positive_thresh;
		if( quantified_numbers_cell.at(0) == quantified_numbers_cell.at(quantified_numbers_cell.size()-1) )
			skipKmeans = true;

		if( !skipKmeans ){
			std::cout<<"Starting k-means\n";
			std::cout<<"First:"<<quantified_numbers_cell.at(0)<<" Last:"<<quantified_numbers_cell.at(quantified_numbers_cell.size()-1)<<std::endl;
			unsigned k = 2;
			//Vectors and matrices for k-means
			std::vector< USImageType::PixelType > partition( roi_list_size, 0 );
			std::vector< double > sums   ( k, 0.0 );
			std::vector< double > centers( k, 0.0 );
			std::vector< USImageType::PixelType > nNearest( k, 0 );

			//Use the elements that are evenly spaced to get the intial centers
			for( unsigned i=0; i<k; ++i ){
				double index = ((double)(i)*roi_list_size)/(k+1);
				centers.at(i) = quantified_numbers_cell.at((itk::SizeValueType)index);
				bool duplicated;
				std::cout<<"Initializing centers\n"<<std::flush;
				if(i){
					if( centers.at((i-1)) == centers.at(i) ){
						duplicated = true;
						itk::SizeValueType ind=i+1;
						while( centers.at((i-1))==quantified_numbers_cell.at(ind) )
							++ind;
						centers.at(i) = quantified_numbers_cell.at(ind);
						sums.at(i)    = quantified_numbers_cell.at(ind);
					}
				}
				if(!duplicated)
					sums.at(i) = quantified_numbers_cell.at((i+1)/(k+1));
				++nNearest[i];
			}

			bool changed = true;
			std::cout<<"Waiting for kmeans to converge\n"<<std::flush;
			while(changed){
				changed = false;
				for(itk::SizeValueType i=0; i<roi_list_size; ++i){
					unsigned bestCentre = 0;
					double bestDist = fabs((centers.at(0)-quantified_numbers_cell.at(i)));
					for(unsigned j=1; j<k; ++j){
						double dist = fabs((centers.at(j)-quantified_numbers_cell.at(i)));
						if( dist < bestDist ){
							bestDist = dist; bestCentre = j;
						}
					}
					sums[bestCentre] += quantified_numbers_cell.at(i);
					++ nNearest[bestCentre];
					if( bestCentre != partition.at(i) ){
						changed = true;
						partition.at(i) = bestCentre;
					}
				}
				for( unsigned j=0; j<k; ++j) centers.at(j)  = sums.at(j)/nNearest.at(j);
				for( unsigned j=0; j<k; ++j) sums.at(j)     = 0;
				for( unsigned j=0; j<k; ++j) nNearest.at(j) = 0;
			}
			for( unsigned i=0; i<k; ++i )
				std::cout<<"Center "<<i<<" "<<centers.at(i)<<"\n";

			Positive_thresh = ((centers.at(0)+centers.at(1))/2) < (255.0*thresh)?
						 ((centers.at(0)+centers.at(1))/2) : (255.0*thresh); //Arbitrary upper thresh
		}
		else
			Positive_thresh = 255.0*thresh;

		std::cout<<"Positive_thresh "<<Positive_thresh<<"\n";

		std::cout<<"Done k-means\n";
		itk::SizeValueType ind = 0;
		for( USPixelType i=0; i<labelsList.size(); ++i ){
			if( zp && (zero==i) ) continue;
			int num_positive_rois = 0;
			for( unsigned j=0; j<number_of_rois; ++j ){
				itk::SizeValueType index_of_roi = ind*number_of_rois+j;
				if( quantified_numbers_cell_cpy.at(index_of_roi)>Positive_thresh )
					++num_positive_rois;
			}
			qfied_num.push_back(num_positive_rois);
			++ind;
		}
	}
	std::cout<<"Done surroundedness\n"<<std::flush;
	return qfied_num;
}