sightmachine / SimpleCV

The Open Source Framework for Machine Vision
http://simplecv.org
BSD 3-Clause "New" or "Revised" License
2.68k stars 798 forks source link

Added findHOGFeatures() #607

Open lastlegion opened 10 years ago

lastlegion commented 10 years ago

HOG(Histogram of Oriented Gradients) features are widely used in various Computer Vision and image processing for object detection.

Usage

I = Image("lena.jpg")
H1 = I.findHOGFeatures()
H2 = I.findHOGFeatures(2,6)

For sample image: lena_color It would return the hog descriptor:

>H1
array([[ 0.70799777,  0.31031786,  0.43538802,  0.7119953 ,  0.35283551,
         0.44640515,  1.39636142,  0.66822192,  0.9737663 ,  1.35927688,
         0.61152601,  1.03855733,  1.69911792,  0.62897737,  1.92188941,
         1.67472578,  0.63001834,  1.99064839,  0.84245818,  0.80247882,
         0.79771883,  0.65534026,  0.76592214,  0.7464986 ,  1.95349545,
         0.73081933,  1.0270115 ,  1.88424318,  0.86515135,  1.01216288,
         0.79783098,  0.63841941,  0.56898374,  0.72427718,  0.6168658 ,
         0.72017109,  0.89275505,  0.46247547,  0.58670203,  0.93734243,
         0.41994468,  0.51827528,  0.95650341,  0.39389738,  0.71125951,
         0.83805511,  0.4436618 ,  0.74813277,  0.97483522,  0.36429496,
         0.8730933 ,  0.93598927,  0.48391781,  0.61659925]])
>H2
array([[ 2.3547329 ,  1.24260293,  1.34765038,  2.16142711,  1.28855857,
         1.59244553,  3.73639567,  1.53089352,  3.16332987,  3.63308637,
         1.47675359,  3.25464767,  2.11491471,  1.1703252 ,  1.68901189,
         2.11247633,  1.32217436,  1.43717833,  2.09424087,  1.08864922,
         1.72708496,  1.89273196,  1.13458106,  1.58801289]])
lastlegion commented 10 years ago

Thanks Louis for your inputs. I have updated the code to improve the performance.

louist87 commented 10 years ago

@lastlegion I did a bit of digging around codereview.stackexchange.com and got some help vectorizing your function. This new version clocks in at 49.5 ms total execution time, or about 88 times faster than the original iterative version. You can find stack exchange post here.

A few notes about the changes (mostly copied, pasted, & adapted from Gareth Rees' answer):

  1. used % (2 * pi) to get the angles in the range [0, 2π). An alternative that's more like your code would be angles[angles < 0] += 2 * pi but using the modulus is shorter and, I think, clearer.
  2. postponed the division by img_area until after the summation, because it looks to me as though in the common case n_HOG is much less than img_area and so it's cheaper to do the division later when there are fewer items. (This means that the results differ very slightly from your code, so bear that in mind when checking.)
  3. wrote angles[...,0] and magnit[...,0] here in order to drop the third axis. But I think it would make more sense if you dropped this axis earlier, before computing angles and magnit, by writing Ix = Ix[...,0] or just Ix = Ix.reshape((height, width)) if you know that the last axis has length 1.

Anyway, the code can be found in this gist.

If you don't feel like amending your pull request, I'll be happy to file one on my end. Thanks again for your very helpful contributions! I hope your request will be merged soon!