HOG wiki
HOG(梯度方向直方图)可以用来检测物体的轮廓,对于我们识别一个目标物体是非常有用的。
HOG 的计算通过以下步骤实现:
1. (可选的) 对图像做全局的归一化 (normalisation)
2. 像素在计算 x 和 y 轴上的梯度
3. 计算在一个 cell 级别上的 梯度直方图 (gradient histograms)
4. 在 block 级别做归一化 (normalization)
5. 展开成为一个特征向量 (feature vector)
第一步的归一化,可以去除光照强度对图像的影响。
第二步用来计算像素的一阶导数(梯度),能够探测到物体的轮廓、纹理以及文字等信息。
也可以采用二阶的导数,这样就能够探测到一个条状的物体,比如自行车上面的辐条、人的四肢等。
第三步把局部的梯度方向信息投影到直方图的 bin 区间,图形被划分成一个个的 cell 大小,统计每个 cell 内做直方图分布。
我们还考虑梯度的大小用来产生直方图。
第四步利用周围的 block 级别的区域(每个 block 往往包含了多个 cell)进行归一化。
每一个cell 的归一化因子是它周围的cell 组成的block的值,所以会发现在每个cell 会归到不同的block 中去计算,多有重复。
不过 block 级别的normalization 有助于去除光照强度、阴影等对目标检测的影响。
第五步我们需要把生成的 HOG 数据展开成一个向量作为分类器的输入。
这也是
Dalal, N. and Triggs, B., 在 “Histograms of Oriented Gradients for Human Detection,” IEEE Computer Society Conference on Computer Vision and Pattern Recognition, 2005, San Diego, CA, USA. 当中的算法。
skimage 提供了 hog 的接口,让我们能够很容易的调用。
skimage hog
skimage.feature.hog(img, orientations = 9, pixels_per_cell = (8, 8), cells_per_block = (3, 3), block_norm = None, visualize = False, visualise = None, transform_sqrt = False, feature_vector = True, multichannel = None)
import matplotlib.pyplot as plt from skimage.feature import hog from skimage import data, exposure image = data.astronaut()[:,:,0] print('image shape = ', image.shape) fd, hog_image = hog(image, orientations=8, pixels_per_cell=(16, 16), cells_per_block=(2, 2), visualise =True) print('fd shape = ', fd.shape) fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4), sharex=True, sharey=True) ax1.axis('off') ax1.imshow(image, cmap=plt.cm.gray) ax1.set_title('Input image') # Rescale histogram for better display hog_image_rescaled = exposure.rescale_intensity(hog_image, in_range=(0, 10)) ax2.axis('off') ax2.imshow(hog_image_rescaled, cmap=plt.cm.gray) ax2.set_title('Histogram of Oriented Gradients') plt.show()
imgcpy = np.copy(img) for window in windows: (x1, y1), (x2, y2) = window imgcpy[x1:x2][y1:y2] += 1 heatmap = np.copy(imgcpy) heatmap[imgcpy < threshold] = 0
from scipy.ndimage.measurements import label labels = label(heatmap) # labels[0] is the labeld object map # labels[1] is the object count obj_cnt = labels[1] for obj_idx in range(1, obj_cnt +1): nonzero = (labels[0] == obj_idx).nonzero() nonzeroy = np.array(nonzero[0]) nonzerox = np.array(nonzero[1]) bbox = ((np.min(nonzerox), np.min(nonzeroy)), (np.max(nonzerox), np.max(nonzeroy))) cv2.rectangle(img, bbox[0], bbox[1], (0,0,255), 6)