1

I am trying to extract hog descriptors for some ROI on a given image (2D) using the implementation in skimage.feature. I have attached some samples of the ROI that I have extracted. I am just using the hog descriptor with all the default values.

Configuration: python:3.9.13; scikit-image: 0.19.2; Windows 10

The feature vector that is returned has nothing i.e. it is a null array ([]).

NOTE: I want to use the HOG descriptors from positive and negative sample to train and Linear SVM model.

Sample ROI positive sample negative sample

Code to reproduce problem

from skimage.feature import hog
import cv2 as cv
img = cv.imread(<path to image>, cv.IMREAD_GRAYSCALE)
desc = hog(img)
print(desc)

#output: array([], dtype=float64)

The feature descriptor should not be null. Even if I am giving a completely blank white image there should be a descriptor. But again I am not getting a descriptor for the positive samples as well.

Can someone please help with what is going wrong or is it an issue with the implementation?

Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
tintin98
  • 91
  • 9
  • Actually I just checked that you can apply the hog on the images that I have attached after reading it using opencv imread in grayscale mode and reproduce the problem. – tintin98 Jul 13 '23 at 16:50
  • Done. Thanks for guiding me. – tintin98 Jul 13 '23 at 17:43
  • This is really surprising. To me this looks like a bug. If the input is too small for the operation, it should error out, not produce an empty array. I’ll have to check the source code to understand what is going on. – Cris Luengo Jul 13 '23 at 19:03
  • I've submitted an issue to the skimage project: https://github.com/scikit-image/scikit-image/issues/7064#issue-1803707400 – Cris Luengo Jul 13 '23 at 20:20
  • Great. Thanks a lot. – tintin98 Jul 13 '23 at 20:29

1 Answers1

1

I referenced the source code

It looks like it produces output for n_blocks_rowxn_blocks_col elements, with:

s_row, s_col = image.shape[:2]
c_row, c_col = pixels_per_cell  # input parameter, 8x8 by default
b_row, b_col = cells_per_block  # input parameter, 3x3 by default

n_cells_row = int(s_row // c_row)  # number of cells along row-axis
n_cells_col = int(s_col // c_col)  # number of cells along col-axis

n_blocks_row = (n_cells_row - b_row) + 1
n_blocks_col = (n_cells_col - b_col) + 1

With the image having only 16 rows, you get two cells vertically, which is not enough to fill a single block of 3x3 cells. So, n_blocks_row is 0, and you get as output a 0x22 array of blocks.

For such small images, you must change the pixels_per_cell and/or the cells_per_block parameters so that pixels_per_cell[0] * cells_per_block[0] is not larger than your image height (and similarly for the image width).

For example, this worked for me:

skimage.feature.hog(img, cells_per_block=(2,2))

though I don't know if this produces a useful output or not. Having fewer cells per block might not give you as good a result. Maybe you could make the blocks wider as you make them less tall, so their size remains the same? Something like cells_per_block=(2,5)? I don't have enough experience with HOG to advice on this.

Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
  • Thanks for the help. An exception should have been raised. As for the "cells_per_block = (2,5)" for sure it can be done (main reason being it is allowed). Also in HOG these are just aggregating information upwards (in order) pixel -> cell -> block -> histogram and then other steps follow. – tintin98 Jul 13 '23 at 20:28