Ejemplo n.º 1
0
LabelImageType::Pointer getYousefSegmented(InputImageType::Pointer im_input,std::list<Seed> &seed_list,char *filename)
{
	// copy the image into a unsigned char *
	char configfile[1024];
	strcpy(configfile,filename);

	printf("Entering YousefSeg\n");
	InputImageType::SizeType size = im_input->GetLargestPossibleRegion().GetSize();
	unsigned char * in_Image;
	in_Image = (unsigned char*) malloc( size[0]*size[1]*(size[2]+1)*sizeof(unsigned char));
	if(in_Image == NULL)
	{
		printf("Couldn't allocate memory\n");
	}

	memset(in_Image,0,size[0]*size[1]*(size[2]+1)*sizeof(unsigned char));

	ConstIteratorType pix_buf(im_input,im_input->GetLargestPossibleRegion());
	int ind = 0;
	for ( pix_buf.GoToBegin(); !pix_buf.IsAtEnd(); ++pix_buf, ++ind )
		in_Image[ind]=(pix_buf.Get());

	printf("Copied input data\n");

	yousef_nucleus_seg *NucleusSeg = new yousef_nucleus_seg();
	NucleusSeg->readParametersFromFile(configfile);
	NucleusSeg->setDataImage(in_Image,size[0],size[1],size[2]+1,"null");

	unsigned short * output_img;
	//	int *bounds_img;
	NucleusSeg->runBinarization();
	output_img = NucleusSeg->getBinImage();
	//	getITKImage(output_img);
	//	getProcessedBinaryImage(
	NucleusSeg->runSeedDetection();
	std::vector<Seed> seeds = NucleusSeg->getSeeds();
	printf("In yousef_seg Seed size = %d\n", (int)seeds.size());
	std::vector<Seed>::iterator iter = seeds.begin();
	for(;iter!=seeds.end();iter++)
	{
		seed_list.push_back(*iter);
	}
	NucleusSeg->runClustering();
	printf("Finished Clustering\n");
	if(NucleusSeg->isSegmentationFinEnabled())
	{
		NucleusSeg->runAlphaExpansion3D();		
		output_img=NucleusSeg->getSegImage();
	}
	else
	{
		output_img=NucleusSeg->getClustImage();
	}

	//	bounds_img = NucleusSeg->getBoundsImage();

	printf("Finished segmentation\n");

	LabelImageType::Pointer label = LabelImageType::New();
	label->SetRegions(im_input->GetLargestPossibleRegion());
	label->Allocate();

	LabelIteratorType liter(label,label->GetLargestPossibleRegion());
	ind = 0;
	for(liter.GoToBegin();!liter.IsAtEnd();++liter,++ind)
	{
		liter.Set(output_img[ind]);
	}
	delete NucleusSeg;
	free(in_Image);
	return label;
}
Ejemplo n.º 2
0
vtkSmartPointer<vtkPolyData> getVTKPolyDataPrecise(LabelImageType::Pointer label)
{
	LabelIteratorType liter = LabelIteratorType(label,label->GetLargestPossibleRegion());
	liter.GoToBegin();

	//find the maximum number of cells
	unsigned short max1 = 0;
	for(liter.GoToBegin();!liter.IsAtEnd();++liter)
		max1 = MAX(max1,liter.Get());

	//find all the cubes in which cells lie
	cubecoord* carray = new cubecoord[max1+1];
	for(int counter=0; counter<=max1; counter++)
	{
		carray[counter].sx=60000; carray[counter].sy=60000;carray[counter].sz=60000;
		carray[counter].ex=0;carray[counter].ey=0;carray[counter].ez=0;
	}

	typedef itk::ImageRegionConstIteratorWithIndex<LabelImageType> ConstLabelIteratorWithIndex;
	ConstLabelIteratorWithIndex cliter = ConstLabelIteratorWithIndex(label,label->GetLargestPossibleRegion());
	InputImageType::IndexType index;
	for(cliter.GoToBegin();!cliter.IsAtEnd();++cliter)
	{
		int cur = cliter.Get();
		if(cur!=0)
		{
			index = cliter.GetIndex();
			carray[cur].sx= MIN(index[0],carray[cur].sx);
			carray[cur].sy= MIN(index[1],carray[cur].sy);
			carray[cur].sz= MIN(index[2],carray[cur].sz);
			carray[cur].ex= MAX(index[0],carray[cur].ex);
			carray[cur].ey= MAX(index[1],carray[cur].ey);
			carray[cur].ez= MAX(index[2],carray[cur].ez);
		}
	}

	//find the largest image size we need
	unsigned short wx=0,wy=0,wz=0;
	for(int counter=1; counter<=max1; counter++)
	{
		wx = MAX(carray[counter].ex-carray[counter].sx+1,wx);
		wy = MAX(carray[counter].ey-carray[counter].sy+1,wy);
		wz = MAX(carray[counter].ez-carray[counter].sz+1,wz);
	}
	// accommodate padding
	wx = wx+2;wy = wy +2; wz = wz+2;
	printf("wx wy wz %u %u %u\n",wx,wy,wz);
	// create a tiny image of maximum size


	//appendfilter->UserManagedInputsOn();
	//appendfilter->SetNumberOfInputs(max1);
	vtkSmartPointer<vtkAppendPolyData> appendfilter = vtkSmartPointer<vtkAppendPolyData>::New();

/**************/
			ExportFilterType::Pointer itkexporter = ExportFilterType::New();
			
			vtkSmartPointer<vtkImageImport> vtkimporter = vtkSmartPointer<vtkImageImport>::New();
			ConnectPipelines(itkexporter,(vtkImageImport *)vtkimporter);
			vtkSmartPointer<vtkMarchingCubes> contourf = vtkSmartPointer<vtkMarchingCubes>::New();
			contourf->SetInputData(vtkimporter->GetOutput());
			contourf->SetValue(0,127);
			contourf->ComputeNormalsOff();
			contourf->ComputeScalarsOff();
			contourf->ComputeGradientsOff();
			vtkSmartPointer<vtkSmoothPolyDataFilter> smoothf = vtkSmartPointer<vtkSmoothPolyDataFilter>::New();
			smoothf->SetInputData(contourf->GetOutput());
			smoothf->SetRelaxationFactor(0.3);
			smoothf->SetNumberOfIterations(20);

			vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
			transform->PostMultiply();
	
			transform->Identity();
			vtkSmartPointer<vtkTransformPolyDataFilter> tf = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
			tf->SetTransform(transform);
			tf->SetInputData(smoothf->GetOutput());
		
/******************/



InputImageType::Pointer t = getEmpty(wx,wy,wz);
	for(int counter=1; counter<=max1; counter++)
	{

		
			
			//printf("Maximum tiny image size I need is [%d %d %d]\n",wx,wy,wz);

			if(carray[counter].sx > 59999)
				continue;
			printf("Working..\n");
	//		scanf("%*d");
			InputImageType::SizeType size;
			InputImageType::RegionType region;
			index.Fill(1);

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


			LabelImageType::SizeType lsize;
			LabelImageType::IndexType lindex;
			LabelImageType::RegionType lregion;

			itkexporter->SetInput(t);

			
			
		

			t->FillBuffer(0);
			lsize[0] = carray[counter].ex-carray[counter].sx+1;
			lsize[1] = carray[counter].ey-carray[counter].sy+1;
			lsize[2] = carray[counter].ez-carray[counter].sz+1;

			lindex[0] = carray[counter].sx;
			lindex[1] = carray[counter].sy;
			lindex[2] = carray[counter].sz;

			lregion.SetIndex(lindex);
			lregion.SetSize(lsize);
			LabelIteratorType localiter = LabelIteratorType(label,lregion);

			size = lsize;
			region.SetSize(size);
			IteratorType iter = IteratorType(t,region);
			for(localiter.GoToBegin(),iter.GoToBegin();!localiter.IsAtEnd();++localiter,++iter)
			{
				if(localiter.Get()==counter)
				{
					iter.Set(255);
				}
			}
			t->Modified();
			vtkimporter->Modified();

			transform->Identity();	
			transform->Translate(carray[counter].sx-1,carray[counter].sy-1,carray[counter].sz-1);
			tf->SetTransform(transform);
			tf->Update();
		vtkSmartPointer<vtkPolyData> pol=vtkSmartPointer<vtkPolyData>::New();
		pol->DeepCopy(tf->GetOutput());
	//	tf->GetOutput()->Print(std::cout);
		
		appendfilter->AddInputData(pol);
		//appendfilter->Update();
	
		//appendfilter->SetInputByNumber(counter-1,tf->GetOutput());
	//	appendfilter->Update();
	//	appendfilter->GetOutput()->Print(std::cout);
		//if(counter>500)
		//	break;
		printf("Completed %d/%d\r",counter,max1);
	//	scanf("%*d");
	}

	appendfilter->Update();
	vtkSmartPointer<vtkDecimatePro> decimate = vtkSmartPointer<vtkDecimatePro>::New();
	decimate->SetInputData(appendfilter->GetOutput());
	decimate->SetTargetReduction(0.1);
	//decimate->SetNumberOfDivisions(32,32,32);
	printf("Decimating the contours...");
	decimate->Update();
	printf("Done\n");
	printf("Smoothing the contours after decimation...");
	vtkSmartPointer<vtkSmoothPolyDataFilter> smoothfinal = vtkSmartPointer<vtkSmoothPolyDataFilter>::New();
	smoothfinal->SetRelaxationFactor(0.2);
	smoothfinal->SetInputData(decimate->GetOutput());
	smoothfinal->SetNumberOfIterations(0);
	smoothfinal->Update();
	printf("Done\n");
	delete [] carray;
	vtkSmartPointer<vtkPolyData> out = smoothfinal->GetOutput();
	return out;
}
Ejemplo n.º 3
0
void otb::Wrapper::Aggregate::DoExecute()
{
    // Récupération de la labelmap
    LabelImageType::Pointer labelIn = GetParameterUInt32Image("inseg");
    labelIn->SetRequestedRegionToLargestPossibleRegion();
    labelIn->Update();

    // Filtre statistique pour récupérer le nombre de label dans la labelmap
    StatisticsImageFilterType::Pointer stats = StatisticsImageFilterType::New();
    stats->SetInput(labelIn);
    stats->Update();
    unsigned int regionCount=stats->GetMaximum();

    otbAppLogINFO(<<"Number of objects: "<<regionCount);

    //Récupération de la classification et statistique pour connaître le nombre de classes
    ImageType::Pointer imageIn = GetParameterUInt32Image("in");
    stats->SetInput(imageIn);
    stats->Update();
    unsigned int nbclass=stats->GetMaximum()-stats->GetMinimum()+1;
    otbAppLogINFO(<<"Number of classes: "<<nbclass);
    unsigned int minimum =stats->GetMinimum();
    otbAppLogINFO(<<"Minimum: "<<minimum);

    // Filtre LabelImage vers LabelMap(StatisticsLabelObject)
    ConverterStatisticsType::Pointer converterStats = ConverterStatisticsType::New();
    converterStats->SetInput(labelIn);
    converterStats->SetBackgroundValue(0);
    converterStats->Update();

    // Calcul des statistiques par objet de la LabelMap
    StatisticsFilterType::Pointer statistics = StatisticsFilterType::New();
    statistics->SetInput(converterStats->GetOutput());
    statistics->SetFeatureImage(imageIn);
    statistics->SetNumberOfBins(nbclass);
    statistics->Update();

    // Définition du filtre ChangeLabel
    m_ChangeLabelFilter = ChangeLabelImageFilterType::New();
    m_ChangeLabelFilter->SetInput(labelIn);

    // Iteration sur les objets, récupération de l'histogramme, extraction de la valeur mojoritaire
    // Changement de la valeur du label par la valeur majoritaire dans la label map => obtention d'une classification corrigée

    for(unsigned int i=0; i<regionCount+1; i++)
    {
        if(statistics->GetOutput()->HasLabel(i))
        {
            const StatisticsLabelObjectType *labelObjectStats = statistics->GetOutput()->GetLabelObject(i);
            const HistogramType *histogram = labelObjectStats->GetHistogram();

            unsigned int var = 0;
            unsigned int classe = minimum;
            for(unsigned int j=0; j< nbclass; j++)
            {
                if(histogram->GetFrequency(j)>var)
                {
                    var = histogram->GetFrequency(j);
                    classe = j+minimum;
                }
            }
            m_ChangeLabelFilter->SetChange(i,classe);
        }
    }

    SetParameterOutputImage("outim", m_ChangeLabelFilter->GetOutput());

    //Vectorisation
    otbAppLogINFO(<<"Vectorization...");

    //Définition du shapefile
    const std::string shapefile = GetParameterString("out");

    otb::ogr::DataSource::Pointer ogrDS;
    otb::ogr::Layer layer(NULL, false);

    std::string projRef = imageIn->GetProjectionRef();

    OGRSpatialReference oSRS(projRef.c_str());

    otbAppLogINFO(<< projRef);

    std::vector<std::string> options;

    ogrDS = otb::ogr::DataSource::New(shapefile, otb::ogr::DataSource::Modes::Overwrite);
    std::string layername = itksys::SystemTools::GetFilenameName(shapefile.c_str());
    std::string const extension = itksys::SystemTools::GetFilenameLastExtension(shapefile.c_str());
    layername = layername.substr(0,layername.size()-(extension.size()));
    layer = ogrDS->CreateLayer(layername, &oSRS, wkbMultiPolygon, options);

    OGRFieldDefn labelField("label", OFTInteger);
    layer.CreateField(labelField, true);
    OGRFieldDefn MajorityField("Majority", OFTInteger);
    layer.CreateField(MajorityField, true);

    // Write label image
    /*
    WriterType::Pointer writer = WriterType::New();
    writer->SetInput(m_ChangeLabelFilter->GetOutput());
    writer->SetFileName("label_image.tif");
    writer->Update();
    */

    // Filtre LabelImage vers OGRDataSource
    LabelImageToOGRDataSourceFilterType::Pointer labelToOGR = LabelImageToOGRDataSourceFilterType::New();
    labelToOGR->SetInput(m_ChangeLabelFilter->GetOutput());
    labelToOGR->SetInputMask(m_ChangeLabelFilter->GetOutput());		// La classe 0  est considérée comme du background et n'est pas vectorisée
    labelToOGR->SetFieldName("Majority");
    labelToOGR->Update();

    otb::ogr::DataSource::ConstPointer ogrDSTmp = labelToOGR->GetOutput();
    otb::ogr::Layer layerTmp = ogrDSTmp->GetLayerChecked(0);

    otb::ogr::Layer::const_iterator featIt = layerTmp.begin();

    int nveau_label = 1;
    for(; featIt!=layerTmp.end(); ++featIt)
    {
        otb::ogr::Feature dstFeature(layer.GetLayerDefn());
        dstFeature.SetFrom( *featIt, TRUE );
        layer.CreateFeature( dstFeature );
        dstFeature.ogr().SetField("label",nveau_label);
        layer.SetFeature(dstFeature);
        nveau_label +=1;
    }

    otbAppLogINFO(<<"Processing complete.");
}
int main(int argc, char **argv)
{
	
	if(argc <5)
	{
		std::cout<<"Usage: mixture_segment  <MixtureLabelImageFileName> <OutputMixtureLabelImageFileName> <volume1> <volume2>\n";
		return 0;
	}
	
	// read the parameters //
	std::string ifName = argv[1];
	std::string ofName = argv[2];
	unsigned int volume1 = atoi(argv[3]);	// minimum area1 of the large components 
	unsigned int volume2 = atoi(argv[4]);	// minimum area2 of the small components ( heads of the cells )
	printf("volume1: %d\t",volume1);
	printf("volume2: %d\n",volume2);
	
	// read input image:
	LabelImageType::Pointer mixtureLabelImage = readImage<LabelImageType>(ifName.c_str());
	LabelPixelType nr = mixtureLabelImage->GetLargestPossibleRegion().GetSize()[0];
	LabelPixelType nc = mixtureLabelImage->GetLargestPossibleRegion().GetSize()[1];
	LabelPixelType ns = mixtureLabelImage->GetLargestPossibleRegion().GetSize()[2];
	LabelPixelType * mixtureLabelImagePtr = mixtureLabelImage->GetBufferPointer();
	
	
	//generate label image
	LabelImageType::SizeType size;
	size[0] = nr;
	size[1] = nc;
	size[2] = ns;
	LabelImageType::Pointer outputImage = GetITKImageOfSize<LabelImageType>(size);
	LabelPixelType * outputImagePtr = outputImage->GetBufferPointer();
	
	// parameters for 2D image
	LabelImageType::SizeType sz2;
	sz2[0] = nr;
	sz2[1] = nc;
	sz2[2] = 1;
	unsigned int sz = nr*nc;

	
	//bool FoundLabel = true;
	
	omp_set_num_threads(1);
	itk::MultiThreader::SetGlobalDefaultNumberOfThreads(1);
	#pragma omp  parallel for num_threads(80)	
	for(size_t t = 0; t<ns; ++t)
 	{	
	
  	    LabelImageType::Pointer output2DImage = GetITKImageOfSize<LabelImageType>(sz2);
	    LabelPixelType * output2DImagePtr = output2DImage->GetBufferPointer();

	  
	    unsigned int i;
	    
	    LabelImageType::Pointer binaryLabelImage = GetITKImageOfSize<LabelImageType>(sz2);
	    LabelPixelType * binaryLabelImagePtr = binaryLabelImage->GetBufferPointer();
	    size_t offset = t*((nr*nc));
	    
	    // first mixture 
	    for(i = 0; i < sz; ++i)
	    {
	      if(mixtureLabelImagePtr[i+offset]>0)
	      {
		 binaryLabelImagePtr[i] = 1;
		 //printf("set pixel to one\n");
	      }
	      else
	      {
		binaryLabelImagePtr[i] = 0;
	      }
	    }
	   
	    // well size is 90x90: if any of the connected components is larger than that  it meas something went wrong with the segmnetation
	   // bool isEmpty = CleanImage(binaryLabelImage,6000);
	    bool isEmpty = false;
	    if(!isEmpty)
	    {
		RemoveSmallComponents(binaryLabelImage, volume1);	      

		// copy the clean image to the output
		for(i = 0; i < sz; ++i)
		{
		  if(binaryLabelImagePtr[i]>0)
		  {
		    output2DImagePtr[i] +=1;
		    //printf("added\n");
		  }
		}
	      
		// second mixture 
		for(i = 0; i < sz; ++i)
		{
		  if(mixtureLabelImagePtr[i+offset]>1)
		  {
		    binaryLabelImagePtr[i] = 1;
		  }
		  else
		  {
		    binaryLabelImagePtr[i] = 0;
		  }
		}	    
	
		RemoveSmallComponents(binaryLabelImage, volume2);	
		// copy the clean image to the output
		for(i = 0; i < sz; ++i)
		{
		  if(binaryLabelImagePtr[i]>0)
		  {
		    output2DImagePtr[i] +=1;
		    //printf("added2\n");
		  }
		}
	    }// end of if statement

	    for(i=0 ; i<sz ; ++i)
		outputImagePtr[i+offset] = output2DImagePtr[i];
	    
	} // end of time loop

      writeImage<LabelImageType>(outputImage, ofName.c_str());



	return 0;
}
Ejemplo n.º 5
0
//Function to process the poly data out of the label image
vtkSmartPointer<vtkPolyData> getVTKPolyDataPrecise(labelImageType::Pointer label)
{
	labelIteratorType liter = labelIteratorType(label,label->GetLargestPossibleRegion());
	liter.GoToBegin();

	//find the maximum number of cells
	unsigned short max1 = 0;
	for(liter.GoToBegin();!liter.IsAtEnd();++liter)
	{
		max1 = MAX(max1,liter.Get());
	}

	//find all the cubes in which cells lie
	cubeCoord* carray = new cubeCoord[max1+1];
	for(int counter=0; counter<=max1; counter++)
	{
		carray[counter].sx=6000;carray[counter].sy=6000;carray[counter].sz=6000;
		carray[counter].ex=0;carray[counter].ey=0;carray[counter].ez=0;
	}

	//Declare label image iterators
	typedef itk::ImageRegionConstIteratorWithIndex<labelImageType> ConstLabelIteratorWithIndex;
	ConstLabelIteratorWithIndex cliter = ConstLabelIteratorWithIndex(label,label->GetLargestPossibleRegion());
	inputImageType::IndexType index;

	//Iterate through the label image
	for(cliter.GoToBegin();!cliter.IsAtEnd();++cliter)
	{
		int cur = cliter.Get();
		if(cur!=0)
		{
			index = cliter.GetIndex();
			carray[cur].sx= MIN(index[0],carray[cur].sx);
			carray[cur].sy= MIN(index[1],carray[cur].sy);
			carray[cur].sz= MIN(index[2],carray[cur].sz);
			carray[cur].ex= MAX(index[0],carray[cur].ex);
			carray[cur].ey= MAX(index[1],carray[cur].ey);
			carray[cur].ez= MAX(index[2],carray[cur].ez);
		}
	}

	//find the largest image size we need
	unsigned short wx=0,wy=0,wz=0;
	for(int counter=1; counter<=max1; counter++)
	{
		wx = MAX(carray[counter].ex-carray[counter].sx+1,wx);
		wy = MAX(carray[counter].ey-carray[counter].sy+1,wy);
		wz = MAX(carray[counter].ez-carray[counter].sz+1,wz);
	}
	// accommodate padding
	wx = wx+2;wy = wy +2; wz = wz+2;
	printf("wx wy wz %u %u %u\n",wx,wy,wz);

	//Declare itk image exporter and vtk image importer, then connect their pipelines
    vtkSmartPointer<vtkImageImport> vtkimporter = vtkSmartPointer<vtkImageImport>::New();
	ExportFilterType::Pointer itkexporter = ExportFilterType::New();
	connectPipelines(itkexporter,(vtkImageImport *)vtkimporter);

	//Using Marching cubes as a contour filter
	vtkSmartPointer<vtkMarchingCubes> contourf = vtkSmartPointer<vtkMarchingCubes>::New();
	contourf->SetInput(vtkimporter->GetOutput());
	contourf->SetValue(0,127);
	contourf->ComputeNormalsOff();
	contourf->ComputeScalarsOff();
	contourf->ComputeGradientsOff();

	//Using vtkSmoothPolyDataFilter as an initial smoothing filter
	vtkSmartPointer<vtkSmoothPolyDataFilter> smoothf = vtkSmartPointer<vtkSmoothPolyDataFilter>::New();
	smoothf->SetInput(contourf->GetOutput());
	smoothf->SetRelaxationFactor(0.3);
	smoothf->SetNumberOfIterations(20);

	//Set up polydata transform
	vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
	transform->PostMultiply();
	transform->Identity();
	vtkSmartPointer<vtkTransformPolyDataFilter> tf = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
	tf->SetTransform(transform);
	tf->SetInput(smoothf->GetOutput());

	vtkSmartPointer<vtkAppendPolyData> appendfilter = vtkSmartPointer<vtkAppendPolyData>::New();
	
	//Generate empty image, and iterate through the cells, filling the image
	inputImageType::Pointer t = getEmptyImage(wx,wy,wz);
	for(int counter=1; counter<=max1; counter++)
	{

		inputImageType::SizeType size;
		inputImageType::RegionType region;
		index.Fill(1);

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

		labelImageType::SizeType lsize;
		labelImageType::IndexType lindex;
		labelImageType::RegionType lregion;

		itkexporter->SetInput(t);

		t->FillBuffer(0);
		lsize[0] = carray[counter].ex-carray[counter].sx+1;
		lsize[1] = carray[counter].ey-carray[counter].sy+1;
		lsize[2] = carray[counter].ez-carray[counter].sz+1;

		lindex[0] = carray[counter].sx;
		lindex[1] = carray[counter].sy;
		lindex[2] = carray[counter].sz;

		lregion.SetIndex(lindex);
		lregion.SetSize(lsize);
		labelIteratorType localiter = labelIteratorType(label,lregion);

		size = lsize;
		region.SetSize(size);
		iteratorType iter = iteratorType(t,region);
		for(localiter.GoToBegin(),iter.GoToBegin();!localiter.IsAtEnd();++localiter,++iter)
		{
			if(localiter.Get()==counter)
			{
				iter.Set(255);
			}
		}
		t->Modified();
		vtkimporter->Modified();

		transform->Identity();	
		transform->Translate(carray[counter].sx-1,carray[counter].sy-1,carray[counter].sz-1);
		tf->SetTransform(transform);
		tf->Update();
		vtkSmartPointer<vtkPolyData> pol=vtkSmartPointer<vtkPolyData>::New();
		pol->DeepCopy(tf->GetOutput());
		
		appendfilter->AddInput(pol);
		printf("Completed %d/%d\r",counter,max1);
	}

	appendfilter->Update();

	//Decimate filter (reduces the number of triangles in the mesh) for the poly data
	vtkSmartPointer<vtkDecimatePro> decimate = vtkSmartPointer<vtkDecimatePro>::New();
	decimate->SetInput(appendfilter->GetOutput());
	decimate->SetTargetReduction(0.75);
	printf("Decimating the contours...");
	decimate->Update();
	printf("Done\n");

	//Smooth poly data filter for a final smoothing
	printf("Smoothing the contours after decimation...");
	vtkSmartPointer<vtkSmoothPolyDataFilter> smoothfinal = vtkSmartPointer<vtkSmoothPolyDataFilter>::New();
	smoothfinal->SetRelaxationFactor(0.2);
	smoothfinal->SetInput(decimate->GetOutput());
	smoothfinal->SetNumberOfIterations(0);
	smoothfinal->Update();
	printf("Done\n");

	//Return processed poly data
	vtkSmartPointer<vtkPolyData> out = smoothfinal->GetOutput();
	return out;
}