Segmentation and visualization with color

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Segmentation and visualization with color

Ashef Shahrior
I have followed the itk guide and implemented those segmentation methods. Using fast marching segmentation, I am getting this in the fourth box. I have used itk for segmentation and vtk for visualization with C++.
image.png
But what I actually want is something like this - 
image.png
I want to show the segmented portion right on top of the main image but with a different color to distinguish it. How can I do that?

This is my code:-


#include "iostream"
#include "string.h"
using namespace std;

#include "itkCurvatureAnisotropicDiffusionImageFilter.h"

#include "itkGradientMagnitudeRecursiveGaussianImageFilter.h"
#include "itkSigmoidImageFilter.h"

#include "itkFastMarchingImageFilter.h"

#include "itkBinaryThresholdImageFilter.h"

#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

#include "itkRescaleIntensityImageFilter.h"
#include "QuickView.h"

#include "itkCastImageFilter.h"

#include "itkGDCMImageIO.h"

char inputFile[1000], iseedX[100], iseedY[100], isigma[100], isigmoidAlpha[100], isigmoidBeta[100], itimeThreshold[100], istoppingValue[100], inputType[100];
char inputName[1000], outputImage[1000], smoothingOutputImage[1000], gradientMagnitudeOutputImage[1000], sigmoidOutputImage[1000];

void takeInput()
{
    cout<< " Enter file path: ";
    cin>>inputFile;
    cout<< " Enter seed in X position: ";
	cin>>iseedX;
    cout<< " Enter seed in Y position: ";
    cin>>iseedY;
    cout<< " Enter Sigma value: ";
    cin>>isigma;
    cout<< " Enter SigmoidAlpha value: ";
    cin>>isigmoidAlpha;
    cout<< " Enter SigmoidBeta value: ";
    cin>>isigmoidBeta;
    cout<< " Enter time-threshold value: ";
    cin>>itimeThreshold;
    cout<< " Enter stopping value: ";
    cin>>istoppingValue;
    cout<< " Enter input file type '-IMAGE'/'-DICOM' : ";
    cin>>inputType;
}

void getFileName()
{
    int l = strlen(inputFile);
    int x = 0;
    for(int i = l-1; i>-1; i--)
    {
        if(inputFile[i]=='\\')
            break;
        inputName[x] = inputFile[i];
        x++;
    }
    strrev(inputName);
    return;
}


