Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Image Gradient Vector Field in Python

I am trying to get the Gradient Vector Field of an image using Python (similar to this matlab question).

This is the original image: http:/ /dcc.fceia.unr.edu.ar/~rbaravalle/gradient/test.png

Here is my code:

import numpy as np
import matplotlib.pyplot as plt
import Image
from PIL import ImageFilter

I = Image.open('test.png').transpose(Image.FLIP_TOP_BOTTOM)
I = I.filter(ImageFilter.BLUR)
p = np.asarray(I)
w,h = I.size
y, x = np.mgrid[0:h:500j, 0:w:500j]

dy, dx = np.gradient(p)
skip = (slice(None, None, 3), slice(None, None, 3))

fig, ax = plt.subplots()
im = ax.imshow(I, extent=[x.min(), x.max(), y.min(), y.max()])
ax.quiver(x[skip], y[skip], dx[skip], dy[skip])

ax.set(aspect=1, title='Quiver Plot')
plt.show()

This is the result: http://dcc.fceia.unr.edu.ar/~rbaravalle/gradient/result.png

The problem is that the vectors seem to be incorrect. This point gets more clear when you zoom in the image:

http://dcc.fceia.unr.edu.ar/~rbaravalle/gradient/result2.png

Why do some of the vectors point to the center as expected, while others do not?

Maybe there is an issue with the result of the call to np.gradient?

like image 728
Rodrigo Baravalle Avatar asked May 06 '15 14:05

Rodrigo Baravalle


People also ask

How do you find the gradient of a vector in Python?

We will use numdifftools to find Gradient of a function. Examples: Input : x^4+x+1 Output :Gradient of x^4+x+1 at x=1 is 4.99 Input :(1-x)^2+(y-x^2)^2 Output :Gradient of (1-x^2)+(y-x^2)^2 at (1, 2) is [-4.

How do you find the gradient of an image in Python?

We can find the gradient of an image by the help of Sobel and Laplacian derivatives of the image. Sobel is used for either X or Y direction or even in combined form while Laplacian help in both directions. Don't worry about the mathematical calculation of the image.

How do you find the gradient of a vector image?

You can compute the gradient by subtracting left from right or right from left, you just have to be consistent across the image. 93 - 55 = 38 in the y-direction. Putting these two values together, we now have our gradient vector.


1 Answers

I think your strange results are, at least in part, because p is of type uint8. Even numpy diff results in clearly incorrect values for an array of this dtype. If you convert to signed integer by replacing the definition of p with the following: p = np.asarray(I).astype(int8) then the results of diff are correct. The following code gives me what looks like a reasonable field,

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
from PIL import ImageFilter

I = Image.open('./test.png')
I = I.filter(ImageFilter.BLUR)
p = np.asarray(I).astype('int8')
w,h = I.size
x, y = np.mgrid[0:h:500j, 0:w:500j]

dy, dx = np.gradient(p)
skip = (slice(None, None, 3), slice(None, None, 3))

fig, ax = plt.subplots()
im = ax.imshow(I.transpose(Image.FLIP_TOP_BOTTOM), 
               extent=[x.min(), x.max(), y.min(), y.max()])
plt.colorbar(im)
ax.quiver(x[skip], y[skip], dx[skip].T, dy[skip].T)

ax.set(aspect=1, title='Quiver Plot')
plt.show()

This gives the following:

Solution

and close up this looks like you'd expect,

enter image description here

like image 174
Ed Smith Avatar answered Sep 20 '22 16:09

Ed Smith