如何使用HOG描述符检测图像中的对象?

时间:2019-03-28 12:09:21

标签: c++ image opencv image-processing object-detection

跟踪对象时,我希望能够在遮挡后重新检测到它。

在OpenCV 3.4.5(C ++)上,我尝试了模板匹配和光流分割。但是现在,我想使用HOG描述符实现更强大的算法。

我举了一个小例子来说明问题。 这是我的2张图片:

enter image description here 我要检测的车辆

enter image description here 我要搜索的图像

PS:我不想训练SVM,因为我只想在几帧中检测到一个唯一的对象。

我的代码:

#include <opencv2/core/utility.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/objdetect.hpp>

#include <iostream>
#include <vector>

using namespace std;
using namespace cv;

int main(int argc, char** argv){

        //load images
        Mat lastSeenObject=imread("lastSeenObject.png",1); //21x39
        Mat patch=imread("patch.png",1); //150x150

        //params
        Size cellSize(8,8);
        int nbins= 9;
        Size blockSize(2,2);

        //my variables
        vector<float>templ_descriptor;
        vector<float>p_descriptor;
        Mat templ_gray,p_gray,iMatches;
        vector<DMatch> matches;

        //convert to gray
        cvtColor(lastSeenObject,templ_gray,CV_BGR2GRAY);
        cvtColor(patch,p_gray,CV_BGR2GRAY);

        //create hog object
        HOGDescriptor hog(Size(templ_gray.cols/cellSize.width*cellSize.width,templ_gray.rows/cellSize.height*cellSize.height),
                Size(blockSize.height*cellSize.height,blockSize.width*cellSize.width),
                Size(cellSize.height,cellSize.width),
                cellSize,
                nbins);
        // gives --> winSize [32 x 16],  blockSize [16 x 16],  blockStride [8 x 8],  cellSize [8 x 8]

        //compute the descriptor of the car
        hog.compute(templ_gray,templ_descriptor, Size(cellSize.height,cellSize.width), Size( 0, 0 ));
        //templ_descriptor.size() = 108, containing floats between 0 and 1

        //compute the descriptor of the patch
        hog.compute(p_gray,p_descriptor, Size(cellSize.height,cellSize.width), Size( 0, 0 ));
        //p_descriptor.size() = 27540, containing floats between 0 and 1

        //compare the descriptors
        double err=0;
        double min_err = -1;
        int idx=-1;
        for (unsigned int i =0;i<p_descriptor.size();i++)
        {
            if(i%templ_descriptor.size()==0 && i!=0) // iterate the computation of error over the templ_descriptor size
            {
                if(err<min_err || min_err ==-1)
                {
                    min_err = err;
                    idx = i-nbins;
                }
                err = 0;
            }
            //euclidean error distance accumulator between each component of the histogram
            err += abs(p_descriptor[i] - templ_descriptor[i%templ_descriptor.size()]);
        }

        // we get idx = 11655 and err = 5.34021

        //convert vector idx in x,y coordonates in the patch
        int row= static_cast<int>(idx/patch.cols);
        int col = idx%patch.cols;

        //show the result
        Rect2f found_object(col,row,hog.winSize.width,hog.winSize.height); // [32 x 16 from (105, 77)]
        rectangle(patch,found_object,Scalar(0,0,255));
        imshow("result",patch);
        waitKey(500000);

        return 1;
}

我的结果

enter image description here

当然,预期的结果是在车辆上安装边框。

我的问题

1 /函数compute返回的描述符的结构如何?

我假设有9个(nBins)浮点数描述cellSize,但我不明白为什么winl为16x32,cellSize为8x8时,templ_descriptor中有108/9 = 12个单元格。

2 /如何从p_descriptor中检索与templ_descriptor最匹配的winSize的像素坐标?

3 /您还有其他建议来解决我在小遮挡后重新检测目标的问题吗?

有用的链接

OpenCV 3.4.5 documentation on HOG Descriptor

LearnOpenCV article on HOG

1 个答案:

答案 0 :(得分:1)

尝试使用SIFT。要在opencv3中使用SIFT,必须在contrib启用的情况下构建opencv。

如果您仍然想尝试HOG是否起作用。尝试在两个向量之间计算distance-车辆图像的描述符和较大图像的每个描述符。如果设置blockSize = (vehicle image size),向量大小应该相同。

HOG的缺点是旋转公差小。 SIFT承载可旋转每个角度的对象。但是,SIFT会更多地涉及对象的细节图案,因此,当图像分辨率较小时,SIFT可能会更具风险。