/skimage/feature/tests/test_hog.py

https://github.com/neurodebian/scikits.image-1
Python | 142 lines | 80 code | 31 blank | 31 comment | 8 complexity | 92f029d83efcd1adbb975e24c705c6c1 MD5 | raw file
  1. import numpy as np
  2. from scipy import ndimage
  3. from skimage import data
  4. from skimage import feature
  5. from skimage import img_as_float
  6. from skimage import draw
  7. from numpy.testing import (assert_raises,
  8. assert_almost_equal,
  9. )
  10. def test_histogram_of_oriented_gradients():
  11. img = img_as_float(data.lena()[:256, :].mean(axis=2))
  12. fd = feature.hog(img, orientations=9, pixels_per_cell=(8, 8),
  13. cells_per_block=(1, 1))
  14. assert len(fd) == 9 * (256 // 8) * (512 // 8)
  15. def test_hog_image_size_cell_size_mismatch():
  16. image = data.camera()[:150, :200]
  17. fd = feature.hog(image, orientations=9, pixels_per_cell=(8, 8),
  18. cells_per_block=(1, 1))
  19. assert len(fd) == 9 * (150 // 8) * (200 // 8)
  20. def test_hog_color_image_unsupported_error():
  21. image = np.zeros((20, 20, 3))
  22. assert_raises(ValueError, feature.hog, image)
  23. def test_hog_basic_orientations_and_data_types():
  24. # scenario:
  25. # 1) create image (with float values) where upper half is filled by zeros, bottom half by 100
  26. # 2) create unsigned integer version of this image
  27. # 3) calculate feature.hog() for both images, both with 'normalise' option enabled and disabled
  28. # 4) verify that all results are equal where expected
  29. # 5) verify that computed feature vector is as expected
  30. # 6) repeat the scenario for 90, 180 and 270 degrees rotated images
  31. # size of testing image
  32. width = height = 35
  33. image0 = np.zeros((height, width), dtype='float')
  34. image0[height / 2:] = 100
  35. for rot in range(4):
  36. # rotate by 0, 90, 180 and 270 degrees
  37. image_float = np.rot90(image0, rot)
  38. # create uint8 image from image_float
  39. image_uint8 = image_float.astype('uint8')
  40. (hog_float, hog_img_float) = feature.hog(image_float, orientations=4, pixels_per_cell=(8, 8),
  41. cells_per_block=(1, 1), visualise=True, normalise=False)
  42. (hog_uint8, hog_img_uint8) = feature.hog(image_uint8, orientations=4, pixels_per_cell=(8, 8),
  43. cells_per_block=(1, 1), visualise=True, normalise=False)
  44. (hog_float_norm, hog_img_float_norm) = feature.hog(image_float, orientations=4, pixels_per_cell=(8, 8),
  45. cells_per_block=(1, 1), visualise=True, normalise=True)
  46. (hog_uint8_norm, hog_img_uint8_norm) = feature.hog(image_uint8, orientations=4, pixels_per_cell=(8, 8),
  47. cells_per_block=(1, 1), visualise=True, normalise=True)
  48. # set to True to enable manual debugging with graphical output,
  49. # must be False for automatic testing
  50. if False:
  51. import matplotlib.pyplot as plt
  52. plt.figure()
  53. plt.subplot(2, 3, 1); plt.imshow(image_float); plt.colorbar(); plt.title('image')
  54. plt.subplot(2, 3, 2); plt.imshow(hog_img_float); plt.colorbar(); plt.title('HOG result visualisation (float img)')
  55. plt.subplot(2, 3, 5); plt.imshow(hog_img_uint8); plt.colorbar(); plt.title('HOG result visualisation (uint8 img)')
  56. plt.subplot(2, 3, 3); plt.imshow(hog_img_float_norm); plt.colorbar(); plt.title('HOG result (normalise) visualisation (float img)')
  57. plt.subplot(2, 3, 6); plt.imshow(hog_img_uint8_norm); plt.colorbar(); plt.title('HOG result (normalise) visualisation (uint8 img)')
  58. plt.show()
  59. # results (features and visualisation) for float and uint8 images must be almost equal
  60. assert_almost_equal(hog_float, hog_uint8)
  61. assert_almost_equal(hog_img_float, hog_img_uint8)
  62. # resulting features should be almost equal when 'normalise' is enabled or disabled (for current simple testing image)
  63. assert_almost_equal(hog_float, hog_float_norm, decimal=4)
  64. assert_almost_equal(hog_float, hog_uint8_norm, decimal=4)
  65. # reshape resulting feature vector to matrix with 4 columns (each corresponding to one of 4 directions),
  66. # only one direction should contain nonzero values (this is manually determined for testing image)
  67. actual = np.max(hog_float.reshape(-1, 4), axis=0)
  68. if rot in [0, 2]:
  69. # image is rotated by 0 and 180 degrees
  70. desired = [0, 0, 1, 0]
  71. elif rot in [1, 3]:
  72. # image is rotated by 90 and 270 degrees
  73. desired = [1, 0, 0, 0]
  74. else:
  75. raise Exception('Result is not determined for this rotation.')
  76. assert_almost_equal(actual, desired, decimal=2)
  77. def test_hog_orientations_circle():
  78. # scenario:
  79. # 1) create image with blurred circle in the middle
  80. # 2) calculate feature.hog()
  81. # 3) verify that the resulting feature vector contains uniformly distributed values for all orientations,
  82. # i.e. no orientation is lost or emphasized
  83. # 4) repeat the scenario for other 'orientations' option
  84. # size of testing image
  85. width = height = 100
  86. image = np.zeros((height, width))
  87. rr, cc = draw.circle(int(height / 2), int(width / 2), int(width / 3))
  88. image[rr, cc] = 100
  89. image = ndimage.gaussian_filter(image, 2)
  90. for orientations in range(2, 15):
  91. (hog, hog_img) = feature.hog(image, orientations=orientations, pixels_per_cell=(8, 8),
  92. cells_per_block=(1, 1), visualise=True, normalise=False)
  93. # set to True to enable manual debugging with graphical output,
  94. # must be False for automatic testing
  95. if False:
  96. import matplotlib.pyplot as plt
  97. plt.figure()
  98. plt.subplot(1, 2, 1); plt.imshow(image); plt.colorbar(); plt.title('image_float')
  99. plt.subplot(1, 2, 2); plt.imshow(hog_img); plt.colorbar(); plt.title('HOG result visualisation, orientations=%d' % (orientations))
  100. plt.show()
  101. # reshape resulting feature vector to matrix with N columns (each column corresponds to one direction),
  102. hog_matrix = hog.reshape(-1, orientations)
  103. # compute mean values in the resulting feature vector for each direction,
  104. # these values should be almost equal to the global mean value (since the image contains a circle),
  105. # i.e. all directions have same contribution to the result
  106. actual = np.mean(hog_matrix, axis=0)
  107. desired = np.mean(hog_matrix)
  108. assert_almost_equal(actual, desired, decimal=1)
  109. if __name__ == '__main__':
  110. from numpy.testing import run_module_suite
  111. run_module_suite()