OpenCV 2.4+ C++ HOG行人检测

OpenCV 2.4+ C++ 行人检测

2012-12-03 08:24 by Justany_WhiteSnow, 2022 阅读, 0 评论, 收藏, 编辑

HOG特征描述

首先我们来了解一下HOG特征描述子。

HOG特征描述子(HOG descriptors)是由Navneet Dalal和 Bill Triggs在2005年的一篇介绍行人检测方法的论文提到的特征描述子(论文以及演讲可参见参考资料1、2)。

其主要思想是计算局部图像梯度的方向信息的统计值,来作为该图像的局部特征值。

  • 如上图,归一化图像后,由于颜色数据对我们没有帮助,所以将图片转为灰度图。
  • 然后将图片分割成一定“块”数,称作细胞单元。
  • 计算每个细胞单元的梯度大小方向。
  • 得到每个单元的梯度方向组成一个图片的特征向量。
  • 将这个特征向量交给SVM来学习或辨认。

SVM的简单介绍可以参考:OpenCV 2.4+ C++ SVM文字识别

 

算法分析

  • 梯度计算

 OpenCV 2.4+ C++ 边缘梯度计算中,介绍了Sobel算子和Scharr滤波器的梯度计算方法,但是论文作者使用这些复杂方法的效果并不好,最好的是使用简单的一维梯度算子:[-1, 0, 1],进行卷积计算,分别算出x方向梯度Gx与y方向梯度Gy。然后利用下面两个公式计算梯度大小和方向:

    G = \sqrt{ G_{x}^{2} + G_{y}^{2} }

    

  •  平滑处理

 论文作者使用了高斯模糊进行平滑处理,结果效果变差了。其可能原因是:许多有用的图像信息是来自变化剧烈的边缘,而在计算梯度之前加入高斯滤波会把这些边缘滤除掉。

  •  细胞方向选择
  1. 细胞的统计方向,由细胞中的每一个像素点投票取得。
  2. 票箱是0 - PI(无向)角度范围平分为9个角度,即PI/9为每个票箱的角度范围。
  3. 每个投票像素点的投票权重,由其梯度幅值计算出来,可采用幅值本身(实验效果最佳),或者他的函数来表示这个权重。
  • 块 

局部关照变化或者前景和背景的对比变化,可能使梯度强度产生剧烈变化,但我们关注的不是这些信息,所以需要对这些信息弱化处理。利用数个细胞单元组成空间上连通的块。这样,HOG描述就成了由各个块所有细胞单元的直方图组成的一个向量,这些区域是互相重叠的。这样就减小了这些剧烈变化的影响。

每个细胞是8*8个像素点,以四个细胞组成一个块。

 再由块组成检测窗。

  • 块向量归一化

最后是利用L2-norm或者L1-norm进行归一化。

v是未被归一化的向量,| vk |是k阶范数,ε为任意小常数,当k=2时,L2-norm为:

    

当k=1时,L1-norm为:

    

还有一种归一化方式L2-Hys:

    首先进行L2-norm,然后进行截短(即值被限制为v - 0.2v之间),然后再归一化。

 

HOGDescriptor API

gpu::HOGDescriptor::HOGDescriptor

创建HOG描述符和检测器。

C++:   gpu::HOGDescriptor:: HOGDescriptor (Size  win_size=Size(64, 128), Size  block_size=Size(16, 16), Size block_stride=Size(8, 8), Size  cell_size=Size(8, 8), int  nbins=9, double  win_sigma=DEFAULT_WIN_SIGMA, double threshold_L2hys=0.2, bool  gamma_correction=true, int  nlevels=DEFAULT_NLEVELS )
参数
  • win_size – 检测窗大小。需要和块的大小、步长匹配。
  • block_size – 块的大小。需要和细胞大小匹配。目前只支持(16,16)的大小。
  • block_stride – 块的步长,必须是细胞大小的整数倍。
  • cell_size – 细胞大小。目前只支持(8, 8)的大小。
  • nbins – 投票箱的个数。目前只支持每个细胞9个投票箱。
  • win_sigma – 高斯平滑窗口参数。
  • threshold_L2hys – L2-Hys归一化收缩率。
  • gamma_correction – 伽马校正预处理标志,需要或不需要。
  • nlevels – 检测窗口的最大数目。

gpu::HOGDescriptor::getDescriptorSize

返回分类所需的系数的数目。

C++:  size_t  gpu::HOGDescriptor:: getDescriptorSize ( )  const

gpu::HOGDescriptor::getBlockHistogramSize

返回块直方图的大小。

C++:  size_t  gpu::HOGDescriptor:: getBlockHistogramSize ( )  const

gpu::HOGDescriptor::setSVMDetector

