OpenCV 2.4+ C++ 行人檢測

HOG特徵描述 html

首先咱們來了解一下HOG特徵描述子。 算法

HOG特徵描述子(HOG descriptors)是由Navneet Dalal和 Bill Triggs在2005年的一篇介紹行人檢測方法的論文提到的特徵描述子(論文以及演講可參見參考資料一、2)。 數組

其主要思想是計算局部圖像梯度的方向信息的統計值,來做爲該圖像的局部特徵值。 ide

  • 如上圖,歸一化圖像後,因爲顏色數據對咱們沒有幫助,因此將圖片轉爲灰度圖。
  • 而後將圖片分割成必定「塊」數,稱做細胞單元。
  • 計算每一個細胞單元的梯度大小方向。
  • 獲得每一個單元的梯度方向組成一個圖片的特徵向量。
  • 將這個特徵向量交給SVM來學習或辨認。

SVM的簡單介紹能夠參考:OpenCV 2.4+ C++ SVM文字識別函數

 

算法分析 學習

  • 梯度計算

 OpenCV 2.4+ C++ 邊緣梯度計算中,介紹了Sobel算子和Scharr濾波器的梯度計算方法,可是論文做者使用這些複雜方法的效果並很差,最好的是使用簡單的一維梯度算子:[-1, 0, 1],進行卷積計算,分別算出x方向梯度Gx與y方向梯度Gy。而後利用下面兩個公式計算梯度大小和方向: ui

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

    

  •  平滑處理

 論文做者使用了高斯模糊進行平滑處理,結果效果變差了。其可能緣由是:許多有用的圖像信息是來自變化劇烈的邊緣,而在計算梯度以前加入高斯濾波會把這些邊緣濾除掉。 spa

  •  細胞方向選擇
  1. 細胞的統計方向,由細胞中的每個像素點投票取得。
  2. 票箱是0 - PI(無向)角度範圍平分爲9個角度,即PI/9爲每一個票箱的角度範圍。
  3. 每一個投票像素點的投票權重,由其梯度幅值計算出來,可採用幅值自己(實驗效果最佳),或者他的函數來表示這個權重。
  • 塊 

局部關照變化或者前景和背景的對比變化,可能使梯度強度產生劇烈變化,但咱們關注的不是這些信息,因此須要對這些信息弱化處理。利用數個細胞單元組成空間上連通的塊。這樣,HOG描述就成了由各個塊全部細胞單元的直方圖組成的一個向量,這些區域是互相重疊的。這樣就減少了這些劇烈變化的影響。 .net

每一個細胞是8*8個像素點,以四個細胞組成一個塊。 code

 再由塊組成檢測窗。

  • 塊向量歸一化

最後是利用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_8UC1和CV_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

相關文章
相關標籤/搜索