3
$\begingroup$

I am working on medical image exactly CT scan images, there is a method for reading these type of images, also another method for resampling, the code for two methods shown below:

def load_itk_image(filename):
    # read infos from route
    itkimage = sitk.ReadImage(filename)
    # read imagearray
    numpyImage = sitk.GetArrayFromImage(itkimage)
    # read coords
    # the given coords and spacing comes: x, y, z and we should transfer it to z, y, x
    numpyOrigin = np.array(list(reversed(itkimage.GetOrigin())))
    numpySpacing = np.array(list(reversed(itkimage.GetSpacing())))

    return numpyImage, numpyOrigin, numpySpacing

def resample(image,oldspacing,newspacing):
    start_time = time.time()
    resize_factor = np.array(oldspacing).astype(np.float)/np.array(newspacing).astype(np.float)
    new_real_shape = image.shape * resize_factor
    new_shape = np.round(new_real_shape)
    real_resize_factor = new_shape/image.shape
    image = scipy.ndimage.interpolation.zoom(image, real_resize_factor, mode = "nearest")
    print("%s time takes in seconds" % (time.time() - start_time))
    return np.array(image)

my problem is, resample function takes a large amount of time to resample only one 2d image approximatly 30 seconds, why it takes these amount of time? is there any way to reduce resampling time?

$\endgroup$
5
  • $\begingroup$ Can you share one of the images, or post a link to a openly available example dataset? Which format do your images have on disk (what is the file extension)? I want to know the form of the itkimage. What type of object is it? $\endgroup$
    – n1k31t4
    Sep 2, 2018 at 11:28
  • $\begingroup$ the images has two different extensions '.mhd' and '.raw', I work on '.mhd' files, the dataset is freely available here: dropbox.com/sh/mtip9dx6zt9nb3z/AAAKyhu_Ry6NmNKILQ3fA8Nba?dl=0 $\endgroup$
    – Hunar
    Sep 2, 2018 at 16:19
  • $\begingroup$ I didn't download the data because the smallest chunk is 6Gb. Why are you actually resampling the data? If they are images, you only need to make them bigger with some interpolation, right? You don't care about interolating in the 3rd dimension assuming the scans have a z-dim > 1 anyway?). If this is true, you could try resizing using OpenCV. Have a look at this demo. $\endgroup$
    – n1k31t4
    Sep 3, 2018 at 12:07
  • $\begingroup$ the zip file sizes are too big for that I will provide you with two links for one of the scans (with .mhd and .raw extensions) 1- dropbox.com/s/z0fmdhv30c82bzs/… 2- dropbox.com/s/5szgcokqcyoilgt/… $\endgroup$
    – Hunar
    Sep 3, 2018 at 13:49
  • $\begingroup$ for why I do resampling, you can read the reason in the link below, in resample section: kaggle.com/gzuidhof/full-preprocessing-tutorial $\endgroup$
    – Hunar
    Sep 3, 2018 at 13:52

1 Answer 1

1
$\begingroup$

Although my money would be on the interpolation function taking a fair while, here are a few other ideas:

1. Is that resize_factor matrix going to be different for every single image? You could otherwise pre-compute it one for all images of a given size and then just use it, instead of re-computing it for every image.

2. One aspect, which may answer your other related question on DS), is memory usage, that can take time if the arrays are large enough. Those matrix divisions that you perform will return a new matrix, that means a new chunk of memory. If it turns out (from the profiling idea below), that those division operations are costly, you could instead try pre-allocating an array to hold all your results (assuming you know the relaevant shapes), then filling the array with the output.

3. ``scipy.interpolation.zoomreturns anndarray, so you don't need to callnp.arrayon it again in your return statement of theresample` function.


I would suggest profiling your script. This will allow you to see which function calls are called most often and which take the most time. You can then focus on making making changes that will have the biggest effect on the runtime. Here is a nice example tutorial if you're new to profiling in Python.

You can use cProfile, a built-in python module. You can do this in the terminal quite simply (if your script is designed to be run that way) by running:

python -m cProfile -o profiling_results.prof your_script.py

In words (flags shown in bold): python run the module cProfile, to run your_script.py, producing the output file profiling_results.prof.

The generic version of this command it:

python -m cProfile [-o output_file] [-s sort_order] (-m module | myscript.py)

You can open and read the output file in a normal text editor. The suffix is a common convention, because you can pass it to a tool like SnakeViz, which will allow you to visualise the results and introspect the method tree of your script; the order in which functions call each other.


There is a notebook on Kaggle, which you may find interesting, as it performs similar tasks on the same LUNA16 dataset.

$\endgroup$
7
  • $\begingroup$ thank you for all of your explanation, I will try it out, really the idea of the cprofile is interesting I did not know about it before, tried to use same code as in the video tutorial it but I get this error: RecursionError: maximum recursion depth exceeded. $\endgroup$
    – Hunar
    Sep 3, 2018 at 7:40
  • $\begingroup$ @honar.cs - you can try adding import sys; sys.setrecursionlimit(5000) to the start of your script. The default on my machine is actually 3000 - check with sys.getrecursionlimit(). Perhaps the location of the recursion error will actually tell you where your problem is! $\endgroup$
    – n1k31t4
    Sep 3, 2018 at 8:16
  • $\begingroup$ tried this but getting the same error. $\endgroup$
    – Hunar
    Sep 3, 2018 at 8:38
  • $\begingroup$ tried it in another way, here is the result: ibb.co/d98PPe $\endgroup$
    – Hunar
    Sep 3, 2018 at 8:46
  • 1
    $\begingroup$ You can see from the cumulative time column that the zoom_shift and spline_filterID methods are taking all the time within the interpolation function, as I had guessed. You can't (easily) change those library methods, so you'd either have to reduce your data size beforehand, play with the parameters of those functions, or come up with a different way to get what you want. $\endgroup$
    – n1k31t4
    Sep 3, 2018 at 9:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.