void fastMarchingSegmentation()
{
    try
    {
        takeInput();
        getFileName();
    }
    catch(exception e)
    {
        cout<<"Exception occurred in taking input"<<endl;
    }

    typedef   float           InternalPixelType;
    const     unsigned int    Dimension = 2;
    typedef itk::Image< InternalPixelType, Dimension >  InternalImageType;

    typedef unsigned char                            OutputPixelType;
    typedef itk::Image< OutputPixelType, Dimension > OutputImageType;

    typedef itk::BinaryThresholdImageFilter< InternalImageType, OutputImageType    >    ThresholdingFilterType;
    ThresholdingFilterType::Pointer thresholder = ThresholdingFilterType::New();

    typedef itk::CastImageFilter< InternalImageType, OutputImageType > CastingFilterType;
    CastingFilterType::Pointer caster = CastingFilterType::New();

    const InternalPixelType  timeThreshold = atof( itimeThreshold );

    thresholder->SetLowerThreshold(  0.0  );
    thresholder->SetUpperThreshold( timeThreshold  );

    thresholder->SetOutsideValue(  0  );
    thresholder->SetInsideValue(  255 );

	typedef itk::GDCMImageIO           ImageIOType;
	ImageIOType::Pointer gdcmImageIO = ImageIOType::New();

    typedef  itk::ImageFileReader< InternalImageType > ReaderType;
    typedef  itk::ImageFileWriter<  OutputImageType  > WriterType;

    ReaderType::Pointer reader = ReaderType::New();
    WriterType::Pointer writer = WriterType::New();

    reader->SetFileName( inputFile );
	//outputImage = "Fast Marching Segmented ";// +inputFile;
	strcpy(outputImage, "Fast_Marching_Segmented_");
	strcat(outputImage, inputName);
    writer->SetFileName( outputImage );


	for (int i = 0; inputType[i] != '\0'; i++)
		inputType[i] = toupper(inputType[i]);

	if (strcmp(inputType,"-DICOM")==0)
	{
		reader->SetImageIO(gdcmImageIO);
	}
	try
	{
		reader->Update();
	}
	catch (itk::ExceptionObject & e)
	{
		std::cerr << "exception in file reader " << std::endl;
		std::cerr << e << std::endl;
		return; // EXIT_FAILURE;
	}

    typedef itk::RescaleIntensityImageFilter<InternalImageType, OutputImageType >   CastFilterType;

    typedef   itk::CurvatureAnisotropicDiffusionImageFilter<
    InternalImageType,
    InternalImageType >  SmoothingFilterType;

    SmoothingFilterType::Pointer smoothing = SmoothingFilterType::New();

    typedef   itk::GradientMagnitudeRecursiveGaussianImageFilter<InternalImageType, InternalImageType >  GradientFilterType;

    typedef   itk::SigmoidImageFilter<InternalImageType, InternalImageType >  SigmoidFilterType;

    GradientFilterType::Pointer  gradientMagnitude = GradientFilterType::New();
    SigmoidFilterType::Pointer sigmoid = SigmoidFilterType::New();

    sigmoid->SetOutputMinimum(  0.0  );
    sigmoid->SetOutputMaximum(  1.0  );

    typedef  itk::FastMarchingImageFilter< InternalImageType,InternalImageType >    FastMarchingFilterType;

    FastMarchingFilterType::Pointer  fastMarching = FastMarchingFilterType::New();

    smoothing->SetInput( reader->GetOutput() );
    gradientMagnitude->SetInput( smoothing->GetOutput() );
    sigmoid->SetInput( gradientMagnitude->GetOutput() );
    fastMarching->SetInput( sigmoid->GetOutput() );
    thresholder->SetInput( fastMarching->GetOutput() );
    //caster->SetInput( thresholder->GetOutput() );
    writer->SetInput(thresholder->GetOutput());

    smoothing->SetTimeStep( 0.125 );
    smoothing->SetNumberOfIterations(  5 );
    smoothing->SetConductanceParameter( 9.0 );

    const double sigma = atof( isigma );

    gradientMagnitude->SetSigma(  sigma  );

    const double alpha =  atof( isigmoidAlpha );
    const double beta  =  atof( isigmoidBeta );

    sigmoid->SetAlpha( alpha );
    sigmoid->SetBeta(  beta  );

    typedef FastMarchingFilterType::NodeContainer           NodeContainer;
    typedef FastMarchingFilterType::NodeType                NodeType;
    NodeContainer::Pointer seeds = NodeContainer::New();

    InternalImageType::IndexType  seedPosition;

    seedPosition[0] = atoi( iseedX );
    seedPosition[1] = atoi( iseedY );

    NodeType node;
    const double seedValue = 0.0;

    node.SetValue( seedValue );
    node.SetIndex( seedPosition );

    seeds->Initialize();
    seeds->InsertElement( 0, node );

    fastMarching->SetTrialPoints(  seeds  );


    typedef itk::Image<unsigned char, 2>  ImageType;
    ImageType::Pointer image;
	QuickView viewer;

    try
    {
		typedef itk::RescaleIntensityImageFilter< ImageType, ImageType > RescaleFilterType;
		RescaleFilterType::Pointer caster1 = RescaleFilterType::New();
        WriterType::Pointer writer1 = WriterType::New();
        caster->SetInput( smoothing->GetOutput() );

        image = caster->GetOutput();

        caster1->SetInput( image );
        writer1->SetInput( caster1->GetOutput() );
        //writer1->SetFileName("Smoothing Output Image "+inputFile);
        char t1[100];
		strcpy(t1,"Smoothing_Output_Image_" );
		char tmp[1000];
		strcpy(tmp,inputName);
		strcat(t1, tmp);
		writer1->SetFileName(t1);
        caster1->SetOutputMinimum(   0 );
        caster1->SetOutputMaximum( 255 );
        caster1->Update();
        writer1->Update();
        //QuickView viewer;
        //viewer.AddImage(image.GetPointer());
        viewer.AddImage(caster1->GetOutput());

    }
    catch( itk::ExceptionObject & err )
    {
        std::cerr << "ExceptionObject caught in the kahini one !" << std::endl;
        std::cerr << err << std::endl;
		return; // EXIT_FAILURE;
    }

    try
    {
        CastFilterType::Pointer caster2 = CastFilterType::New();
        WriterType::Pointer writer2 = WriterType::New();
        caster2->SetInput( gradientMagnitude->GetOutput() );
        writer2->SetInput( caster2->GetOutput() );
        //writer2->SetFileName("Gradient Magnitude Output Image "+inputFile);
        char t1[100];
        strcpy(t1,"Gradient_Magnitude_Output_Image_");
		char tmp[1000];
		strcpy(tmp, inputName);
		strcat(t1, tmp);
		writer2->SetFileName(t1);
        caster2->SetOutputMinimum(   0 );
        caster2->SetOutputMaximum( 255 );
        writer2->Update();

		image = caster2->GetOutput();

		/*
		QuickView viewer;
		viewer.AddImage(image.GetPointer());*/
		viewer.AddImage(caster2->GetOutput());
    }
    catch( itk::ExceptionObject & err )
    {
        std::cerr << "ExceptionObject caught !" << std::endl;
        std::cerr << err << std::endl;
		return; //EXIT_FAILURE;
    }

    try
    {
        CastFilterType::Pointer caster3 = CastFilterType::New();
        WriterType::Pointer writer3 = WriterType::New();
        caster3->SetInput( sigmoid->GetOutput() );
        writer3->SetInput( caster3->GetOutput() );
        //writer3->SetFileName("Sigmoid Output Image"+inputFile);

        char t1[100];
		strcpy(t1,"Sigmoid_Output_Image_");
		char tmp[1000];
		strcpy(tmp,inputName);
		strcat(t1, tmp);
		writer3->SetFileName(t1);
        caster3->SetOutputMinimum(   0 );
        caster3->SetOutputMaximum( 255 );
        writer3->Update();

		//image = caster3->GetOutput();
		//QuickView viewer;
		//viewer.AddImage(image.GetPointer());
		viewer.AddImage(caster3->GetOutput());
		//viewer.Visualize();
    }
    catch( itk::ExceptionObject & err )
    {
        std::cerr << "ExceptionObject caught !" << std::endl;
        std::cerr << err << std::endl;
		return; //EXIT_FAILURE;
    }

    fastMarching->SetOutputSize( reader->GetOutput()->GetBufferedRegion().GetSize() );

    const double stoppingTime = atof( istoppingValue );

    fastMarching->SetStoppingValue(  stoppingTime  );

    try
    {
        writer->Update();
    }
    catch( itk::ExceptionObject & excep )
    {
        std::cerr << "Exception caught !" << std::endl;
        std::cerr << excep << std::endl;
		return; //EXIT_FAILURE;
    }

    try
    {
        CastFilterType::Pointer caster4 = CastFilterType::New();
        WriterType::Pointer writer4 = WriterType::New();
        caster4->SetInput( fastMarching->GetOutput() );
        writer4->SetInput( caster4->GetOutput() );
        //writer4->SetFileName("Fast Marching Filter Output " + inputFile);
        char t1[100];
		strcpy(t1,"Fast_Marching_Filter_Output_");
		char tmp[1000];
		strcpy(tmp,inputName);
		strcat(t1, tmp);
		writer4->SetFileName(t1);
        caster4->SetOutputMinimum(   0 );
        caster4->SetOutputMaximum( 255 );
        writer4->Update();

		viewer.AddImage(caster4->GetOutput());

    }
    catch( itk::ExceptionObject & err )
    {
        std::cerr << "ExceptionObject caught !" << std::endl;
        std::cerr << err << std::endl;
		return; //EXIT_FAILURE;
    }
	viewer.ShareCameraOff();
	viewer.Visualize();
}


