1

I have a numpy array A composed of multiple same sized images [N_images,width,height,3].

I want to apply misc.imresize() to each and everyone of them the fastest way possible.

So I defined:

def myfunc(x):
  return misc.imresize(x,(wanted_width,wanted_height))

and then I did:

vfunc=np.vectorize(my_func)

but when I try:

test=vfunc(A)

I get a not-suitable-array-shape-for-converting-into-images error. I thought it was because I did not specify the axis on which the op should be vectorized, which caused it to not broadcast the array ops the way to wanted so I tried another thing to narrow down the error:

test=np.apply_along_axis(my_func,0,A)

and got the same error. Even if I force a np.squeeze() into my_func. That really surprised me.

EDIT: I also tried with map same error. It might stem from the fact that you can only use vectorize with scalar function as pointed out by @jotasi.

It must be pretty silly but I do not know what is going on. Could somebody enlighten me ? Is there a way to fix it ?

jeandut
  • 2,471
  • 4
  • 29
  • 56
  • `np.vectorize` does not have an `axis` parameter as it is only meant to be used for functions that are not numpy aware and take scalars. See [this answer](http://stackoverflow.com/a/3379505/6614295) for details. – jotasi Dec 15 '16 at 09:06
  • Thanks, I didn't know that ! So should I give up trying to vectorize it or is there some other ways ? – jeandut Dec 15 '16 at 09:07
  • I don't think that there is an easy way to avoid doing some kind of loop, as `misc.imresize` also does not support a vectorized application along an axis. If your image is large enough, I'd guess, that a loop should not represent a bottleneck anyway. – jotasi Dec 15 '16 at 09:10
  • Ok I will close my question tomorrow if there is a consensus. – jeandut Dec 15 '16 at 09:12
  • Yes. Definitively, I also might be mistaken. Let's see if someone else comes up with something. – jotasi Dec 15 '16 at 09:14
  • If speed is your motivation then `np.vectorize` is unlikely to help. [*"The vectorize function is provided primarily for convenience, not for performance. The implementation is essentially a for loop."*](https://docs.scipy.org/doc/numpy/reference/generated/numpy.vectorize.html) – ali_m Dec 15 '16 at 10:53
  • Thanks @ali_m I did not know that at all ! – jeandut Dec 15 '16 at 12:16

1 Answers1

3

There is an alternative vectorized approach using scipy's zoom. However, it is not necessarily faster for small amount of images (e.g. for N=100 a loop might be faster).

>>> from skimage import color, util, data
>>> img = util.img_as_float(color.gray2rgb(data.camera())) # Sample RGB image

I did just replicate a gray-scale image over the RGB channels, so it will still look gray-scale, but it is RGB in practice.

Create 100 RGB images by replicating above RGB image and its horizontal flip (to ensure interpolation is working properly).

>>> data = np.empty((100,) + img.shape, img.dtype)
>>> data[0::2] = img
>>> data[1::2] = img[:,::-1]
>>> plt.imshow(data[50])

enter image description here

Find zooming factors:

>>> from scipy.ndimage import zoom
>>> new_size = (200, 200)
>>> fy, fx = np.asarray(new_size, np.float32) / data.shape[1:3]

Resize image, factor of 1 means no interpolation over that axis:

>>> resized = zoom(data, (1, fy, fx, 1), order=0) # order=0 for quicker
>>> plt.imshow(resized[50]) # resized.shape = (100, 200, 200, 3)

enter image description here

Again, be aware that although it is a vectorized version, it uses NN interpolation in order to be quick, a standard loop + arbitrary interpolation might be way faster. Take this as a proof of concept and have a look if it works for you.

Imanol Luengo
  • 15,366
  • 2
  • 49
  • 67
  • Thanks for your answer ! I upvoted it. I am gonna benchmark it for my implementation and see what comes out. – jeandut Dec 15 '16 at 12:17
  • But I don't really care about the kind of interpolation as long as the images look ok and I have around 500000 images so it might be indeed faster. – jeandut Dec 15 '16 at 12:19
  • I cannot use NN interpolation the artefacts are too important for my application and when I push the order of the spline to 1 there is no speed up. – jeandut Dec 15 '16 at 14:03
  • @jean No problem! Thanks for the feedback, I didn't actually benchmark the approach. – Imanol Luengo Dec 15 '16 at 14:17
  • The fact that it is not faster (or maybe even slower) is because, even if it just does 2D+color interpolation in practice, the function is trying to perform a 4D interpolation. The factor set to `1` prevents those axis from being interpolated, but I'm pressuming it has to do that check every time. Or in other words, N times 2D+color interpolation is better optimized than the above N-D interpolation with constrains. – Imanol Luengo Dec 15 '16 at 14:42