计算 HOG(Histogram of Oriented Gradients,方向梯度直方图)算子的典型 MATLAB 程序。这个实现遵循 Dalal & Triggs 2005 的经典 CVPR 论文 流程,结构清晰、参数可调
一、HOG 计算流程
- 灰度化
- Gamma 校正(可选)
- 计算梯度(x/y 方向)
- 构建 Cell(如 8×8 像素)内的方向直方图(9 bins,0°~180°)
- Block 归一化(如 2×2 Cells,L2-norm)
- 拼接所有 Block 的特征 → 最终 HOG 特征向量
二、MATLAB 程序
主程序:hog_demo.m
matlab
%% HOG (Histogram of Oriented Gradients) Demo
% 参考: Dalal & Triggs, CVPR 2005
clear; clc; close all;
%% ========== 1. 读入图像 ==========
img = imread('test_image.jpg'); % 建议用行人图片测试
% img = imresize(img, [128 64]); % INRIA 行人标准尺寸
if size(img,3)==3
gray = rgb2gray(img);
else
gray = img;
end
%% ========== 2. Gamma 校正(可选) ==========
gray = imadjust(gray, [], [], 0.5); % 压缩动态范围
%% ========== 3. 计算梯度 ==========
[Gx, Gy] = imgradientxy(gray, 'sobel');
[mag, ori] = imgradient(Gx, Gy); % mag: 梯度幅值, ori: 方向[-180,180]
% 转为 [0,180](无符号梯度,亮度不变性)
ori = mod(ori, 180);
%% ========== 4. HOG 参数 ==========
cellSize = 8; % 每个 cell 8×8 像素
numBins = 9; % 方向 bin 数
anglePerBin = 180 / numBins;
blockSize = 2; % 2×2 cells per block
stride = 1; % block 滑动步长(cell 数)
[h, w] = size(gray);
cellsX = floor(w / cellSize);
cellsY = floor(h / cellSize);
%% ========== 5. 构建 Cell 直方图 ==========
cellHist = zeros(cellsY, cellsX, numBins);
for cy = 1:cellsY
for cx = 1:cellsX
% Cell 区域
yrange = (cy-1)*cellSize+1 : cy*cellSize;
xrange = (cx-1)*cellSize+1 : cx*cellSize;
magCell = mag(yrange, xrange);
oriCell = ori(yrange, xrange);
% 投票到 9 个方向 bin
for b = 1:numBins
binLow = (b-1)*anglePerBin;
binHigh = b*anglePerBin;
% 方向落在当前 bin 内
idx = (oriCell >= binLow) & (oriCell < binHigh);
cellHist(cy, cx, b) = sum(magCell(idx));
end
end
end
%% ========== 6. Block 归一化 ==========
blocksY = cellsY - blockSize + 1;
blocksX = cellsX - blockSize + 1;
hogFeat = [];
for by = 1:blocksY
for bx = 1:blocksX
% 取出 2×2 cell 的直方图
block = cellHist(by:by+blockSize-1, bx:bx+blockSize-1, :);
blockVec = block(:);
% L2 归一化
epsVal = 1e-6;
blockNorm = blockVec / sqrt(norm(blockVec)^2 + epsVal);
hogFeat = [hogFeat; blockNorm];
end
end
%% ========== 7. 可视化 ==========
figure('Color','white','Position',[100 100 900 400])
subplot(1,2,1)
imshow(gray)
title('Input Image')
subplot(1,2,2)
visualizeHOG(gray, hogFeat, cellSize, blockSize, numBins)
title('HOG Visualization')
fprintf('HOG 特征维度: %d\n', length(hogFeat));
HOG 可视化函数:visualizeHOG.m
matlab
function visualizeHOG(img, hogFeat, cellSize, blockSize, numBins)
% 绘制 HOG 箭头图
[h, w] = size(img);
imshow(img); hold on;
anglePerBin = 180 / numBins;
featIdx = 1;
for by = 1:(h/cellSize - blockSize + 1)
for bx = 1:(w/cellSize - blockSize + 1)
for cy = 0:blockSize-1
for cx = 0:blockSize-1
% Cell 中心
centerY = (by+cy-1)*cellSize + cellSize/2;
centerX = (bx+cx-1)*cellSize + cellSize/2;
% 该 Cell 的 9 维直方图
histVec = hogFeat(featIdx:featIdx+numBins-1);
featIdx = featIdx + numBins;
% 画 9 个方向的箭头
for b = 1:numBins
angle = (b-0.5)*anglePerBin;
len = histVec(b) * 10; % 缩放因子
dx = len * cosd(angle);
dy = len * sind(angle);
quiver(centerX, centerY, dx, dy, ...
'Color','r','LineWidth',1.2,'MaxHeadSize',0.5);
end
end
end
end
end
hold off;
end
三、运行效果说明
-
红色箭头:表示梯度方向强度
-
箭头长度:正比于该方向的梯度幅值
-
特征维度示例(128×64 图像):
Cell: 16×8 Block: 15×7 每 Block: 2×2×9 = 36 维 总维度: 15×7×36 = 3780这正是 INRIA 行人检测 的标准 HOG 维度。
参考代码 计算HOG算子的典型程序 www.youwenfan.com/contentcsw/82584.html
四、关键参数含义
| 参数 | 典型值 | 作用 |
|---|---|---|
cellSize |
8×8 | 统计梯度的局部区域 |
numBins |
9 | 0°~180°,每 20° 一个 bin |
blockSize |
2×2 | 对比度归一化,抗光照 |
L2-norm |
防止单一强梯度主导 | |
| 无符号梯度 | 0°~180° | 忽略边缘方向正反 |
五、与 OpenCV / VLFeat 的差异
| 实现 | 特点 |
|---|---|
| 本程序 | 教学友好、完全透明 |
VLFeat (vl_hog) |
速度快、支持浮点 Cell |
OpenCV (HOGDescriptor) |
工业级、支持 SVM 训练 |
MATLAB 自带 extractHOGFeatures |
封装好,但不可控 |
如果你想完全对齐 OpenCV 结果,需要:
- 用
[0,360)有符号梯度- 改用 三线性插值投票
- 增加 重叠 Block 的裁剪方式