_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Please keep messages on-topic and check the VTK FAQ at: http://www.vtk.org/Wiki/VTK_FAQ

Search the list archives at: http://markmail.org/search/?q=vtkusers

Follow this link to subscribe/unsubscribe:
https://public.kitware.com/mailman/listinfo/vtkusers
Reply | Threaded
Open this post in threaded view
|

Re: Segmentation and visualization with color

Dženan Zukić
Hi Ashef,

have you looked at this example? If not, try it. Otherwise re-post this question on the forum. There was already a similar question.

Regards,
Dženan

On Thu, Jul 12, 2018 at 10:53 AM Ashef Shahrior <[hidden email]> wrote:
I have followed the itk guide and implemented those segmentation methods. Using fast marching segmentation, I am getting this in the fourth box. I have used itk for segmentation and vtk for visualization with C++.
image.png
But what I actually want is something like this - 
image.png
I want to show the segmented portion right on top of the main image but with a different color to distinguish it. How can I do that?

This is my code:-


#include "iostream"
#include "string.h"
using namespace std;

#include "itkCurvatureAnisotropicDiffusionImageFilter.h"

#include "itkGradientMagnitudeRecursiveGaussianImageFilter.h"
#include "itkSigmoidImageFilter.h"

#include "itkFastMarchingImageFilter.h"

