Commit 8257dc3c authored by Vladislav Vinogradov's avatar Vladislav Vinogradov

refactor CUDA HOG algorithm:

use abstract interface with hidden implementation
parent 0af7597d
......@@ -71,10 +71,10 @@ PERF_TEST_P(Image, ObjDetect_HOG,
const cv::cuda::GpuMat d_img(img);
std::vector<cv::Rect> gpu_found_locations;
cv::cuda::HOGDescriptor d_hog;
d_hog.setSVMDetector(cv::cuda::HOGDescriptor::getDefaultPeopleDetector());
cv::Ptr<cv::cuda::HOG> d_hog = cv::cuda::HOG::create();
d_hog->setSVMDetector(d_hog->getDefaultPeopleDetector());
TEST_CYCLE() d_hog.detectMultiScale(d_img, gpu_found_locations);
TEST_CYCLE() d_hog->detectMultiScale(d_img, gpu_found_locations);
SANITY_CHECK(gpu_found_locations);
}
......@@ -82,8 +82,10 @@ PERF_TEST_P(Image, ObjDetect_HOG,
{
std::vector<cv::Rect> cpu_found_locations;
cv::Ptr<cv::cuda::HOG> d_hog = cv::cuda::HOG::create();
cv::HOGDescriptor hog;
hog.setSVMDetector(cv::cuda::HOGDescriptor::getDefaultPeopleDetector());
hog.setSVMDetector(d_hog->getDefaultPeopleDetector());
TEST_CYCLE() hog.detectMultiScale(img, cpu_found_locations);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -48,9 +48,10 @@ using namespace cvtest;
//#define DUMP
struct HOG : testing::TestWithParam<cv::cuda::DeviceInfo>, cv::cuda::HOGDescriptor
struct HOG : testing::TestWithParam<cv::cuda::DeviceInfo>
{
cv::cuda::DeviceInfo devInfo;
cv::Ptr<cv::cuda::HOG> hog;
#ifdef DUMP
std::ofstream f;
......@@ -69,23 +70,13 @@ struct HOG : testing::TestWithParam<cv::cuda::DeviceInfo>, cv::cuda::HOGDescript
devInfo = GetParam();
cv::cuda::setDevice(devInfo.deviceID());
hog = cv::cuda::HOG::create();
}
#ifdef DUMP
void dump(const cv::Mat& blockHists, const std::vector<cv::Point>& locations)
void dump(const std::vector<cv::Point>& locations)
{
f.write((char*)&blockHists.rows, sizeof(blockHists.rows));
f.write((char*)&blockHists.cols, sizeof(blockHists.cols));
for (int i = 0; i < blockHists.rows; ++i)
{
for (int j = 0; j < blockHists.cols; ++j)
{
float val = blockHists.at<float>(i, j);
f.write((char*)&val, sizeof(val));
}
}
int nlocations = locations.size();
f.write((char*)&nlocations, sizeof(nlocations));
......@@ -93,21 +84,18 @@ struct HOG : testing::TestWithParam<cv::cuda::DeviceInfo>, cv::cuda::HOGDescript
f.write((char*)&locations[i], sizeof(locations[i]));
}
#else
void compare(const cv::Mat& blockHists, const std::vector<cv::Point>& locations)
void compare(const std::vector<cv::Point>& locations)
{
// skip block_hists check
int rows, cols;
f.read((char*)&rows, sizeof(rows));
f.read((char*)&cols, sizeof(cols));
ASSERT_EQ(rows, blockHists.rows);
ASSERT_EQ(cols, blockHists.cols);
for (int i = 0; i < blockHists.rows; ++i)
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < blockHists.cols; ++j)
for (int j = 0; j < cols; ++j)
{
float val;
f.read((char*)&val, sizeof(val));
ASSERT_NEAR(val, blockHists.at<float>(i, j), 1e-3);
}
}
......@@ -126,54 +114,41 @@ struct HOG : testing::TestWithParam<cv::cuda::DeviceInfo>, cv::cuda::HOGDescript
void testDetect(const cv::Mat& img)
{
gamma_correction = false;
setSVMDetector(cv::cuda::HOGDescriptor::getDefaultPeopleDetector());
hog->setGammaCorrection(false);
hog->setSVMDetector(hog->getDefaultPeopleDetector());
std::vector<cv::Point> locations;
// Test detect
detect(loadMat(img), locations, 0);
hog->detect(loadMat(img), locations);
#ifdef DUMP
dump(cv::Mat(block_hists), locations);
dump(locations);
#else
compare(cv::Mat(block_hists), locations);
compare(locations);
#endif
// Test detect on smaller image
cv::Mat img2;
cv::resize(img, img2, cv::Size(img.cols / 2, img.rows / 2));
detect(loadMat(img2), locations, 0);
hog->detect(loadMat(img2), locations);
#ifdef DUMP
dump(cv::Mat(block_hists), locations);
dump(locations);
#else
compare(cv::Mat(block_hists), locations);
compare(locations);
#endif
// Test detect on greater image
cv::resize(img, img2, cv::Size(img.cols * 2, img.rows * 2));
detect(loadMat(img2), locations, 0);
hog->detect(loadMat(img2), locations);
#ifdef DUMP
dump(cv::Mat(block_hists), locations);
dump(locations);
#else
compare(cv::Mat(block_hists), locations);
compare(locations);
#endif
}
// Does not compare border value, as interpolation leads to delta
void compare_inner_parts(cv::Mat d1, cv::Mat d2)
{
for (int i = 1; i < blocks_per_win_y - 1; ++i)
for (int j = 1; j < blocks_per_win_x - 1; ++j)
for (int k = 0; k < block_hist_size; ++k)
{
float a = d1.at<float>(0, (i * blocks_per_win_x + j) * block_hist_size);
float b = d2.at<float>(0, (i * blocks_per_win_x + j) * block_hist_size);
ASSERT_FLOAT_EQ(a, b);
}
}
};
// desabled while resize does not fixed
......@@ -182,13 +157,8 @@ CUDA_TEST_P(HOG, DISABLED_Detect)
cv::Mat img_rgb = readImage("hog/road.png");
ASSERT_FALSE(img_rgb.empty());
#ifdef DUMP
f.open((std::string(cvtest::TS::ptr()->get_data_path()) + "hog/expected_output.bin").c_str(), std::ios_base::binary);
ASSERT_TRUE(f.is_open());
#else
f.open((std::string(cvtest::TS::ptr()->get_data_path()) + "hog/expected_output.bin").c_str(), std::ios_base::binary);
ASSERT_TRUE(f.is_open());
#endif
// Test on color image
cv::Mat img;
......@@ -198,8 +168,6 @@ CUDA_TEST_P(HOG, DISABLED_Detect)
// Test on gray image
cv::cvtColor(img_rgb, img, cv::COLOR_BGR2GRAY);
testDetect(img);
f.close();
}
CUDA_TEST_P(HOG, GetDescriptors)
......@@ -216,8 +184,14 @@ CUDA_TEST_P(HOG, GetDescriptors)
// Convert train images into feature vectors (train table)
cv::cuda::GpuMat descriptors, descriptors_by_cols;
getDescriptors(d_img, win_size, descriptors, DESCR_FORMAT_ROW_BY_ROW);
getDescriptors(d_img, win_size, descriptors_by_cols, DESCR_FORMAT_COL_BY_COL);
hog->setWinStride(Size(64, 128));
hog->setDescriptorFormat(cv::cuda::HOG::DESCR_FORMAT_ROW_BY_ROW);
hog->compute(d_img, descriptors);
hog->setDescriptorFormat(cv::cuda::HOG::DESCR_FORMAT_COL_BY_COL);
hog->compute(d_img, descriptors_by_cols);
// Check size of the result train table
wins_per_img_x = 3;
......@@ -242,48 +216,6 @@ CUDA_TEST_P(HOG, GetDescriptors)
ASSERT_EQ(l[(y * blocks_per_win_x + x) * block_hist_size + k],
r[(x * blocks_per_win_y + y) * block_hist_size + k]);
}
/* Now we want to extract the same feature vectors, but from single images. NOTE: results will
be defferent, due to border values interpolation. Using of many small images is slower, however we
wont't call getDescriptors and will use computeBlockHistograms instead of. computeBlockHistograms
works good, it can be checked in the gpu_hog sample */
img_rgb = readImage("hog/positive1.png");
ASSERT_TRUE(!img_rgb.empty());
cv::cvtColor(img_rgb, img, cv::COLOR_BGR2BGRA);
computeBlockHistograms(cv::cuda::GpuMat(img));
// Everything is fine with interpolation for left top subimage
ASSERT_EQ(0.0, cv::norm((cv::Mat)block_hists, (cv::Mat)descriptors.rowRange(0, 1)));
img_rgb = readImage("hog/positive2.png");
ASSERT_TRUE(!img_rgb.empty());
cv::cvtColor(img_rgb, img, cv::COLOR_BGR2BGRA);
computeBlockHistograms(cv::cuda::GpuMat(img));
compare_inner_parts(cv::Mat(block_hists), cv::Mat(descriptors.rowRange(1, 2)));
img_rgb = readImage("hog/negative1.png");
ASSERT_TRUE(!img_rgb.empty());
cv::cvtColor(img_rgb, img, cv::COLOR_BGR2BGRA);
computeBlockHistograms(cv::cuda::GpuMat(img));
compare_inner_parts(cv::Mat(block_hists), cv::Mat(descriptors.rowRange(2, 3)));
img_rgb = readImage("hog/negative2.png");
ASSERT_TRUE(!img_rgb.empty());
cv::cvtColor(img_rgb, img, cv::COLOR_BGR2BGRA);
computeBlockHistograms(cv::cuda::GpuMat(img));
compare_inner_parts(cv::Mat(block_hists), cv::Mat(descriptors.rowRange(3, 4)));
img_rgb = readImage("hog/positive3.png");
ASSERT_TRUE(!img_rgb.empty());
cv::cvtColor(img_rgb, img, cv::COLOR_BGR2BGRA);
computeBlockHistograms(cv::cuda::GpuMat(img));
compare_inner_parts(cv::Mat(block_hists), cv::Mat(descriptors.rowRange(4, 5)));
img_rgb = readImage("hog/negative3.png");
ASSERT_TRUE(!img_rgb.empty());
cv::cvtColor(img_rgb, img, cv::COLOR_BGR2BGRA);
computeBlockHistograms(cv::cuda::GpuMat(img));
compare_inner_parts(cv::Mat(block_hists), cv::Mat(descriptors.rowRange(5, 6)));
}
INSTANTIATE_TEST_CASE_P(CUDA_ObjDetect, HOG, ALL_DEVICES);
......@@ -310,12 +242,12 @@ CUDA_TEST_P(CalTech, HOG)
cv::cuda::GpuMat d_img(img);
cv::Mat markedImage(img.clone());
cv::cuda::HOGDescriptor d_hog;
d_hog.setSVMDetector(cv::cuda::HOGDescriptor::getDefaultPeopleDetector());
d_hog.nlevels = d_hog.nlevels + 32;
cv::Ptr<cv::cuda::HOG> d_hog = cv::cuda::HOG::create();
d_hog->setSVMDetector(d_hog->getDefaultPeopleDetector());
d_hog->setNumLevels(d_hog->getNumLevels() + 32);
std::vector<cv::Rect> found_locations;
d_hog.detectMultiScale(d_img, found_locations);
d_hog->detectMultiScale(d_img, found_locations);
#if defined (LOG_CASCADE_STATISTIC)
for (int i = 0; i < (int)found_locations.size(); i++)
......@@ -326,7 +258,8 @@ CUDA_TEST_P(CalTech, HOG)
cv::rectangle(markedImage, r , CV_RGB(255, 0, 0));
}
cv::imshow("Res", markedImage); cv::waitKey();
cv::imshow("Res", markedImage);
cv::waitKey();
#endif
}
......
......@@ -244,19 +244,13 @@ void App::run()
Size win_size(args.win_width, args.win_width * 2); //(64, 128) or (48, 96)
Size win_stride(args.win_stride_width, args.win_stride_height);
cv::Ptr<cv::cuda::HOG> gpu_hog = cv::cuda::HOG::create(win_size);
cv::HOGDescriptor cpu_hog(win_size, Size(16, 16), Size(8, 8), Size(8, 8), 9);
// Create HOG descriptors and detectors here
vector<float> detector;
if (win_size == Size(64, 128))
detector = cv::cuda::HOGDescriptor::getPeopleDetector64x128();
else
detector = cv::cuda::HOGDescriptor::getPeopleDetector48x96();
cv::cuda::HOGDescriptor gpu_hog(win_size, Size(16, 16), Size(8, 8), Size(8, 8), 9,
cv::cuda::HOGDescriptor::DEFAULT_WIN_SIGMA, 0.2, gamma_corr,
cv::cuda::HOGDescriptor::DEFAULT_NLEVELS);
cv::HOGDescriptor cpu_hog(win_size, Size(16, 16), Size(8, 8), Size(8, 8), 9, 1, -1,
HOGDescriptor::L2Hys, 0.2, gamma_corr, cv::HOGDescriptor::DEFAULT_NLEVELS);
gpu_hog.setSVMDetector(detector);
Mat detector = gpu_hog->getDefaultPeopleDetector();
gpu_hog->setSVMDetector(detector);
cpu_hog.setSVMDetector(detector);
while (running)
......@@ -307,9 +301,6 @@ void App::run()
else img = img_aux;
img_to_show = img;
gpu_hog.nlevels = nlevels;
cpu_hog.nlevels = nlevels;
vector<Rect> found;
// Perform HOG classification
......@@ -317,11 +308,19 @@ void App::run()
if (use_gpu)
{
gpu_img.upload(img);
gpu_hog.detectMultiScale(gpu_img, found, hit_threshold, win_stride,
Size(0, 0), scale, gr_threshold);
gpu_hog->setNumLevels(nlevels);
gpu_hog->setHitThreshold(hit_threshold);
gpu_hog->setWinStride(win_stride);
gpu_hog->setScaleFactor(scale);
gpu_hog->setGroupThreshold(gr_threshold);
gpu_hog->detectMultiScale(gpu_img, found);
}
else cpu_hog.detectMultiScale(img, found, hit_threshold, win_stride,
else
{
cpu_hog.nlevels = nlevels;
cpu_hog.detectMultiScale(img, found, hit_threshold, win_stride,
Size(0, 0), scale, gr_threshold);
}
hogWorkEnd();
// Draw positive classified windows
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment