Search code examples
c#pointersimage-processingitksimpleitk

SimpleITK - Manipulating pixel of the buffer image


I am currently using SimpleITK libraries for manipulating 3d images. I have been able to read my .mhd meta image and perform thresholding, erotion, dilation, etc. The input image is 3D image (or stacked 2D images) with one component per pixel.

Now I am moving to manual pixel manipulation with get buffer method. I am aware with Simple ITK doxygen and examples https://itk.org/SimpleITKDoxygen/html/ImageGetBuffer_8cs-example.html

I did just that but unable to see the image that I have manipulated - the output image showed just the same as my input image (I've checked my pixel looping and its working, so it seems that either my buffer is not manipulated with the unsafe pointer or I import the buffer wrongly). Here is my code

Help and guidance is much appreciated!! Thanks

        itk.simple.Image input = new itk.simple.Image();
        string filepath = "C:\\Users\\pragun\\Desktop\\Selected Data\\stack.mhd";

        ImageFileReader readerx = new ImageFileReader();
        readerx.SetFileName(filepath);
        input = readerx.Execute();

        input = SimpleITK.Cast(input, PixelIDValueEnum.sitkUInt8);

        // calculate the nubmer of pixels
        VectorUInt32 size = input.GetSize();
        VectorDouble spacing = input.GetSpacing();
        Console.WriteLine(size[0]);
        Console.WriteLine(size[1]);
        Console.WriteLine(size[2]);
        IntPtr buffer = new IntPtr(0);
        buffer = input.GetBufferAsUInt8();
        // There are two ways to access the buffer:
        // (1) Access the underlying buffer as a pointer in an "unsafe" block
        // (note that in C# "unsafe" simply means that the compiler can not
        // perform full type checking), and requires the -unsafe compiler flag
     unsafe
        {
            byte* bufferPtr = (byte*)buffer.ToPointer();
            // Now the byte pointer can be accessed as per Brad's email
            // (of course this example is only a 2d single channel image):
            // This is a 1-D array but can be access as a 3-D. Given an
            // image of size [xS,yS,zS], you can access the image at
            // index [x,y,z] as you wish by image[x+y*xS+z*xS*yS],
            // so x is the fastest axis and z is the slowest.
            for (int k = 0; k < size[2]; k++)
            {
                for (int j = 0; j < size[1]; j++)
                {
                    for (int i = 0; i < size[0]; i++)
                    {

                        byte pixel = bufferPtr[i + j * size[1] + k * size[2]*size[1] ] ;
                        pixel = 255; // example -> it should turn the images to all white
                    }
                }
            }
        }




        itk.simple.ImportImageFilter importer = new ImportImageFilter();


        importer.SetSize(size);
        importer.SetSpacing(spacing);
        importer.SetBufferAsUInt8(buffer);
        importer.SetOutputPixelType(PixelIDValueEnum.sitkUInt8);
        itk.simple.Image output = importer.Execute();


        SimpleITK.Show(output);

Solution

  • Try:

    bufferPtr[i + j * size[1] + k * size[2]*size[1] ] = 255
    

    In the first line of the inner loop you have assigned a value of the array to pixel variable, not the element. In the second line, you have assigned a new value to the variable.