#include "itkBinaryThresholdImageFilter.h"

#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

#include "itkRescaleIntensityImageFilter.h"
#include "QuickView.h"

#include "itkCastImageFilter.h"

#include "itkGDCMImageIO.h"

char inputFile[1000], iseedX[100], iseedY[100], isigma[100], isigmoidAlpha[100], isigmoidBeta[100], itimeThreshold[100], istoppingValue[100], inputType[100];
char inputName[1000], outputImage[1000], smoothingOutputImage[1000], gradientMagnitudeOutputImage[1000], sigmoidOutputImage[1000];

void takeInput()
{
    cout<< " Enter file path: ";
    cin>>inputFile;
    cout<< " Enter seed in X position: ";
	cin>>iseedX;
    cout<< " Enter seed in Y position: ";
    cin>>iseedY;
    cout<< " Enter Sigma value: ";
    cin>>isigma;
    cout<< " Enter SigmoidAlpha value: ";
    cin>>isigmoidAlpha;
    cout<< " Enter SigmoidBeta value: ";
    cin>>isigmoidBeta;
    cout<< " Enter time-threshold value: ";
    cin>>itimeThreshold;
    cout<< " Enter stopping value: ";
    cin>>istoppingValue;
    cout<< " Enter input file type '-IMAGE'/'-DICOM' : ";
    cin>>inputType;
}

void getFileName()
{
    int l = strlen(inputFile);
    int x = 0;
    for(int i = l-1; i>-1; i--)
    {
        if(inputFile[i]=='\\')
            break;
        inputName[x] = inputFile[i];
        x++;
    }
    strrev(inputName);
    return;
}


