如何从OpenCV和Python中获取HOG图像特征?

41 投票
6 回答
108822 浏览
提问于 2025-04-16 18:08

我看过一篇关于如何使用OpenCV的HOG行人检测器的帖子: 我该如何使用OpenCV检测和跟踪人?

我想用HOG来检测图像中的其他类型物体(不仅仅是行人)。但是,Python中HOGDetectMultiScale的绑定似乎无法直接访问实际的HOG特征。

有没有办法用Python和OpenCV直接从任何图像中提取HOG特征?

6 个回答

18

这里有一个只用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描述符的计算和可视化来理解数据的布局,并对循环进行了向量化处理。

47

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 文件中编辑相应的参数值。

169

在Python的OpenCV库中,你可以这样计算HOG特征:

 import cv2
 hog = cv2.HOGDescriptor()
 im = cv2.imread(sample)
 h = hog.compute(im)

撰写回答