设置线性SVM分类器的系数。

C++:  void  gpu::HOGDescriptor:: setSVMDetector (const vector<float>&  detector )

gpu::HOGDescriptor::getDefaultPeopleDetector

返回人的分类训练检测(默认的窗口大小)的默认系数。

C++:   static vector<float>  gpu::HOGDescriptor:: getDefaultPeopleDetector ( )

gpu::HOGDescriptor::getPeopleDetector48x96

返回人的分类训练检测(48*96窗口大小)的系数。

C++:   static vector<float>  gpu::HOGDescriptor:: getPeopleDetector48x96 ( )

gpu::HOGDescriptor::getPeopleDetector64x128

返回人的分类训练检测(64*128窗口大小)的系数。

C++:   static vector<float>  gpu::HOGDescriptor:: getPeopleDetector64x128 ( )

gpu::HOGDescriptor::detect

在没有多尺度的窗口执行对象检测

C++:  void  gpu::HOGDescriptor:: detect (const GpuMat&  img, vector<Point>&  found_locations, double  hit_threshold=0, Size win_stride=Size(), Size  padding=Size() )
Parameters:
  • img – 源图像。只支持CV_8UC1CV_8UC4数据类型
  • found_locations – 检测出的物体的边缘。
  • hit_threshold – 特征向量和SVM划分超平面的阀值距离。通常它为0,并应由检测器系数决定。但是,当系数被省略时,可以手动指定它。
  • win_stride – 窗口步长,必须是块步长的整数倍。
  • padding – 模拟参数,使得CUP能兼容。目前必须是(0,0)。

gpu::HOGDescriptor::detectMultiScale

在多尺度窗口中执行对象检测。

C++:  void  gpu::HOGDescriptor:: detectMultiScale (const GpuMat&  img, vector<Rect>&  found_locations, double  hit_threshold=0, Size  win_stride=Size(), Size  padding=Size(), double  scale0=1.05, int  group_threshold=2 )
参数
  • img – 源图像。只支持CV_8UC1CV_8UC4数据类型
  • found_locations – 检测出的物体的边缘。
  • hit_threshold – 特征向量和SVM划分超平面的阀值距离。通常它为0,并应由检测器系数决定。但是,当系数被省略时,可以手动指定它。
  • win_stride – 窗口步长,必须是块步长的整数倍。
  • padding – 模拟参数,使得CUP能兼容。目前必须是(0,0)。
  • scale0 – 检测窗口增长参数。
  • group_threshold – 调节相似性系数的阈值。检测到时,某些对象可以由许多矩形覆盖。 0表示不进行分组。

gpu::HOGDescriptor::getDescriptors

返回整个图片的块描述符。

C++:  void  gpu::HOGDescriptor:: getDescriptors (const GpuMat&  img, Size  win_stride, GpuMat&  descriptors, int descr_format=DESCR_FORMAT_COL_BY_COL )
参数
  • img – 源图像。只支持CV_8UC1CV_8UC4数据类型
  • win_stride – 窗口步长,必须是块步长的整数倍。
  • descriptors – 描述符的2D数组。
  • descr_format –

    描述符存储格式:

    • DESCR_FORMAT_ROW_BY_ROW - 行存储。
    • DESCR_FORMAT_COL_BY_COL - 列存储。

这个函数主要用于分类学习。

 

检测代码

复制代码
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/gpu/gpu.hpp>

#include <stdio.h>

using namespace cv;

int main(int argc, char** argv){
    Mat img;
    vector<Rect> found;

     img = imread(argv[1]);

    if(argc != 2 || !img.data){
        printf("没有图片\n");
        return -1;
    }

    HOGDescriptor defaultHog;
    defaultHog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());

    //进行检测
    defaultHog.detectMultiScale(img, found);

    //画长方形,框出行人
    for(int i = 0; i < found.size(); i++){
        Rect r = found[i];
        rectangle(img, r.tl(), r.br(), Scalar(0, 0, 255), 3);
    }

    
    namedWindow("检测行人", CV_WINDOW_AUTOSIZE);
    imshow("检测行人", img);

    waitKey(0);

    return 0;
}
复制代码

这段代码虽然可以检测出行人,但是可能会出现,一个人身上有几个框框。例如下图左边的行人:

所以我们需要对found进行筛选,把那些被嵌套的长方形去除。

复制代码
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/gpu/gpu.hpp>

#include <stdio.h>

using namespace cv;

