Vision Quest
HoG - Histogram of Gradients
UFO:Detector Test
FAIL
Desert Moon - Sidereal Galaxy Ways
image courtesy of the late
Eddie Takosori
This document has not been classified by the CIDC
nor had it been documented would we be at liberty to disclose said rating
I'm I am the curator Eddie's life work, this photo comes from his personal effects.  Make of it what you will.  
First an image of an embassy.
Something neither the Arturians
(I think that's how it's spelled)
nor the CIDC
(once again, I'm pretty sure that's the correct acronym for the CIDC)
ever want you to see.
So, like, you didn't see it here first (if you know what I mean).
 
C is the Cell size.  Since HoG measures a gradient, the smallest meaningful cell is (2,2).
I found no effect from changes in B (the block size) for any test run.  So variance in B is omitted throughout.
For C=(2,2), there was no difference due to number of slots in the histogram (h=1,h=2,h=4,h=8 omitted).
HoG - Base Test Run
C varies per column
H varies per row
 
 
 
 
Above: Two Histograms per Cell
 
 
 
 
Above: Four Histograms per Cell
 
 
 
 
Above: Eight Histograms per Cell
 
 
 
 
Above: Sixteen Histograms per Cell
 
 
 
 
Above: Thirty Two Histograms per Cell
Same Thing - Larger Cells
 
 
 
 
 
 
 
 
 
c=500 (the column on the far right) is an interesting test condition as one cell takes up the entire image.
HoG - Cell Decomposition
 
Above: One Image
Below: Sixteen Sub-Images
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Color Test
This should be self-explainatory.  But if not, in the following, I plug the histogram return values in for the standard rgb color values.  Thereby, replacing the funky default star graphics of 
from skimage.feature import hog with color.
 
RGB images use three color layers.
If h=3, HoG kicks back three histogram values.
Rocket Science, this is not.
 
 
 
For reference: these are the raw histogram values
Presented counterclockwise, from left-top
columns are [red  green  blue]
x000-y000 [ 0.46650601  0.30661453  0.18926898]
x250-y000 [ 0.31422072  0.4707383   0.20310213]
x250-y250 [ 0.25183926  0.58050045  0.15758351]
x000-y250 [ 0.30955919  0.43543831  0.15302716]
The brightest squares match up with the highest values, so it looks right to me. 
 
This is the combined overlay.
But at this scale, it's not very interesting, so...
 
which when plugged in for color yields
 
which still isn't very interesting, but now that the idea is clear, all we have to do is reduce the cell size to something a little more refined (i.e. a little less granular); and when we plug the histograms in for color, we get:
 
 
The image on the right has been 'stretched' (normalized) to fill the full color gradient from 0.00 to 1.00, but as there's no real difference, I won't bother with that anymore.
The cell size on the above is 5.
Below, it's 2.
 
Base colorized image, h=2.
 
 
Images passed through a low pass filter.
 If color value below 0.25 on left (hogValue < 0.25),
 below 0.33 or right (hogValue < 0.33)
 
 Not stretched, so maybe I there was a reason I included a stretching function...
 
 
Above are the same images stretched (color expanded to fill the full gradient).
There is a lot more action (noticable) action in the air in these images, which is as one might expect, what with the humming of the Van Der Wahl drives and all.
 
 
 
The above are after passing the results through a high pass filter.
Greater than 0.50 (hogValue > 0.50)
Greater than 0.75 (hogValue > 0.75)
Greater than 0.90 (hogValue > 0.90)
from left to right.
And I do believe I will have some pretty gif's of this at the bottom of the page, but first some code.  You do like code, don't you?
HoG (Histogram of Gradients) - Python Code
First, the stretch function.  Nothing fancy.
def stretch(a):
    '''normalizes the values in an array
    from 0.0 to 1.0
    '''
    a = a - numpy.min(a)
    if numpy.max(a) != 0.00:
        a = a / numpy.max(a)
    return a
Everything shown on this page (except for the animated gif's, to follow below) can be derived from judicious use of the following function. 
import numpy
from skimage import io
from skimage.feature import hog
def hogFdTest(img, c=250, nH=3,
               tL=0.00, tH=1.00,
                expand=False):
    '''
        a function to play with
            from skimage.feature import hog
             
        img = a greyscale image array
            io.imread(sN, as_grey=True)
            
        c = cell size = (c,c)
            must be an integer
            2 is the lowest that will work
            up to picture size
            
        nH = numberHistograms
            3 works well if splitting
                to picture bands r,g,b
            as goes higher, grinds to a halt
                takes a lot of time
            as written nH must be 3 or greater
        
        tL and tH together form a band pass
            tL = lowest number to pass
            tH = higherst number to pass
            tL=0.00, tH=1.00
                passes everything
        
        expand if true
            referred to as 'stretch' in text
            renormalizes gradients 
            to range 0.00 - 1.00
            regardless of the band passed
        
        returns
            iO = a numpy image array (w,h,4)
            hV = hog values
                a['name'] = holding name
                a['hog'] = values
                a['xS'] = xStart
                a['xE'] = xEnd
                a['yS'] = yStart
                a['yE'] = yEnd
        
    '''
    print "hogFdTest Starting"
    
    nH = int(nH)
    c = int(c)
    #creating the r,g,b,a holding arrays
    w, h = img.shape
    r = numpy.ndarray((w,h), float)
    g = numpy.ndarray((w,h), float)
    b = numpy.ndarray((w,h), float)
    a = numpy.ones_like(g, float)
    z = numpy.zeros_like(a, float)    
    
    
    #splits image into chuncks
    #based on c=cellSize
    sC = [(x,y) for x in range(0,w,c)
                for y in range(0,h,c)]
    #holding object for fd arrays
    hV=[]
    for x,y in sC:
        
        s = img[x:(x+c),y:(y+c)]
        
        #fd is an array with len(fd)=nH
        fd = hog(s, orientations=nH,
                  pixels_per_cell=(c,c),
                    cells_per_block=(1, 1),
                     visualise=False)   
    
        #creation of return value object
        #fill it with values
        #append to the return array hV
        t = {}
        t['name'] ="xy%s%s" % (nFL(x),nFL(y))
        t['hog'] = fd
        t['xS'] = x
        t['xE'] = x + c
        t['yS'] = y
        t['yE'] = y + c
        hV.append(t)
    
        #first three 
        r[x:(x+c),y:(y+c)] = fd[0]
        g[x:(x+c),y:(y+c)] = fd[1]
        b[x:(x+c),y:(y+c)] = fd[2]
    
    #high pass, passes higher than tL
    r = numpy.where((r>=tL), r, z)
    g = numpy.where((g>=tL), g, z)
    b = numpy.where((b>=tL), b, z)
    
    #low pass, passes lower than tH
    r = numpy.where((r<=tH), r, z)
    g = numpy.where((g<=tH), g, z)
    b = numpy.where((b<=tH), b, z)
    
    #stretched the passed band
    #to fill the full range 0.00 - 1.00
    if expand:
        r = stretch(r)
        g = stretch(g)
        b = stretch(b)
    #assembling 4 (w,h) arrays into one
    #(w,h,4) array RGBA
    iO = numpy.dstack((r,g,b,a))
                      
    sN = "ufo_%s_%f-%f.png" % (nFL(c), tL, tH)
    print "hogFdTest saving %s" % sN
    io.imsave(sN, iO)  
    
    #We'll play with hV in a moment
    return iO,hV  
'''
#Example test code for hogFdTest
#Bandpass filter
for r in range(0,100,10):
    r = r/100.00
    hogFdTest(io.imread(sN, as_grey=True),
              c=2, nH=3, tL=(r), tH=(r+0.10),
              expand=True)
'''
The above includes a hV return value, which the code below plays with a little (but just a little).
def analyzeHOGValues(img):
    d, h500 = hogFdTest(img, c=500)
    d, h250 = hogFdTest(img, c=250)
    d, h125 = hogFdTest(img, c=125)
    print "Sum of Gradients Full Image"
    print "h500 :  " + str(sum(item['hog']
                    for item in h500))
    print "h250 :  " + str(sum(item['hog']
              for item in h250)/len(h250))
    print "h125 :  " + str(sum(item['hog']
              for item in h125)/len(h125))
    print "250 vs 125 Corner Test"
    c = [item['hog'] for item in h250 if
               (item['xE'] <= 250) and
               (item['yE'] <= 250)]
    print "h250 :  " + str(sum(c)/len(c))
    c = [item['hog'] for item in h125 if
              (item['xE'] <= 250) and
              (item['yE'] <= 250)]
    print "h125 :  " + str(sum(c)/len(c))
sN = "./butterfly/png/UFO-500x500.jpg"
img = io.imread(sN, as_grey=True)
The output for the above being:
Sum of Gradients Full Image
h500 :  [ 0.32074886  0.47799351  0.1798315 ]
h250 :  [ 0.33553129  0.4483229   0.17574545]
h125 :  [ 0.26137455  0.42913492  0.12500847]
250 vs 125 Corner Test
h250 :  [ 0.46650601  0.30661453  0.18926898]
h125 :  [ 0.29768439  0.32754795  0.09223276]
Um?
I do believe I read somewhere that one of the reasons HoG got so much play was due to it's resistance to changes in scale.
So, much for that notion.
The above clearly demonstrates either:
A: My utter lack of understanding as to what the HoG gradient values mean, or
B: There is a wide variance based on scale
Do to reasons of Super-Ego-Id Overwhelming-Superiority of My Nature, I choose to believe it is the latter.
HoG Tied - Wrapping It Up
And that's about it.  A few more pretty pictures, maybe a witty commentary or two, and I do believe that will be all.
 
 
 
 
0.10 Bandpass on the Left : 0.25 Bandpass on the right
Split by band in the top row above.
Additive (increasing window size from 0.00-0.10 to 0.00-1.00) underneath.
And then, below, we have the same thing, only cell size is 2 (bandpass top row, additive below).
 
 
And there you have it.  It being, of course, the yellow tri-wing aerial assault vehicles that can be seen hovering in the background once one dials the 'scanner' in to the right frequency.
Obviously, it's all hush-hush, need to know, probably some diplo-corps mission debriefing thingy.  Anyway, we all know who flies around in those 'tri's', so no sense belaboring the point.
The news will hit the Ethers soon enough.
Just remember, you heard it here first.
Or on second thought, I haven't said a thing.
Haven't said enough.
Already said to much.
Or if you want to believe I mess around with these things because I am of fan of graphic art, well, if that's the case, darned if I know what I'm going to do with this new tech.  Maybe I've just been playing with the wrong images...
HoG Color Gradient
Top Secret
CIDC Demo Page
(aka more pretty pictures like these last two)