Android 版本 OpenCV HOG 特征计算与提取
在计算机视觉任务中,HOG(Histogram of Oriented Gradients,方向梯度直方图) 是一种广泛用于目标检测(如行人检测) 的特征提取方法。它通过计算局部图像梯度的方向和幅值,并构造直方图来表示目标的特征。
在 OpenCV for Android 中,我们可以使用 HOGDescriptor 来计算 HOG 特征,并结合 SVM 进行分类(如行人检测)。
1. HOG 特征的原理
HOG 特征的计算步骤如下:
-
灰度化:将输入图像转换为灰度图(因为颜色信息对梯度计算影响不大)。
-
计算梯度:使用 Sobel 算子计算水平和垂直方向上的梯度。
-
计算梯度方向和幅值:
• 计算每个像素点的梯度方向 θ = arctan(Gy / Gx)
• 计算每个像素点的梯度幅值 M = sqrt(Gx² + Gy²)
- 构建方向直方图:
• 将图像划分为小块(Cell,例如 8×8 像素)
• 统计每个 Cell 内不同方向的梯度值,形成梯度直方图
- 块归一化(Block Normalization) :
• 组合多个相邻的 Cell 形成 Block(如 16×16)
• 进行 L2 归一化,提高对光照和对比度变化的鲁棒性
- 生成 HOG 特征向量:
• 将所有 Block 的 HOG 直方图组合成最终特征向量。
2. OpenCV Android 版 HOG 特征提取
在 OpenCV for Android 中,可以使用 HOGDescriptor 进行 HOG 特征提取,并结合 SVM 进行分类。
2.1 HOG 特征计算
代码示例
import org.opencv.android.Utils;
import org.opencv.core.*;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.HOGDescriptor;
import android.graphics.Bitmap;
public class HOGFeatureExtractor {
public static float[] computeHOG(Bitmap bitmap) {
// 1. 转换 Bitmap 为 Mat
Mat imgMat = new Mat();
Utils.bitmapToMat(bitmap, imgMat);
// 2. 转换为灰度图
Imgproc.cvtColor(imgMat, imgMat, Imgproc.COLOR_BGR2GRAY);
// 3. 设置 HOGDescriptor
HOGDescriptor hog = new HOGDescriptor(
new Size(64, 128), // 窗口大小 (通常64x128用于行人检测)
new Size(16, 16), // Block 大小
new Size(8, 8), // Block 步长
new Size(8, 8), // Cell 大小
9 // 梯度方向数 (bins)
);
// 4. 计算 HOG 特征
MatOfFloat descriptors = new MatOfFloat();
hog.compute(imgMat, descriptors);
// 5. 返回 HOG 特征向量
return descriptors.toArray();
}
}
解释
• computeHOG() 计算图像的 HOG 特征并返回特征向量。
• HOGDescriptor 参数:
• winSize: HOG 计算窗口大小(通常 64×128)。
• blockSize: HOG Block 大小(通常 16×16)。
• blockStride: Block 滑动步长(通常 8×8)。
• cellSize: Cell 大小(通常 8×8)。
• nbins: 方向梯度直方图的 bin 数量(通常 9)。
2.2 使用 HOG 进行行人检测
OpenCV 自带了预训练的 HOG + SVM 行人检测模型,可以直接使用。
代码示例
import org.opencv.android.Utils;
import org.opencv.core.*;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.HOGDescriptor;
import java.util.ArrayList;
import android.graphics.Bitmap;
public class HOGPedestrianDetector {
public static Bitmap detectPedestrians(Bitmap bitmap) {
// 1. 转换 Bitmap 为 Mat
Mat imgMat = new Mat();
Utils.bitmapToMat(bitmap, imgMat);
// 2. 初始化 HOGDescriptor 并加载行人检测 SVM
HOGDescriptor hog = new HOGDescriptor();
hog.setSVMDetector(HOGDescriptor.getDefaultPeopleDetector());
// 3. 进行行人检测
MatOfRect foundLocations = new MatOfRect();
MatOfDouble foundWeights = new MatOfDouble();
hog.detectMultiScale(imgMat, foundLocations, foundWeights);
// 4. 在图像上绘制检测框
for (Rect rect : foundLocations.toArray()) {
Imgproc.rectangle(imgMat, rect.tl(), rect.br(), new Scalar(0, 255, 0), 3);
}
// 5. 转换回 Bitmap
Bitmap outputBitmap = Bitmap.createBitmap(imgMat.cols(), imgMat.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(imgMat, outputBitmap);
return outputBitmap;
}
}
解释
• setSVMDetector(HOGDescriptor.getDefaultPeopleDetector()):使用 OpenCV 预训练的 SVM 行人检测模型。
• detectMultiScale() 进行多尺度行人检测:
• 返回矩形框 foundLocations 代表检测到的行人区域。
• foundWeights 表示置信度(可用于阈值筛选)。
• rectangle() 在检测到的区域绘制绿色边框。
3. 调整 HOG 参数优化检测效果
在行人检测或目标检测任务中,调整 HOG 参数可以提高检测精度和速度:
• winStride(窗口步长):控制检测窗口的滑动步长,可优化速度。
• padding(填充):避免边缘信息丢失。
• scale(缩放因子):影响检测精度和计算开销。
• hitThreshold(SVM 置信度阈值):调整误报率。
优化 HOG 检测
hog.detectMultiScale(
imgMat, foundLocations, foundWeights,
0, // hitThreshold 设为 0 以检测更多目标
new Size(8, 8), // winStride (步长)
new Size(0, 0), // padding
1.05, // scaleFactor (缩放)
2 // groupThreshold (最小检测数量)
);
4. HOG 在 Android 端的应用
| 应用场景 | 说明 |
|---|---|
| 行人检测 | 使用 HOG + SVM 预训练模型 |
| 车辆检测 | 需自定义 HOG 训练 SVM |
| 姿态估计 | 提取 HOG 特征训练分类器 |
| 手势识别 | 结合 HOG 和 CNN 训练分类模型 |
HOG 适用于检测固定模式目标,如行人、车辆、手势等,但对姿态变化敏感,可结合深度学习改进!
总结
| 方法 | 作用 | 优缺点 |
|---|---|---|
| HOG 特征提取 | 计算图像的 HOG 描述符 | 计算较快,但需手动训练分类器 |
| HOG + SVM 预训练模型 | 行人检测 | 直接使用 OpenCV 预训练模型 |
| HOG + 自定义 SVM | 目标检测(车辆、手势) | 需要手动标注数据集训练 |