I have the following code to compute HOG image with 8 bins and pre-counted Sobel X and Y filtered image:
for y in xrange(0, 480):
for x in xrange(0, 640):
base_angle = np.arctan2(sobel_Y[y,x], sobel_X[y,x]) * 180/np.pi
if base_angle < 0: base_angle += 360
angle = int(round(base_angle / 45))
if angle == 8: angle = 0
hog[y,x,angle] += np.sqrt(sobel_X[y,x]**2 + sobel_Y[y,x]**2)
I was trying to modify it to avoid loops:
base_angle = np.arctan2(sobel_Y, sobel_X) * 180/np.pi
base_angle[base_angle < 0] += 360
angle =(base_angle / 45).round().astype(np.uint8)
angle[angle == bins] = 0
hog[:,:,angle] += np.sqrt(sobel_X**2 + sobel_Y**2)
However, the last expression does not count correctly. What I basically need is to have the magnitude (np.sqrt... expression) being added to hog array according to index from angle array, at every (y,x) point of hog array. Any solutions?
Use
magnitude = np.sqrt(sobel_X**2 + sobel_Y**2)
Y, X = np.ogrid[0:angle.shape[0], 0:angle.shape[1]]
hog[Y, X, angle] += magnitude
to update hog.
import numpy as np
def using_for_loop(hog, sobel_Y, sobel_X):
for y in xrange(0, sobel_Y.shape[0]):
for x in xrange(0, sobel_X.shape[1]):
base_angle = np.arctan2(sobel_Y[y, x], sobel_X[y, x]) * 180 / np.pi
if base_angle < 0:
base_angle += 360
angle = int(round(base_angle / 45))
if angle == 8:
angle = 0
hog[y, x, angle] += np.sqrt(sobel_X[y, x] ** 2 +
sobel_Y[y, x] ** 2)
return hog
def using_indexing(hog, sobel_Y, sobel_X):
base_angle = np.arctan2(sobel_Y, sobel_X) * 180 / np.pi
base_angle[base_angle < 0] += 360
angle = (base_angle / 45).round().astype(np.uint8)
angle[angle == bins] = 0
magnitude = np.sqrt(sobel_X ** 2 + sobel_Y ** 2)
Y, X = np.ogrid[0:angle.shape[0], 0:angle.shape[1]]
hog[Y, X, angle] += magnitude
return hog
bins = 8
sobel_Y, sobel_X = np.meshgrid([1, 2, 3], [4, 5, 6, 7])
# hog = np.zeros(sobel_X.shape + (bins,))
hog = np.random.random(sobel_X.shape + (bins,))
answer = using_for_loop(hog, sobel_Y, sobel_X)
result = using_indexing(hog, sobel_Y, sobel_X)
assert np.allclose(answer, result)
Note that if
In [62]: angle.shape
Out[62]: (4, 3)
then
In [74]: hog[:,:,angle].shape
Out[74]: (4, 3, 4, 3)
That's not the right shape. Rather, if you define
In [75]: Y, X = np.ogrid[0:angle.shape[0], 0:angle.shape[1]]
then hog[Y, X, angle] has the same shape as magnitude:
In [76]: hog[Y, X, angle].shape
Out[76]: (4, 3)
In [77]: magnitude = np.sqrt(sobel_X ** 2 + sobel_Y ** 2)
In [78]: magnitude.shape
Out[78]: (4, 3)
Of course, that is not a proof that hog[Y, X, angle] is the correct expression, but it is the equivalent of a physicist's dimensionality check which shows we at least could be on the right track.
With NumPy fancy indexing, when Y, X, and angle all have the same shape (or broadcast to the same shape),
hog[Y, X, angle]
will also be of the same shape. The (i,j)th element in hog[Y, X, angle] will equal
hog[Y[i,j], X[i,j], angle[i,j]]
This is why hog[Y, X, angle] += magnitude works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With