在 OpenCV 中使用 GPU 进行对象检测的 HOG 特征
HOG features for object detection using GPU in OpenCV
在我的项目中,我正在为同一图像的不同级别计算 GPU 上的 HOG 特征。我的目标是检测以下对象。
1. 卡车
2.汽车
3. 人
大多数 重要的问题 是 select 在多 class 物体检测器的情况下大小为 window 的离子。 This post 提供了一个很好的基础,但它没有为 window 大小的 select 离子提供答案,以防多 class 特征。
为了解决这个问题,我计算了每个正图像在不同 levels/resolution 的 HOG 特征,保持 window 大小(48*96)相同,但每个图像的文件大约 600 MB,这太大了。
请让我知道在多 class 对象检测的情况下如何 select window 大小、块大小和单元格大小。这是我用来计算 HOG 特征的代码。
void App::run()
{
unsigned int count = 1;
FileStorage fs;
running = true;
//int width;
//int height;
Size win_size(args.win_width, args.win_width * 2);
Size win_stride(args.win_stride_width, args.win_stride_height);
cv::gpu::HOGDescriptor gpu_hog(win_size, Size(16, 16), Size(8, 8), Size(8, 8), 9,
cv::gpu::HOGDescriptor::DEFAULT_WIN_SIGMA, 0.2, gamma_corr,
cv::gpu::HOGDescriptor::DEFAULT_NLEVELS);
VideoCapture vc("/home/ubuntu/Desktop/getdescriptor/images/image%d.jpg");
Mat frame;
Mat Left;
Mat img_aux, img, img_to_show, img_new;
cv::Mat temp;
gpu::GpuMat gpu_img, descriptors, new_img;
char cbuff[20];
while (running)
{
vc.read(frame);
if (!frame.empty())
{
workBegin();
width = frame.rows;
height = frame.cols;
sprintf (cbuff, "%04d", count);
// Change format of the image
if (make_gray) cvtColor(frame, img_aux, CV_BGR2GRAY);
else if (use_gpu) cvtColor(frame, img_aux, CV_BGR2BGRA);
else Left.copyTo(img_aux);
// Resize image
if (args.resize_src) resize(img_aux, img, Size(args.width, args.height));
else img = img_aux;
img_to_show = img;
gpu_hog.nlevels = nlevels;
hogWorkBegin();
if (use_gpu)
{
gpu_img.upload(img);
new_img.upload(img_new);
fs.open(cbuff, FileStorage::WRITE);
for(int levels = 0; levels < nlevels; levels++)
{
gpu_hog.getDescriptors(gpu_img, win_stride, descriptors, cv::gpu::HOGDescriptor::DESCR_FORMAT_ROW_BY_ROW);
descriptors.download(temp);
//printf("size %d %d\n", temp.rows, temp.cols);
fs <<"level" << levels;
fs << "features" << temp;
cout<<"("<<width<<","<<height<<")"<<endl;
width = round(width/scale);
height = round(height/scale);
if( width < win_size.width || height < win_size.height )
break;
cout<<"Levels "<<levels<<endl;
resize(img,img_new,Size(width,height));
scale *= scale;
}
cout<<count<< " Image feature calculated !"<<endl;
count++;
//width = 640; height = 480;
scale = 1.05;
}
hogWorkEnd();
fs.release();
}
else running = false;
}
}
应选择 window 尺寸,s.t。您要检测的对象适合 window。如果你想为不同的类型设置不同的 window 大小,这可能会变得棘手。
通常你做的是下面的
- 为每种类型的对象获取训练数据,并使用在对象的已知位置提取的特征训练[对象类型的数量]许多模型。
- 然后拍摄每张测试图像并使用滑动 window 方法在每个位置提取特征。然后将这些功能与每个模型进行比较。如果其中一个模型的得分高于某个阈值,则您已找到该对象。如果不止一个模型得分高于阈值,则只取得分最高的一个。
如果您想使用不同大小的检测 windows,您将获得不同大小的特征向量(根据 HoG 特征的性质)。棘手的是,在测试阶段,您必须使用与您使用的对象类型一样多的滑动 windows。这肯定有效,但您必须多次处理每个测试图像,导致处理时间更长)
回答你的尺寸问题:我没有什么价值可以给你,它总是取决于你的图像。使用上面提到的图像金字塔是处理不同比例对象的好方法。
- window 大小:整个对象应该适合;必须能被块大小整除
- 块大小必须能被像元大小整除
可以找到 HoG 特征可视化的示例代码 here。这也有助于理解特征向量的样子。
编辑: 艰难地发现,单元格大小只允许 cv::Size(8,8)
。参见 documentation。
在我的项目中,我正在为同一图像的不同级别计算 GPU 上的 HOG 特征。我的目标是检测以下对象。
1. 卡车
2.汽车
3. 人
大多数 重要的问题 是 select 在多 class 物体检测器的情况下大小为 window 的离子。 This post 提供了一个很好的基础,但它没有为 window 大小的 select 离子提供答案,以防多 class 特征。
为了解决这个问题,我计算了每个正图像在不同 levels/resolution 的 HOG 特征,保持 window 大小(48*96)相同,但每个图像的文件大约 600 MB,这太大了。
请让我知道在多 class 对象检测的情况下如何 select window 大小、块大小和单元格大小。这是我用来计算 HOG 特征的代码。
void App::run()
{
unsigned int count = 1;
FileStorage fs;
running = true;
//int width;
//int height;
Size win_size(args.win_width, args.win_width * 2);
Size win_stride(args.win_stride_width, args.win_stride_height);
cv::gpu::HOGDescriptor gpu_hog(win_size, Size(16, 16), Size(8, 8), Size(8, 8), 9,
cv::gpu::HOGDescriptor::DEFAULT_WIN_SIGMA, 0.2, gamma_corr,
cv::gpu::HOGDescriptor::DEFAULT_NLEVELS);
VideoCapture vc("/home/ubuntu/Desktop/getdescriptor/images/image%d.jpg");
Mat frame;
Mat Left;
Mat img_aux, img, img_to_show, img_new;
cv::Mat temp;
gpu::GpuMat gpu_img, descriptors, new_img;
char cbuff[20];
while (running)
{
vc.read(frame);
if (!frame.empty())
{
workBegin();
width = frame.rows;
height = frame.cols;
sprintf (cbuff, "%04d", count);
// Change format of the image
if (make_gray) cvtColor(frame, img_aux, CV_BGR2GRAY);
else if (use_gpu) cvtColor(frame, img_aux, CV_BGR2BGRA);
else Left.copyTo(img_aux);
// Resize image
if (args.resize_src) resize(img_aux, img, Size(args.width, args.height));
else img = img_aux;
img_to_show = img;
gpu_hog.nlevels = nlevels;
hogWorkBegin();
if (use_gpu)
{
gpu_img.upload(img);
new_img.upload(img_new);
fs.open(cbuff, FileStorage::WRITE);
for(int levels = 0; levels < nlevels; levels++)
{
gpu_hog.getDescriptors(gpu_img, win_stride, descriptors, cv::gpu::HOGDescriptor::DESCR_FORMAT_ROW_BY_ROW);
descriptors.download(temp);
//printf("size %d %d\n", temp.rows, temp.cols);
fs <<"level" << levels;
fs << "features" << temp;
cout<<"("<<width<<","<<height<<")"<<endl;
width = round(width/scale);
height = round(height/scale);
if( width < win_size.width || height < win_size.height )
break;
cout<<"Levels "<<levels<<endl;
resize(img,img_new,Size(width,height));
scale *= scale;
}
cout<<count<< " Image feature calculated !"<<endl;
count++;
//width = 640; height = 480;
scale = 1.05;
}
hogWorkEnd();
fs.release();
}
else running = false;
}
}
应选择 window 尺寸,s.t。您要检测的对象适合 window。如果你想为不同的类型设置不同的 window 大小,这可能会变得棘手。
通常你做的是下面的
- 为每种类型的对象获取训练数据,并使用在对象的已知位置提取的特征训练[对象类型的数量]许多模型。
- 然后拍摄每张测试图像并使用滑动 window 方法在每个位置提取特征。然后将这些功能与每个模型进行比较。如果其中一个模型的得分高于某个阈值,则您已找到该对象。如果不止一个模型得分高于阈值,则只取得分最高的一个。
如果您想使用不同大小的检测 windows,您将获得不同大小的特征向量(根据 HoG 特征的性质)。棘手的是,在测试阶段,您必须使用与您使用的对象类型一样多的滑动 windows。这肯定有效,但您必须多次处理每个测试图像,导致处理时间更长)
回答你的尺寸问题:我没有什么价值可以给你,它总是取决于你的图像。使用上面提到的图像金字塔是处理不同比例对象的好方法。
- window 大小:整个对象应该适合;必须能被块大小整除
- 块大小必须能被像元大小整除
可以找到 HoG 特征可视化的示例代码 here。这也有助于理解特征向量的样子。
编辑: 艰难地发现,单元格大小只允许 cv::Size(8,8)
。参见 documentation。