在Android上玩转Opencv 系列:22.基础知识 图像Hog 特征提取

137 阅读4分钟

Android 版本 OpenCV HOG 特征计算与提取

在计算机视觉任务中,HOG(Histogram of Oriented Gradients,方向梯度直方图) 是一种广泛用于目标检测(如行人检测) 的特征提取方法。它通过计算局部图像梯度的方向和幅值,并构造直方图来表示目标的特征。

在 OpenCV for Android 中,我们可以使用 HOGDescriptor 来计算 HOG 特征,并结合 SVM 进行分类(如行人检测)。

1. HOG 特征的原理

HOG 特征的计算步骤如下:

  1. 灰度化:将输入图像转换为灰度图(因为颜色信息对梯度计算影响不大)。

  2. 计算梯度:使用 Sobel 算子计算水平和垂直方向上的梯度。

  3. 计算梯度方向和幅值

• 计算每个像素点的梯度方向 θ = arctan(Gy / Gx)

• 计算每个像素点的梯度幅值 M = sqrt(Gx² + Gy²)

  1. 构建方向直方图

• 将图像划分为小块(Cell,例如 8×8 像素)

• 统计每个 Cell 内不同方向的梯度值,形成梯度直方图

  1. 块归一化(Block Normalization)

• 组合多个相邻的 Cell 形成 Block(如 16×16)

• 进行 L2 归一化,提高对光照和对比度变化的鲁棒性

  1. 生成 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目标检测(车辆、手势)需要手动标注数据集训练