Merge pull request #1783 from ivoflipse/fix_hog

Fixing Cythonized version of HOG
This commit is contained in:
Emmanuelle Gouillart
2015-12-19 17:37:24 +01:00
4 changed files with 48 additions and 20 deletions
Binary file not shown.
+11 -6
View File
@@ -5,7 +5,8 @@ from . import _hoghistogram
def hog(image, orientations=9, pixels_per_cell=(8, 8),
cells_per_block=(3, 3), visualise=False, normalise=False):
cells_per_block=(3, 3), visualise=False, normalise=False,
feature_vector=True):
"""Extract Histogram of Oriented Gradients (HOG) for a given image.
Compute a Histogram of Oriented Gradients (HOG) by
@@ -31,6 +32,9 @@ def hog(image, orientations=9, pixels_per_cell=(8, 8),
normalise : bool, optional
Apply power law compression to normalise the image before
processing.
feature_vector : bool, optional
Return the data as a feature vector by calling .ravel() on the result
just before returning.
Returns
-------
@@ -127,13 +131,11 @@ def hog(image, orientations=9, pixels_per_cell=(8, 8),
orientations_arr = np.arange(orientations)
dx_arr = radius * np.cos(orientations_arr / orientations * np.pi)
dy_arr = radius * np.sin(orientations_arr / orientations * np.pi)
cr2 = cy + cy
cc2 = cx + cx
hog_image = np.zeros((sy, sx), dtype=float)
for x in range(n_cellsx):
for y in range(n_cellsy):
for o, dx, dy in zip(orientations_arr, dx_arr, dy_arr):
centre = tuple([y * cr2 // 2, x * cc2 // 2])
centre = tuple([y * cy + cy // 2, x * cx + cx // 2])
rr, cc = draw.line(int(centre[0] - dx),
int(centre[1] + dy),
int(centre[0] + dx),
@@ -171,8 +173,11 @@ def hog(image, orientations=9, pixels_per_cell=(8, 8),
overlapping grid of blocks covering the detection window into a combined
feature vector for use in the window classifier.
"""
if feature_vector:
normalised_blocks = normalised_blocks.ravel()
if visualise:
return normalised_blocks.ravel(), hog_image
return normalised_blocks, hog_image
else:
return normalised_blocks.ravel()
return normalised_blocks
+23 -13
View File
@@ -10,7 +10,9 @@ cdef float cell_hog(double[:, ::1] magnitude,
float orientation_start, float orientation_end,
int cell_columns, int cell_rows,
int column_index, int row_index,
int size_columns, int size_rows) nogil:
int size_columns, int size_rows,
int range_rows_start, int range_rows_stop,
int range_columns_start, int range_columns_stop) nogil:
"""Calculation of the cell's HOG value
Parameters
@@ -35,22 +37,23 @@ cdef float cell_hog(double[:, ::1] magnitude,
Number of columns.
size_rows : int
Number of rows.
range_rows_start : int
Start row of cell.
range_rows_stop : int
Stop row of cell.
range_columns_start : int
Start column of cell.
range_columns_stop : int
Stop column of cell
Returns
-------
total : float
The total HOG value.
"""
cdef int cell_column, cell_row, cell_row_index, cell_column_index, \
range_columns_start, range_columns_stop, range_rows_start, \
range_rows_stop
range_rows_stop = cell_rows/2
range_rows_start = -range_rows_stop
range_columns_stop = cell_columns/2
range_columns_start = -range_columns_stop
cdef int cell_column, cell_row, cell_row_index, cell_column_index
cdef float total = 0.
for cell_row in range(range_rows_start, range_rows_stop):
cell_row_index = row_index + cell_row
if (cell_row_index < 0 or cell_row_index >= size_rows):
@@ -67,7 +70,7 @@ cdef float cell_hog(double[:, ::1] magnitude,
total += magnitude[cell_row_index, cell_column_index]
return total
return total / (cell_rows * cell_columns)
def hog_histograms(double[:, ::1] gradient_columns,
double[:, ::1] gradient_rows,
@@ -106,7 +109,9 @@ def hog_histograms(double[:, ::1] gradient_columns,
gradient_rows)
cdef double[:, ::1] orientation = \
np.arctan2(gradient_rows, gradient_columns) * (180 / np.pi) % 180
cdef int i, x, y, o, yi, xi, cc, cr, x0, y0
cdef int i, x, y, o, yi, xi, cc, cr, x0, y0, \
range_rows_start, range_rows_stop, \
range_columns_start, range_columns_stop
cdef float orientation_start, orientation_end, \
number_of_orientations_per_180
@@ -115,6 +120,10 @@ def hog_histograms(double[:, ::1] gradient_columns,
cc = cell_rows * number_of_cells_rows
cr = cell_columns * number_of_cells_columns
number_of_orientations_per_180 = 180. / number_of_orientations
range_rows_stop = cell_rows/2
range_rows_start = -range_rows_stop
range_columns_stop = cell_columns/2
range_columns_start = -range_columns_stop
with nogil:
# compute orientations integral images
@@ -134,7 +143,8 @@ def hog_histograms(double[:, ::1] gradient_columns,
while x < cr:
orientation_histogram[yi, xi, i] = cell_hog(magnitude,
orientation, orientation_start, orientation_end,
cell_columns, cell_rows, x, y, size_columns, size_rows)
cell_columns, cell_rows, x, y, size_columns, size_rows,
range_rows_start, range_rows_stop, range_columns_start, range_columns_stop)
xi += 1
x += cell_columns
+14 -1
View File
@@ -1,5 +1,7 @@
import os
import numpy as np
from scipy import ndimage as ndi
import skimage as si
from skimage import data
from skimage import feature
from skimage import img_as_float
@@ -9,7 +11,7 @@ from numpy.testing import (assert_raises,
)
def test_histogram_of_oriented_gradients():
def test_histogram_of_oriented_gradients_output_size():
img = img_as_float(data.astronaut()[:256, :].mean(axis=2))
fd = feature.hog(img, orientations=9, pixels_per_cell=(8, 8),
@@ -18,6 +20,17 @@ def test_histogram_of_oriented_gradients():
assert len(fd) == 9 * (256 // 8) * (512 // 8)
def test_histogram_of_oriented_gradients_output_correctness():
img = np.load(os.path.join(si.data_dir, 'lena_GRAY_U8.npy'))
correct_output = np.load(os.path.join(si.data_dir, 'lena_GRAY_U8_hog.npy'))
output = feature.hog(img, orientations=9, pixels_per_cell=(8, 8),
cells_per_block=(3, 3), feature_vector=True,
normalise=False, visualise=False)
assert_almost_equal(output, correct_output)
def test_hog_image_size_cell_size_mismatch():
image = data.camera()[:150, :200]
fd = feature.hog(image, orientations=9, pixels_per_cell=(8, 8),