4

I have been trying to test the numpy.gradient function recently. However, it's behavior is little bit strange for me. I have created an array with random variables and then applied the numpy.gradient over it, but the values seems crazy and irrelevant. But when using numpy.diff the values are correct.

So, after viewing the documentation of numpy.gradient, I see that it uses distance=1 over the desired dimension.

This is what I mean:

import numpy as np;

a= np.array([10, 15, 13, 24, 15, 36, 17, 28, 39]);
np.gradient(a)
"""
Got this: array([  5. ,   1.5,   4.5,   1. ,   6. ,   1. ,  -4. ,  11. ,  11. ])
"""
np.diff(a)
"""
Got this:  array([  5,  -2,  11,  -9,  21, -19,  11,  11])
"""

I don't understand how the values in first result came. If the default distance is supposed to be 1, then I should have got the same results as numpy.diff.

Could anyone explain what distance means here. Is it relative to the array index or to the value in the array? If it depends on the value, then does that mean that numpy.gradient could not be used with images since values of neighbor pixels have no fixed value differences?

Hisham Ragheb
  • 144
  • 2
  • 10
  • 3
    You can find worked examples on stack... for example http://stackoverflow.com/questions/24633618/what-does-numpy-gradient-do and there are others if this doesn't work for you –  Aug 07 '16 at 01:08
  • 1
    Take another look at the docstring (http://docs.scipy.org/doc/numpy/reference/generated/numpy.gradient.html). It explains what `gradient` computes. You can read about "central differences" on, for example, wikipedia (https://en.wikipedia.org/wiki/Finite_difference; in particular, https://en.wikipedia.org/wiki/Finite_difference#Forward.2C_backward.2C_and_central_differences). – Warren Weckesser Aug 07 '16 at 01:14

3 Answers3

6
# load image
img = np.array([[21.0, 20.0, 22.0, 24.0, 18.0, 11.0, 23.0],
                [21.0, 20.0, 22.0, 24.0, 18.0, 11.0, 23.0],
                [21.0, 20.0, 22.0, 24.0, 18.0, 11.0, 23.0],
                [21.0, 20.0, 22.0, 99.0, 18.0, 11.0, 23.0],
                [21.0, 20.0, 22.0, 24.0, 18.0, 11.0, 23.0],
                [21.0, 20.0, 22.0, 24.0, 18.0, 11.0, 23.0],
                [21.0, 20.0, 22.0, 24.0, 18.0, 11.0, 23.0]])
print "image =", img

# compute gradient of image
gx, gy = np.gradient(img)
print "gx =", gx
print "gy =", gy

# plotting
plt.close("all")
plt.figure()
plt.suptitle("Image, and it gradient along each axis")
ax = plt.subplot("131")
ax.axis("off")
ax.imshow(img)
ax.set_title("image")

ax = plt.subplot("132")
ax.axis("off")
ax.imshow(gx)
ax.set_title("gx")

ax = plt.subplot("133")
ax.axis("off")
ax.imshow(gy)
ax.set_title("gy")
plt.show()
Walid Bousseta
  • 1,329
  • 2
  • 18
  • 33
  • thanks for your work! wanted to point out that when you save the output of np.gradient(img), I think the order should be gy, gx not gx, gy ! – jun Oct 10 '22 at 02:19
1

For the boundary points, np.gradient uses the formulas

f'(x) = [f(x+h)-f(x)]/h for the left endpoint, and f'(x) = [f(x)-f(x-h)]/h for the right endpoint.

For the interior points, it uses the formula

f'(x) = [f(x+h)-f(x-h)]/2h

The second approach is more accurate - O(h^2) vs O(h). Thus at the second data point, np.gradient estimates the derivative as (13-10)/2 = 1.5.

I made a video explaining the mathematics: https://www.youtube.com/watch?v=NvP7iZhXqJQ

jtlz2
  • 7,700
  • 9
  • 64
  • 114
0

Central differences in the interior and first differences at the boundaries.

15 - 10
13 - 10 / 2
24 - 15 / 2
...
39 - 28
Philipp Braun
  • 1,583
  • 2
  • 25
  • 41