I have an Image3D
object of image type "Bit16" with the dimensions 1472 x 1472 x 1472 that I would like to split into small image cubes of dimension 64 x 64 x 64 which would give me a total of 23^3 = 12167 small Image3D
objects. I want to apply an adaptive thresholding algorithm I already implemented which computes separate thresholds for each image block and then interpolates the computed threshold values (adaptive thresholding). For this purpose I use the function ImagePartition
. The following code illustrates the partitioning:
croppped = ImageCrop[image, {1472, 1472, 1472}];
parts = ImagePartition[cropped, {64, 64, 64}];
I use ImageCrop
to add a border to the original image which results in the mentioned Image3D
object of dimensions 1472 x 1472 x 1472. If I try to run the partitioning my Mathematica kernel crashes with an out of memory error. I have 96 GB RAM installed on my machine. I'm not sure, but the memory should be a sufficient amount of memory available to do the partitioning.
What surprised me is that i can create multiple huge Image3D
objects and the kernel doesn't crash, but when I partition an Image3D
, using ImagePartition it does. See the following code for the memory usage when I create another Image3D
object:
MemoryInUse[]
cropped2 = ImageCrop[image, {1472, 1472, 1472}];
MemoryInUse[]
14461079560
20840097904
Questions:
- Is there a simple explanation for this problem?
- What would be a suitable workaround in order to perform the splitting?
Edit (08/01/2014)
First of all thanks very much UDB for this nice solution you posted. I now had the time to try out the function MyImagePartition
on my data and here are the results I obtained so far. First, to get a feeling for the timings and memory usage I created the same test volume and partitioned it on my machine. I then checked whether the original volume can be assembled again to give the volume again.
volume = Image3D[RandomInteger[{0, 255}, {8, 9, 10}*64], "Byte"];
First@AbsoluteTiming[ip = ImagePartition[volume, {64, 64, 64}]]
10.899000
MaxMemoryUsed[]
First@AbsoluteTiming[mip = MyImagePartition[volume, {64, 64, 64}]]
MaxMemoryUsed[]
248907056 1.505000 542529936
Image3D[ImageAssemble@ip] == volume
True
Image3D[ImageAssemble@mip] == volume
True
Then I tested the function MyImagePartition
on a real image I have. In between the partitioning of the test volume and the real data i quit the kernel to get a fresh Mathematica session. Fortunately, the function is very fast in partitioning my data and memory consumption seems to be no issue. When reassembling it again I checked for the image dimensions of the assembled image.
ImageDimensions@testImage
{458, 403, 202}
MaxMemoryUsed[]
First@AbsoluteTiming[mip = MyImagePartition[testImage, {64, 64, 64}]]
MaxMemoryUsed[]
249027112 0.278000 542635024
ImageDimensions@Image3D[ImageAssemble@mip]
{448, 384, 192}
Obviously the dimensions of the reassembled image do not match the original image dimensions. I have to admit that I didn't fully understand the usage of the second parameter 'dwdh'. Is it the option for image padding such that the image matches up with the partitioning block size? I tried several options but failed continuously ;) Besides that issue, would it be possible to add the functionality to create an overlapping partitioning of the image (e.g. give the overlap of the blocks in voxels as an additional parameter). With the built-in function ImagePartition
this works quite good as follows:
parts = ImagePartition[spheroid3d, {64, 64, 64}, {60, 60, 60},
Padding -> 0];