[Insight-users] Convert image to (multi-dimensional) array in SimpleITK
Zhongliu Xie
zhongliu.xie10 at imperial.ac.uk
Sun Jan 12 16:53:57 EST 2014
Many thanks for the help of you both.
Regards,
Zhongliu
On 12/01/2014 21:47, Dan Mueller wrote:
> Hi Zhongliu,
>
> Further to Brad's email, please find below an example SimpleITK C#
> program demonstrating how to access the pixel buffer of a 2D floating
> point image.
>
> To answer your other question: the "c" stands for component (or
> channel). For a multi-component image (such as a RGB image) each
> component/channel (e.g. red channel, green channel, blue channel) must
> also be accessed in the 1-d array.
>
> HTH
>
> Cheers, Dan
>
> using System;
> using System.Runtime.InteropServices;
>
> using itk.simple;
> using PixelId = itk.simple.PixelIDValueEnum;
>
> namespace TestSimpleITK {
> public class Program {
> static void Main(string[] args) {
>
> var input = SimpleITK.ReadImage("C:/Temp/cthead1.png"); // UC2 =
> unsigned char, 2d
> input = SimpleITK.Cast(input, PixelId.sitkFloat32);
> var size = input.GetSize();
> int len = 1;
> for (int dim = 0; dim < input.GetDimension(); dim++) {
> len *= (int)size[dim];
> }
> IntPtr buffer = input.GetBufferAsFloat();
>
> // 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)
> unsafe {
> float* bufferPtr = (float*)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 j = 0; j < size[1]; j++) {
> for (int i = 0; i < size[0]; i++) {
> float pixel = bufferPtr[i + j*size[1]];
> // Do something with pixel here
> }
> }
> }
>
> // (2) Copy the buffer to a "safe" array (i.e. a fully typed array)
> // (note that this means memory is duplicated)
> var bufferAsArray = new float[len]; // Allocates new memory the
> size of input
> Marshal.Copy(source: buffer, destination: bufferAsArray,
> startIndex: 0, length: len);
> for (int j = 0; j < size[1]; j++) {
> for (int i = 0; i < size[0]; i++) {
> float pixel = bufferAsArray[i + j*size[1]];
> // Do something with pixel here
> }
> }
>
> }
> }
> }
>
> On 13 January 2014 06:54, Zhongliu Xie <zhongliu.xie10 at imperial.ac.uk> wrote:
>> Dear Brad,
>>
>> Thanks for your reply. Yet the method image.GetBufferAsFloat() returns an
>> IntPtr, how do I convert it to float[] then? Also, in the SimpleITK docs it
>> says:
>> uint8_t *buffer = img->GetBufferAsUInt8();
>> buffer[c + numComponents*(x+ xSize* (y*+ySize*z))]
>> what is c in this case?
>>
>> Regards,
>> Zhongliu
>>
>>
>>
>> On 12/01/2014 20:07, Bradley Lowekamp wrote:
>>
>> Hello,
>>
>> Available only in C++ and C#, are a set of methods which being as
>> "GetBufferAs":
>>
>> itk::simple::Image::GetBufferAsInt8;
>> itk::simple::Image::GetBufferAsUInt8;
>> itk::simple::Image::GetBufferAsInt16;
>> itk::simple::Image::GetBufferAsUInt16;
>> itk::simple::Image::GetBufferAsInt32;
>> itk::simple::Image::GetBufferAsUInt32;
>> itk::simple::Image::GetBufferAsInt64;
>> itk::simple::Image::GetBufferAsUInt64;
>> itk::simple::Image::GetBufferAsFloat;
>> itk::simple::Image::GetBufferAsDouble;
>>
>> These return a pointer or array to the image buffer that you are looking
>> for. The correctly typed method mush be call, or else an exception will be
>> thrown. The array returned has not line padding, and a SimpleITK image
>> always begins with an index of [0,0,0].
>>
>> 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.
>>
>> Brad
>>
>>
>> On Jan 12, 2014, at 1:35 PM, Zhongliu Xie <zhongliu.xie10 at imperial.ac.uk>
>> wrote:
>>
>> Dear fellow ITK users,
>>
>> Recently I have been using Simple ITK under C# environment. I wonder whether
>> there is a way to quickly convert an image into an array of intensities
>> (leaving out the meta info)? In particular, is it possible to directly
>> convert to a multidimensional array such as intensity[x,y,z] (or
>> intensity[x][y][z] in C++) indicating the intensity of voxel at <x,y,z>?
>>
>> BTW, I also noticed there is something called Buffer which seems related.
>> Could someone explain what buffer is more explicitly so that I can make
>> sure I understand it correctly?
>>
>> Thanks in advance,
>> Zhongliu
>> _____________________________________
>> Powered by www.kitware.com
>>
>> Visit other Kitware open-source projects at
>> http://www.kitware.com/opensource/opensource.html
>>
>> Kitware offers ITK Training Courses, for more information visit:
>> http://www.kitware.com/products/protraining.php
>>
>> Please keep messages on-topic and check the ITK FAQ at:
>> http://www.itk.org/Wiki/ITK_FAQ
>>
>> Follow this link to subscribe/unsubscribe:
>> http://www.itk.org/mailman/listinfo/insight-users
>>
>>
>>
>> _____________________________________
>> Powered by www.kitware.com
>>
>> Visit other Kitware open-source projects at
>> http://www.kitware.com/opensource/opensource.html
>>
>> Kitware offers ITK Training Courses, for more information visit:
>> http://www.kitware.com/products/protraining.php
>>
>> Please keep messages on-topic and check the ITK FAQ at:
>> http://www.itk.org/Wiki/ITK_FAQ
>>
>> Follow this link to subscribe/unsubscribe:
>> http://www.itk.org/mailman/listinfo/insight-users
>>
More information about the Insight-users
mailing list