Ответ 1
Если вам нужен быстрый код Python для функций HOG, я портировал код на Cython: https://github.com/cvondrick/pyvision/blob/master/vision/features.pyx
Я прочитал этот пост о том, как использовать пешеходный детектор на основе HOG на базе OpenCV: Как я могу обнаружить и отслеживать людей с помощью OpenCV?
Я хочу использовать HOG для обнаружения других типов объектов в изображениях (а не только для пешеходов). Однако привязка Python к HOGDetectMultiScale, похоже, не дает доступа к действительным функциям HOG.
Можно ли использовать Python + OpenCV для извлечения функций HOG прямо из любого изображения?
Если вам нужен быстрый код Python для функций HOG, я портировал код на Cython: https://github.com/cvondrick/pyvision/blob/master/vision/features.pyx
В python opencv вы можете вычислить hog следующим образом:
import cv2
hog = cv2.HOGDescriptor()
im = cv2.imread(sample)
h = hog.compute(im)
1. Получить встроенную документацию: Следующая команда на вашей консоли python поможет вам узнать структуру класса HOGDescriptor:
import cv2;
help(cv2.HOGDescriptor())
2. Пример кода: Вот фрагмент кода для инициализации cv2.HOGDescriptor с различными параметрами (термины, которые я использовал здесь, являются стандартными терминами, которые хорошо определены в документации OpenCV здесь):
import cv2
image = cv2.imread("test.jpg",0)
winSize = (64,64)
blockSize = (16,16)
blockStride = (8,8)
cellSize = (8,8)
nbins = 9
derivAperture = 1
winSigma = 4.
histogramNormType = 0
L2HysThreshold = 2.0000000000000001e-01
gammaCorrection = 0
nlevels = 64
hog = cv2.HOGDescriptor(winSize,blockSize,blockStride,cellSize,nbins,derivAperture,winSigma,
histogramNormType,L2HysThreshold,gammaCorrection,nlevels)
#compute(img[, winStride[, padding[, locations]]]) -> descriptors
winStride = (8,8)
padding = (8,8)
locations = ((10,20),)
hist = hog.compute(image,winStride,padding,locations)
3. Рассуждение: Результирующий дескриптор hog будет иметь размерность как: 9 ориентаций X (4 угловых блока, которые получают 1 нормализацию + 6x4 блоков по краям, которые получают 2 нормализации + 6x6 блоков, которые получают 4 нормализации) = 1764. поскольку я дал только одно местоположение для hog.compute().
4. Еще один способ инициализации - это файл xml, содержащий все значения параметров:
hog = cv2.HOGDescriptor("hog.xml")
Чтобы получить файл xml, выполните следующие действия:
hog = cv2.HOGDescriptor()
hog.save("hog.xml")
и отредактируйте соответствующие значения параметров в файле xml.
Вот решение, которое использует только OpenCV:
import numpy as np
import cv2
import matplotlib.pyplot as plt
img = cv2.cvtColor(cv2.imread("/home/me/Downloads/cat.jpg"),
cv2.COLOR_BGR2GRAY)
cell_size = (8, 8) # h x w in pixels
block_size = (2, 2) # h x w in cells
nbins = 9 # number of orientation bins
# winSize is the size of the image cropped to an multiple of the cell size
hog = cv2.HOGDescriptor(_winSize=(img.shape[1] // cell_size[1] * cell_size[1],
img.shape[0] // cell_size[0] * cell_size[0]),
_blockSize=(block_size[1] * cell_size[1],
block_size[0] * cell_size[0]),
_blockStride=(cell_size[1], cell_size[0]),
_cellSize=(cell_size[1], cell_size[0]),
_nbins=nbins)
n_cells = (img.shape[0] // cell_size[0], img.shape[1] // cell_size[1])
hog_feats = hog.compute(img)\
.reshape(n_cells[1] - block_size[1] + 1,
n_cells[0] - block_size[0] + 1,
block_size[0], block_size[1], nbins) \
.transpose((1, 0, 2, 3, 4)) # index blocks by rows first
# hog_feats now contains the gradient amplitudes for each direction,
# for each cell of its group for each group. Indexing is by rows then columns.
gradients = np.zeros((n_cells[0], n_cells[1], nbins))
# count cells (border cells appear less often across overlapping groups)
cell_count = np.full((n_cells[0], n_cells[1], 1), 0, dtype=int)
for off_y in range(block_size[0]):
for off_x in range(block_size[1]):
gradients[off_y:n_cells[0] - block_size[0] + off_y + 1,
off_x:n_cells[1] - block_size[1] + off_x + 1] += \
hog_feats[:, :, off_y, off_x, :]
cell_count[off_y:n_cells[0] - block_size[0] + off_y + 1,
off_x:n_cells[1] - block_size[1] + off_x + 1] += 1
# Average gradients
gradients /= cell_count
# Preview
plt.figure()
plt.imshow(img, cmap='gray')
plt.show()
bin = 5 # angle is 360 / nbins * direction
plt.pcolor(gradients[:, :, bin])
plt.gca().invert_yaxis()
plt.gca().set_aspect('equal', adjustable='box')
plt.colorbar()
plt.show()
Я использовал вычисление и визуализацию дескриптора HOG, чтобы понять расположение данных и векторизовать петли над группами.
Несмотря на то, что существует метод, как сказано в предыдущих ответах:
hog = cv2.HOGDescriptor()
Я хотел бы опубликовать реализацию python, которую вы можете найти в каталоге примеров opencv, надеясь, что может быть полезно понять функциональность HOG:
def hog(img):
gx = cv2.Sobel(img, cv2.CV_32F, 1, 0)
gy = cv2.Sobel(img, cv2.CV_32F, 0, 1)
mag, ang = cv2.cartToPolar(gx, gy)
bin_n = 16 # Number of bins
bin = np.int32(bin_n*ang/(2*np.pi))
bin_cells = []
mag_cells = []
cellx = celly = 8
for i in range(0,img.shape[0]/celly):
for j in range(0,img.shape[1]/cellx):
bin_cells.append(bin[i*celly : i*celly+celly, j*cellx : j*cellx+cellx])
mag_cells.append(mag[i*celly : i*celly+celly, j*cellx : j*cellx+cellx])
hists = [np.bincount(b.ravel(), m.ravel(), bin_n) for b, m in zip(bin_cells, mag_cells)]
hist = np.hstack(hists)
# transform to Hellinger kernel
eps = 1e-7
hist /= hist.sum() + eps
hist = np.sqrt(hist)
hist /= norm(hist) + eps
return hist
С уважением.
Я бы не согласился с аргументом peakxu. В конце концов детектор HOG является "просто" жестким линейным фильтром. любые степени свободы в "объекте" (то есть лица) приводят к размытию в детекторе и фактически не обрабатываются им. Существует расширение этого детектора с использованием скрытых SVM, которые явно обрабатывают dgrees свободы, вводя структурные ограничения между независимыми частями (например, головой, оружием и т.д.), А также допускают множественные проявления на объект (то есть лобовые люди и боковые люди...).
Относительно детектора HOG в opencv: в теории вы можете загрузить еще один детектор, который будет использоваться с функциями, но вы не можете самим использовать функции. таким образом, если у вас есть обученный детектор (т.е. линейный фильтр, специфичный для класса), вы должны иметь возможность загрузить его в детектор, чтобы получить быстрое обнаружение opencv. что было бы легко взломать исходный код opencv, чтобы обеспечить этот доступ и предложить этот патч для сопровождающих.
Я бы не рекомендовал использовать функции HOG для обнаружения объектов, отличных от пешеходов. В оригинальной HOG-бумаге Далала и Триггса они специально упоминали, что их детектор построен вокруг обнаружения пешеходов, позволяя значительную степень свободы в конечностях при использовании сильных структурных подсказок вокруг человеческого тела.
Вместо этого попробуйте взглянуть на OpenCV HaarDetectObjects. Вы можете узнать, как тренировать свои собственные каскады здесь.