void fastMarchingSegmentation()
{
    try
    {
        takeInput();
        getFileName();
    }
    catch(exception e)
    {
        cout<<"Exception occurred in taking input"<<endl;
    }

    typedef   float           InternalPixelType;
    const     unsigned int    Dimension = 2;
    typedef itk::Image< InternalPixelType, Dimension >  InternalImageType;

    typedef unsigned char                            OutputPixelType;
    typedef itk::Image< OutputPixelType, Dimension > OutputImageType;

    typedef itk::BinaryThresholdImageFilter< InternalImageType, OutputImageType    >    ThresholdingFilterType;
    ThresholdingFilterType::Pointer thresholder = ThresholdingFilterType::New();

    typedef itk::CastImageFilter< InternalImageType, OutputImageType > CastingFilterType;
    CastingFilterType::Pointer caster = CastingFilterType::New();

    const InternalPixelType  timeThreshold = atof( itimeThreshold );

    thresholder->SetLowerThreshold(  0.0  );
    thresholder->SetUpperThreshold( timeThreshold  );

    thresholder->SetOutsideValue(  0  );
    thresholder->SetInsideValue(  255 );

	typedef itk::GDCMImageIO           ImageIOType;
	ImageIOType::Pointer gdcmImageIO = ImageIOType::New();

    typedef  itk::ImageFileReader< InternalImageType > ReaderType;
    typedef  itk::ImageFileWriter<  OutputImageType  > WriterType;

    ReaderType::Pointer reader = ReaderType::New();
    WriterType::Pointer writer = WriterType::New();

    reader->SetFileName( inputFile );
	//outputImage = "Fast Marching Segmented ";// +inputFile;
	strcpy(outputImage, "Fast_Marching_Segmented_");
	strcat(outputImage, inputName);
    writer->SetFileName( outputImage );


	for (int i = 0; inputType[i] != '\0'; i++)
		inputType[i] = toupper(inputType[i]);

	if (strcmp(inputType,"-DICOM")==0)
	{
		reader->SetImageIO(gdcmImageIO);
	}
	try
	{
		reader->Update();
	}
	catch (itk::ExceptionObject & e)
	{
		std::cerr << "exception in file reader " << std::endl;
		std::cerr << e << std::endl;
		return; // EXIT_FAILURE;
	}

    typedef itk::RescaleIntensityImageFilter<InternalImageType, OutputImageType >   CastFilterType;

    typedef   itk::CurvatureAnisotropicDiffusionImageFilter<
    InternalImageType,
    InternalImageType >  SmoothingFilterType;

    SmoothingFilterType::Pointer smoothing = SmoothingFilterType::New();

    typedef   itk::GradientMagnitudeRecursiveGaussianImageFilter<InternalImageType, InternalImageType >  GradientFilterType;

    typedef   itk::SigmoidImageFilter<InternalImageType, InternalImageType >  SigmoidFilterType;

    GradientFilterType::Pointer  gradientMagnitude = GradientFilterType::New();
    SigmoidFilterType::Pointer sigmoid = SigmoidFilterType::New();

    sigmoid->SetOutputMinimum(  0.0  );
    sigmoid->SetOutputMaximum(  1.0  );

    typedef  itk::FastMarchingImageFilter< InternalImageType,InternalImageType >    FastMarchingFilterType;

    FastMarchingFilterType::Pointer  fastMarching = FastMarchingFilterType::New();

    smoothing->SetInput( reader->GetOutput() );
    gradientMagnitude->SetInput( smoothing->GetOutput() );
    sigmoid->SetInput( gradientMagnitude->GetOutput() );
    fastMarching->SetInput( sigmoid->GetOutput() );
    thresholder->SetInput( fastMarching->GetOutput() );
    //caster->SetInput( thresholder->GetOutput() );
    writer->SetInput(thresholder->GetOutput());

    smoothing->SetTimeStep( 0.125 );
    smoothing->SetNumberOfIterations(  5 );
    smoothing->SetConductanceParameter( 9.0 );

    const double sigma = atof( isigma );

    gradientMagnitude->SetSigma(  sigma  );

    const double alpha =  atof( isigmoidAlpha );
    const double beta  =  atof( isigmoidBeta );

    sigmoid->SetAlpha( alpha );
    sigmoid->SetBeta(  beta  );

    typedef FastMarchingFilterType::NodeContainer           NodeContainer;
    typedef FastMarchingFilterType::NodeType                NodeType;
    NodeContainer::Pointer seeds = NodeContainer::New();

    InternalImageType::IndexType  seedPosition;

    seedPosition[0] = atoi( iseedX );
    seedPosition[1] = atoi( iseedY );

    NodeType node;
    const double seedValue = 0.0;

    node.SetValue( seedValue );
    node.SetIndex( seedPosition );

    seeds->Initialize();
    seeds->InsertElement( 0, node );

    fastMarching->SetTrialPoints(  seeds  );


    typedef itk::Image<unsigned char, 2>  ImageType;
    ImageType::Pointer image;
	QuickView viewer;

    try
    {
		typedef itk::RescaleIntensityImageFilter< ImageType, ImageType > RescaleFilterType;
		RescaleFilterType::Pointer caster1 = RescaleFilterType::New();
        WriterType::Pointer writer1 = WriterType::New();
        caster->SetInput( smoothing->GetOutput() );

        image = caster->GetOutput();

        caster1->SetInput( image );
        writer1->SetInput( caster1->GetOutput() );
        //writer1->SetFileName("Smoothing Output Image "+inputFile);
        char t1[100];
		strcpy(t1,"Smoothing_Output_Image_" );
		char tmp[1000];
		strcpy(tmp,inputName);
		strcat(t1, tmp);
		writer1->SetFileName(t1);
        caster1->SetOutputMinimum(   0 );
        caster1->SetOutputMaximum( 255 );
        caster1->Update();
        writer1->Update();
        //QuickView viewer;
        //viewer.AddImage(image.GetPointer());
        viewer.AddImage(caster1->GetOutput());

    }
    catch( itk::ExceptionObject & err )
    {
        std::cerr << "ExceptionObject caught in the kahini one !" << std::endl;
        std::cerr << err << std::endl;
		return; // EXIT_FAILURE;
    }

    try
    {
        CastFilterType::Pointer caster2 = CastFilterType::New();
        WriterType::Pointer writer2 = WriterType::New();
        caster2->SetInput( gradientMagnitude->GetOutput() );
        writer2->SetInput( caster2->GetOutput() );
        //writer2->SetFileName("Gradient Magnitude Output Image "+inputFile);
        char t1[100];
        strcpy(t1,"Gradient_Magnitude_Output_Image_");
		char tmp[1000];
		strcpy(tmp, inputName);
		strcat(t1, tmp);
		writer2->SetFileName(t1);
        caster2->SetOutputMinimum(   0 );
        caster2->SetOutputMaximum( 255 );
        writer2->Update();

		image = caster2->GetOutput();

		/*
		QuickView viewer;
		viewer.AddImage(image.GetPointer());*/
		viewer.AddImage(caster2->GetOutput());
    }
    catch( itk::ExceptionObject & err )
    {
        std::cerr << "ExceptionObject caught !" << std::endl;
        std::cerr << err << std::endl;
		return; //EXIT_FAILURE;
    }

    try
    {
        CastFilterType::Pointer caster3 = CastFilterType::New();
        WriterType::Pointer writer3 = WriterType::New();
        caster3->SetInput( sigmoid->GetOutput() );
        writer3->SetInput( caster3->GetOutput() );
        //writer3->SetFileName("Sigmoid Output Image"+inputFile);

        char t1[100];
		strcpy(t1,"Sigmoid_Output_Image_");
		char tmp[1000];
		strcpy(tmp,inputName);
		strcat(t1, tmp);
		writer3->SetFileName(t1);
        caster3->SetOutputMinimum(   0 );
        caster3->SetOutputMaximum( 255 );
        writer3->Update();

		//image = caster3->GetOutput();
		//QuickView viewer;
		//viewer.AddImage(image.GetPointer());
		viewer.AddImage(caster3->GetOutput());
		//viewer.Visualize();
    }
    catch( itk::ExceptionObject & err )
    {
        std::cerr << "ExceptionObject caught !" << std::endl;
        std::cerr << err << std::endl;
		return; //EXIT_FAILURE;
    }

    fastMarching->SetOutputSize( reader->GetOutput()->GetBufferedRegion().GetSize() );

    const double stoppingTime = atof( istoppingValue );

    fastMarching->SetStoppingValue(  stoppingTime  );

    try
    {
        writer->Update();
    }
    catch( itk::ExceptionObject & excep )
    {
        std::cerr << "Exception caught !" << std::endl;
        std::cerr << excep << std::endl;
		return; //EXIT_FAILURE;
    }

    try
    {
        CastFilterType::Pointer caster4 = CastFilterType::New();
        WriterType::Pointer writer4 = WriterType::New();
        caster4->SetInput( fastMarching->GetOutput() );
        writer4->SetInput( caster4->GetOutput() );
        //writer4->SetFileName("Fast Marching Filter Output " + inputFile);
        char t1[100];
		strcpy(t1,"Fast_Marching_Filter_Output_");
		char tmp[1000];
		strcpy(tmp,inputName);
		strcat(t1, tmp);
		writer4->SetFileName(t1);
        caster4->SetOutputMinimum(   0 );
        caster4->SetOutputMaximum( 255 );
        writer4->Update();

		viewer.AddImage(caster4->GetOutput());

    }
    catch( itk::ExceptionObject & err )
    {
        std::cerr << "ExceptionObject caught !" << std::endl;
        std::cerr << err << std::endl;
		return; //EXIT_FAILURE;
    }
	viewer.ShareCameraOff();
	viewer.Visualize();
}

_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Please keep messages on-topic and check the VTK FAQ at: http://www.vtk.org/Wiki/VTK_FAQ

Search the list archives at: http://markmail.org/search/?q=vtkusers

Follow this link to subscribe/unsubscribe:
https://public.kitware.com/mailman/listinfo/vtkusers

_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Please keep messages on-topic and check the VTK FAQ at: http://www.vtk.org/Wiki/VTK_FAQ

Search the list archives at: http://markmail.org/search/?q=vtkusers

Follow this link to subscribe/unsubscribe:
https://public.kitware.com/mailman/listinfo/vtkusers