Comments (8)
Do you have a minimal reproducible example of this issue?
Also any reason why not using the sitk.GetArrayFromImage method?
from simpleitk.
Minimal example:
import SimpleITK as sitk
img = sitk.Image()
img.GetBufferAsFloat()
Traceback (most recent call last):
AttributeError: 'Image' object has no attribute 'GetBufferAsFloat'
Reason: When working with many large image volumes in parallel on low-performance systems I want to allow suitable in-place numpy operations on the sitk.Image buffer without creating copies.
from simpleitk.
I am able to find in the git history any intentional removal of these methods in Python. Nor do I ever recall intentionally exposing them to go around the copy on write policies in Python. This will require more searching and maybe a git bisect to determine what changed the interface.
How are you converting the swig *float buffer to numpy?
There is the sitk::_GetMemoryViewFromImage
method which is used by sitk::GetArrayFromImage
, which returns a python memory view without performing the copy on write logics that may work as a replacement.
from simpleitk.
The following code works for me in SimpleITK version 2.2.1:
import ctypes
import numpy as np
import SimpleITK as sitk
def get_array_from_buffer(img):
buffer_type = ctypes.c_float * img.GetNumberOfPixels()
buffer = buffer_type.from_address(int(img.GetBufferAsFloat()))
np_arr = np.frombuffer(buffer, dtype=np.float32)
# reshape: sitk (x:columns, y:rows, z:slices) -> numpy (z:slices, y:rows, x:columns)
return np_arr.reshape(img.GetDepth(), img.GetHeight(), img.GetWidth())
reader = sitk.ImageFileReader()
reader.SetFileName('path/to/source.dcm')
reader.SetOutputPixelType(sitk.sitkFloat32) # convert to 32-bit float
img = reader.Execute()
arr = get_array_from_buffer(img)
print(arr, '\n\n')
arr += 1234
print(arr, '\n\n')
# replace pixel value and check if it happened in the buffer
arr[0,2,1] = 4321
print(img[1,2,0])
print(img.GetBufferAsFloat())
print(sitk._SimpleITK._GetMemoryViewFromImage(img))
The last 2 print statements return different things. How would I use the latter to work like the former?
from simpleitk.
I think this is the conversion you are looking for:
SimpleITK/Wrapping/Python/SimpleITK/extra.py
Lines 273 to 275 in 46bf97c
from simpleitk.
Problem is numpy.view is readonly:
def get_array_from_buffer(img):
image_memory_view = sitk._SimpleITK._GetMemoryViewFromImage(img)
array_view = np.asarray(image_memory_view).view(dtype=np.float32)
array_view[0] = 123
# reshape: sitk (x:columns, y:rows, z:slices) -> numpy (z:slices, y:rows, x:columns)
return array_view.reshape(img.GetDepth(), img.GetHeight(), img.GetWidth())
results in
array_view[0] = 123
ValueError: assignment destination is read-only
If I use numpy.astype instead with copy=False (i.e. inplace)
def get_array_from_buffer(img):
image_memory_view = sitk._SimpleITK._GetMemoryViewFromImage(img)
array_view = np.asarray(image_memory_view).astype(dtype=np.float32, copy=False)
array_view[0] = 123
# reshape: sitk (x:columns, y:rows, z:slices) -> numpy (z:slices, y:rows, x:columns)
return array_view.reshape(img.GetDepth(), img.GetHeight(), img.GetWidth())
I can actually modify the numpy array without complaint but now the size and the values of the array (i.e. the memory interpretation) is off and I cannot reshape.
return array_view.reshape(img.GetDepth(), img.GetHeight(), img.GetWidth())
ValueError: cannot reshape array of size 1048576 into shape (1,512,512)
The array_view.shape (as well as image_memory_view.shape) is (1048576,) and therefore 4 x 512*512 which is the pixel matrix. Any suggestions on how to juggle this around to make it work?
from simpleitk.
Figured it out using memory view as suggested. I couldn't obtain a writable numpy array directly from sitk no matter what I tried, but numpy offers access to the buffer of any array, so I could trick it into being writeable:
import numpy as np
import SimpleITK as sitk
from SimpleITK.SimpleITK import _GetMemoryViewFromImage
def get_array_from_buffer(img: sitk.Image):
buffer_type = ctypes.c_float * img.GetNumberOfPixels()
# SimpleITK version: < 2.3.0
# buffer = buffer_type.from_address(int(img.GetBufferAsFloat()))
# SimpleITK version: all
memory_view = sitk._SimpleITK._GetMemoryViewFromImage(img)
array_view = np.asarray(memory_view).view(dtype=np.float32)
buffer = buffer_type.from_address(array_view.ctypes.data)
array_writeable = np.frombuffer(buffer, dtype=np.float32)
# reshape: sitk (x:columns, y:rows, z:slices) -> numpy (z:slices, y:rows, x:columns)
return array_writeable.reshape(img.GetSize()[::-1])
# Test
# create zero image (3 rows x 3 columns x 2 slices) of floats
img = sitk.Image((3,3,2), sitk.sitkFloat32)
arr = get_array_from_buffer(img)
print('arr =', arr)
print('arr[0,2,1] =', arr[0,2,1], ' img[1,2,0] =', img[1,2,0], '\n')
# replace pixel value and check if it happened in the buffer
print('arr[0,2,1] = 4321\n')
arr[0,2,1] = 4321
print('arr =', arr)
print('arr[0,2,1] =', arr[0,2,1], ' img[1,2,0] =', img[1,2,0], '\n')
print('arr += 10\n')
arr += 10
print('arr =', arr)
I have a couple of requests before you close this issue:
- Please document here (and wherever else appropriate) if buffer access was removed on purpose and why, just in case someone else bumps into this during their search. I couldn't find anything in my search before opening the issue.
- Reconsider removing buffer access. If numpy allows it, then you can. Also, for someone coming from C++ ITK it feels weird to work with the buffer in one language but being denied access in another.
FYI, Google Bard hallucinated to me that there is a sitk.Image.GetPixelPointer()
function in version 2.3.2 until I made it aware of the fact that there is no such version released. Maybe Alphabet is watching your activities and my issue here is just some brief episode and a fix is coming soon with such a new function. Would still be good to document somewhere.
Thanks!
from simpleitk.
The GetBuffer
methods were inadvertently added in 6c2ea55 and released in v2.1.x. Then the behavior was removed 66005b0, for release 2.3.x. So SimpleITK release 2.1.x, and 2.2.x appear to mistakenly have these GetBuffer
methods.
Python 3.12 added support for PEP688 which enables proper buffer protocols for native python classes. This looks like a good way to improve our interface moving forward. Contributions are welcomed.
from simpleitk.
Related Issues (20)
- CMake hangs on M1 HOT 1
- Python Documentation bug in sitk.Image constructor HOT 4
- sitk::ERROR: Pixel type: 32-bit unsigned integer is not supported in 3D byN3itk6simple15MaskImageFilterE HOT 7
- Export `PixelIDValueEnum` members as members of Enum in Python binding
- missing numpy dependency in python wheels and conda package HOT 2
- Move detailed class description to the top of the doc page
- Install on IpadOS v16.6 HOT 2
- RuntimeError: Exception thrown in SimpleITK ImageFileReader_Execute: ../Code/IO/src/sitkImageReaderBase.cxx:97: sitk::ERROR: HOT 1
- Add ImageSeriesReader::SpacingWarningRelThreshold
- SimpleITK getting slower with intense working (JAVA) (memory leak?) HOT 11
- enable ImageFileReader.SetUseStreaming method for JAVA
- SetKernelRadius() does not handle numpy integer types HOT 1
- Extend sitk.ReadImage()/WriteImage() to support pathlib.Path() HOT 1
- add or change the interface for the ImageRegistraitonMethod.SetOptimizerAsAmoeba method HOT 1
- Error writing `SimpleITK Image` to DICOM files
- PEP 688 add buffer protocol support
- After registration, is the order of transforms composition specified in the documentation correct? HOT 4
- `MetaData dictionary key must be str`? HOT 2
- simpleITK python acts differently while reading metadata with upper or lower case hexadecimal label HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from simpleitk.