OpenCV 2.4+ C++ 行人檢測


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM