使用SimpleITK手动修改3D图像像素后无效果的技术求助
GetBuffer Doesn't Update Output Image Let's break down why your code isn't working and fix it step by step:
Key Issues in Your Code
Incorrect Pixel Index Calculation
Your formula for accessing 3D pixels in the 1D buffer is wrong. SimpleITK uses x as the fastest axis (size[0] = x-dimension, size[1] = y-dimension, size[2] = z-dimension). The correct index formula should map the 3D coordinates to the 1D buffer properly, but your current calculation points to invalid or unrelated memory locations—meaning you weren't actually modifying the pixels you intended.Unnecessary
ImportImageFilter
When you callGetBufferAsUInt8(), you're getting a direct pointer to the original image's underlying memory buffer (assuming the image is contiguous, which it is by default). Modifying this buffer directly changes the originalinputimage, so re-importing the buffer withImportImageFilteris redundant and can cause memory handling confusion.
Fixed Code
Here's the corrected version of your code with clear explanations:
using itk.simple; class Program { static void Main(string[] args) { string filepath = "C:\\Users\\pragun\\Desktop\\Selected Data\\stack.mhd"; ImageFileReader readerx = new ImageFileReader(); readerx.SetFileName(filepath); Image input = readerx.Execute(); // Cast to UInt8 for byte-level buffer access input = SimpleITK.Cast(input, PixelIDValueEnum.sitkUInt8); VectorUInt32 size = input.GetSize(); VectorDouble spacing = input.GetSpacing(); Console.WriteLine($"Image Size: X={size[0]}, Y={size[1]}, Z={size[2]}"); // Get direct pointer to the image's pixel buffer IntPtr buffer = input.GetBufferAsUInt8(); unsafe { byte* bufferPtr = (byte*)buffer.ToPointer(); // Iterate through all 3D pixels with the correct index formula for (int k = 0; k < size[2]; k++) // Z-axis (slowest to iterate) { for (int j = 0; j < size[1]; j++) // Y-axis { for (int i = 0; i < size[0]; i++) // X-axis (fastest to iterate) { // Correct 3D to 1D index mapping int index = i + j * (int)size[0] + k * (int)size[0] * (int)size[1]; bufferPtr[index] = 255; // Set every pixel to white } } } } // No need for ImportImageFilter—use the modified original image directly SimpleITK.Show(input); // Optional: Save the modified image to file ImageFileWriter writer = new ImageFileWriter(); writer.SetFileName("modified_stack.mhd"); writer.Execute(input); } }
Additional Notes
- Enable Unsafe Code: Don't forget to enable unsafe code in your project settings (right-click project → Properties → Build → Check "Allow unsafe code").
- Image Contiguity: If your image ever becomes non-contiguous (rare for standard workflows), create a contiguous copy first with:
input = SimpleITK.MakeImage(input.GetSize(), input); - Unsafe Code Alternative: If you prefer to avoid unsafe code, use
GetPixelAsUInt8()andSetPixelAsUInt8()(note: this is slower for large 3D images):for (int k = 0; k < size[2]; k++) { for (int j = 0; j < size[1]; j++) { for (int i = 0; i < size[0]; i++) { input.SetPixelAsUInt8(new[] { (uint)i, (uint)j, (uint)k }, 255); } } }
内容的提问来源于stack exchange,提问作者Tompel

