MCPcopy Create free account
hub / github.com/MITK/MITK / ImageFromNumpy

Function ImageFromNumpy

Wrapping/Python/mitk/Image.cpp:204–268  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

202// ---------------------------------------------------------------------------
203
204Image::Pointer ImageFromNumpy(py::array array,
205 std::optional<std::array<double, 3>> spacing,
206 std::optional<std::array<double, 3>> origin,
207 std::optional<py::array_t<double>> direction,
208 bool copy)
209{
210 if (!copy)
211 throw py::value_error("from_numpy(copy=False) is not yet supported");
212
213 // Make C-contiguous (forcecast to ensure compatible dtype passes through)
214 auto arr = py::array::ensure(array, py::array::c_style);
215
216 if (!arr)
217 throw py::type_error("from_numpy: input is not array-like");
218
219 const auto ndim = arr.ndim();
220
221 if (ndim < 2 || ndim > 4)
222 throw py::value_error("from_numpy: only 2D, 3D, and 4D arrays are supported");
223
224 // numpy is C-order with the slowest dimension first; MITK expects
225 // dimensions in (x, y, z[, t]) order with x as the fastest dimension.
226 // Reverse the numpy shape to obtain the MITK dimensions vector.
227 std::vector<unsigned int> dims(ndim);
228 for (py::ssize_t i = 0; i < ndim; ++i)
229 dims[i] = static_cast<unsigned int>(arr.shape(ndim - 1 - i));
230
231 auto pixelType = MakePixelType(py::object(arr.dtype()));
232
233 auto img = Image::New();
234 img->Initialize(pixelType, static_cast<unsigned int>(ndim), dims.data());
235
236 // Copy the buffer one volume at a time. For 2D/3D arrays this is a
237 // single SetVolume call; for 4D the slowest numpy dim becomes time.
238 if (ndim < 4)
239 {
240 img->SetVolume(arr.data());
241 }
242 else
243 {
244 const auto bytesPerVolume = static_cast<size_t>(arr.nbytes()) / dims[3];
245 const auto* base = static_cast<const unsigned char*>(arr.data());
246 for (unsigned int t = 0; t < dims[3]; ++t)
247 img->SetVolume(base + static_cast<size_t>(t) * bytesPerVolume, static_cast<int>(t));
248 }
249
250 // Apply geometry overrides to every time step so a 4D image is not left
251 // with inconsistent per-time-step geometries.
252 auto* tg = img->GetTimeGeometry();
253 const auto numSteps = tg->CountTimeSteps();
254
255 for (mitk::TimeStepType t = 0; t < numSteps; ++t)
256 {
257 if (spacing.has_value())
258 SetSpacing(tg, *spacing, t);
259
260 if (origin.has_value())
261 SetOrigin(tg, *origin, t);

Callers 1

InitImageFunction · 0.85

Calls 9

SetSpacingFunction · 0.85
SetOriginFunction · 0.85
SetDirectionFunction · 0.85
SetVolumeMethod · 0.80
MakePixelTypeFunction · 0.70
NewFunction · 0.50
InitializeMethod · 0.45
dataMethod · 0.45
CountTimeStepsMethod · 0.45

Tested by

no test coverage detected