1. 程式人生 > >OpenCV之影象特徵提取與檢測(十) HOG特徵檢測

OpenCV之影象特徵提取與檢測(十) HOG特徵檢測

用於人像的識別,動物識別。需要提前錄入訓練資料,才能進行對比識別,OpenCV中已經錄入了行人的訓練資料

HOG(Histogram of Oriented Gradient)特徵描述子提取:

  • 灰度影象轉換—gray = R*0.3 + 0.59*G + 0.11*B
  • 梯度計算—sobel運算元計算梯度,畫素點的兩個特徵:方向(角度)與梯度
  • 分網格的梯度方向直方圖
    這裡寫圖片描述
  • 塊描述子—方塊的:R-HOG 圓形的:C-HOG
    這裡寫圖片描述
  • 塊描述子歸一化 —至此得到了 HOG特徵的資料了
    這裡寫圖片描述
  • 特徵資料與檢測視窗

        最終獲得HOG描述運算元(特徵資料)
        需要正向訓練200個左右的特徵樣本
        反向訓練600~800個左右的特徵樣本
        初步測試、開窗檢測
    
        舉例:
            對於64x128的畫素塊,可以分為8x16個Cell分為7x15個塊(R-HOG)
            總計的直方圖向量數為:
            7x15x2x2x9 = 3780個向量陣列
    
  • 匹配方法

    cv::HOGDescriptor HOGDescriptor( // HOG特徵描述子提取
        Size _winSize, // 視窗大小,對應上面舉例的 64x128
        Size _blockSize, // 2x2個_cellSize,也就是 16x16
        Size _blockStride, // 每次移動步長,也就是 _cellSize的尺寸 8x8
        Size _cellSize, // 8x8
        int _nbins, // 對梯度方向直方圖中的bins 9
        int _derivAperture=1, // 求梯度的引數
        double _winSigma=-1, 
        int _histogramNormType=HOGDescriptor::L2Hys, // 求直方圖的引數
        double _L2HysThreshold=0.2, // 歸一化閾值引數
        bool _gammaCorrection=false, // 對於灰度的輸入影象是否要做伽馬校正
        int _nlevels=HOGDescriptor::DEFAULT_NLEVELS, 
        bool _signedGradient=false 
    

    )

程式碼

    #include "../common/common.hpp"

    void main(int argc, char** argv)
    {
        Mat src = imread(getCVImagesPath("images/hogman.png"));
        imshow("src-13", src);

        // HOG特徵描述子
        Mat dst, dst_gray;
        resize(src, dst, Size(64, 128)); // 將原始影象變成 64x128 尺寸
        imshow("resize2-13", dst);
        cvtColor(dst, dst_gray, COLOR_BGR2GRAY);
        HOGDescriptor detector(Size(64, 128), Size(16, 16), Size(8, 8), Size(8, 8), 9); // HOG特徵描述子提取類

        vector<float> descriptors; // 儲存舉例中的計算出來的3780個向量陣列
        vector<Point> locations; // 作用?
        detector.compute(dst_gray, descriptors, Size(0, 0), Size(0, 0), locations); // 計算HOG特徵描述子
        // descriptors.size=3780, locations.size=0
        cout << "descriptors.size=" << descriptors.size() << ", locations.size=" << locations.size() << endl;

        // HOG+SVM 實現行人檢測
        Mat walkers = imread(getCVImagesPath("images/HOGV.png"));
        imshow("walkers", walkers);

        HOGDescriptor hog = HOGDescriptor();
        hog.setSVMDetector(hog.getDefaultPeopleDetector()); // opencv自帶的封裝好了行人資料的Detector
        vector<Rect> foundLocations; // 儲存檢測到的行人的 Rect
        hog.detectMultiScale(walkers, foundLocations, 0, Size(8, 8), Size(32, 32), 1.05, 2); // 在多個尺寸上尋找,detect 同一尺度
        cout << "foundLocations.size=" << foundLocations.size() << endl; // foundLocations.size=3
        Mat result = walkers.clone();
        for (size_t t = 0; t < foundLocations.size(); t++) {
            rectangle(result, foundLocations[t], Scalar(0, 0, 255), 2, 8, 0); // 繪製行人的方框
        }
        imshow("HOG SVM Detector", result);

        waitKey(0);
    }

效果圖

這裡寫圖片描述