跟踪对象时,我希望能够在遮挡后重新检测到它。
在OpenCV 3.4.5(C++)上,我尝试了模板匹配和光流分割。但是现在,我想使用HOG描述符实现更强大的算法。
我举了一个小例子来说明问题。
这是我的2张图片:
我要检测的车辆
我要搜索的图像
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;
}
我的结果
当然,预期结果是在车辆上安装了边框。
我的问题
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
最佳答案
尝试使用SIFT。要在opencv3中使用SIFT,必须在contrib
ON的情况下构建opencv。
如果您仍然想尝试HOG是否有效。尝试计算两个 vector 之间的distance-车辆图像的描述符和较大图像的每个描述符。如果设置blockSize = (vehicle image size)
, vector 大小应该相同。
HOG的缺点是旋转公差小。 SIFT承载可旋转每个 Angular 对象。但是,SIFT会更多地涉及对象的细节图案,因此,当图像分辨率较小时,SIFT可能会更具风险。
关于c++ - 如何使用HOG描述符检测图像中的对象?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55397301/