int main(int argc, char** argv){
    Mat img;
    vector<Rect> found, foundRect;

     img = imread(argv[1]);

    if(argc != 2 || !img.data){
        printf("没有图片\n");
        return -1;
    }

    HOGDescriptor defaultHog;
    defaultHog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());

    //进行检测
    defaultHog.detectMultiScale(img, found);

    //遍历found寻找没有被嵌套的长方形
    for(int i = 0; i < found.size(); i++){
        Rect r = found[i];

        int j = 0;
        for(; j < found.size(); j++){
            //如果时嵌套的就推出循环
            if( j != i && (r & found[j]) == r)
                break;
        }
        if(j == found.size()){
            foundRect.push_back(r);
        }
    }

    //画长方形,圈出行人
    for(int i = 0; i < foundRect.size(); i++){
        Rect r = foundRect[i];
        rectangle(img, r.tl(), r.br(), Scalar(0, 0, 255), 3);
    }

    
    namedWindow("检测行人", CV_WINDOW_AUTOSIZE);
    imshow("检测行人", img);

    waitKey(0);

    return 0;
} 
复制代码

 

PS:输入图片不能比检测窗还小,这样会抛出错误的。

 

参考资料

Histograms of Oriented Gradients for Human Detection . Navneet Dalal & Bill Triggs . 2005

Histograms of Oriented Gradients for Human Detection Talk . Navneet Dalal & Bill Triggs

OpenCV HOGDescriptor 参数图解 . Excalibur . 2011-03-11

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python OpenCV HOG SVM 行人检测是使用Python编程语言和OpenCV库来实现行人检测的一种方法。该方法主要利用了HOG(Histogram of Oriented Gradients)特征和SVM(Support Vector Machine)分类器来检测行人。 以下是 Python OpenCV HOG SVM 行人检测的步骤: 1. 收集行人图像数据集并标注。 2. 提取图像中的HOG特征。 3. 利用提取的特征训练SVM分类器。 4. 在测试图像中使用训练好的SVM分类器来检测行人。 具体实现细节如下: 1. 数据集收集和标注 要进行行人检测,首先需要收集行人图像数据集并进行标注。可以使用现有的数据集,例如INRIA行人数据集,或者自己创建数据集。 对于数据集的标注,可以使用图像标注工具来手动标注,例如LabelImg或VGG Image Annotator(VIA)。对于每个行人图像,需要标注行人的位置和大小。 2. 提取HOG特征 OpenCV提供了HOGDescriptor函数来提取图像中的HOG特征HOG特征是由图像中不同方向的梯度组成的向量,可以有效地表示图像的纹理和形状特征。 代码示例: ``` import cv2 # 创建HOG描述符对象 hog = cv2.HOGDescriptor() # 提取HOG特征 features = hog.compute(image) ``` 其中,image是输入图像,features是提取的HOG特征向量。 3. 训练SVM分类器 在提取HOG特征后,需要使用训练数据集来训练SVM分类器。可以使用OpenCV提供的SVM函数来实现训练。 代码示例: ``` import cv2 # 加载训练数据集和标签 train_data = cv2.imread('train_data.png') train_labels = cv2.imread('train_labels.png') # 创建SVM分类器对象 svm = cv2.ml.SVM_create() # 设置SVM参数 svm.setType(cv2.ml.SVM_C_SVC) svm.setKernel(cv2.ml.SVM_LINEAR) svm.setTermCriteria((cv2.TERM_CRITERIA_MAX_ITER, 100, 1e-6)) # 训练SVM分类器 svm.train(train_data, cv2.ml.ROW_SAMPLE, train_labels) ``` 其中,train_data是训练数据集,train_labels是对应的标签。SVM参数可以根据实际情况进行调整。 4. 行人检测 在训练好SVM分类器后,可以在测试图像中使用它来检测行人。可以使用OpenCV提供的detectMultiScale函数来实现检测。 代码示例: ``` import cv2 # 加载测试图像 test_image = cv2.imread('test_image.png') # 创建HOG描述符对象 hog = cv2.HOGDescriptor() # 设置SVM分类器 hog.setSVMDetector(svm.getSupportVectors()) # 行人检测 rects, weights = hog.detectMultiScale(test_image, winStride=(8, 8)) # 绘制检测结果 for (x, y, w, h) in rects: cv2.rectangle(test_image, (x, y), (x + w, y + h), (0, 255, 0), 2) # 显示检测结果 cv2.imshow('result', test_image) cv2.waitKey(0) ``` 其中,test_image是要检测的测试图像。通过设置SVM分类器,可以使用HOG描述符对象的detectMultiScale函数来检测行人。检测结果是一组矩形框,可以使用OpenCV提供的rectangle函数来绘制。最后使用imshow函数显示检测结果。 总结: Python OpenCV HOG SVM 行人检测是一种简单有效的行人检测方法。通过收集数据集,提取HOG特征,训练SVM分类器,可以实现高效的行人检测。可以应用于视频监控、自动驾驶等领域。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值