|
|
|
@ -42,23 +42,12 @@ |
|
|
|
|
|
|
|
|
|
#include "precomp.hpp" |
|
|
|
|
|
|
|
|
|
using namespace cv; |
|
|
|
|
using namespace cv::cuda; |
|
|
|
|
|
|
|
|
|
#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) |
|
|
|
|
|
|
|
|
|
cv::cuda::HOGDescriptor::HOGDescriptor(Size, Size, Size, Size, int, double, double, bool, int) { throw_no_cuda(); } |
|
|
|
|
size_t cv::cuda::HOGDescriptor::getDescriptorSize() const { throw_no_cuda(); return 0; } |
|
|
|
|
size_t cv::cuda::HOGDescriptor::getBlockHistogramSize() const { throw_no_cuda(); return 0; } |
|
|
|
|
double cv::cuda::HOGDescriptor::getWinSigma() const { throw_no_cuda(); return 0; } |
|
|
|
|
bool cv::cuda::HOGDescriptor::checkDetectorSize() const { throw_no_cuda(); return false; } |
|
|
|
|
void cv::cuda::HOGDescriptor::setSVMDetector(const std::vector<float>&) { throw_no_cuda(); } |
|
|
|
|
void cv::cuda::HOGDescriptor::detect(const GpuMat&, std::vector<Point>&, double, Size, Size) { throw_no_cuda(); } |
|
|
|
|
void cv::cuda::HOGDescriptor::detectMultiScale(const GpuMat&, std::vector<Rect>&, double, Size, Size, double, int) { throw_no_cuda(); } |
|
|
|
|
void cv::cuda::HOGDescriptor::computeBlockHistograms(const GpuMat&) { throw_no_cuda(); } |
|
|
|
|
void cv::cuda::HOGDescriptor::getDescriptors(const GpuMat&, Size, GpuMat&, int) { throw_no_cuda(); } |
|
|
|
|
std::vector<float> cv::cuda::HOGDescriptor::getDefaultPeopleDetector() { throw_no_cuda(); return std::vector<float>(); } |
|
|
|
|
std::vector<float> cv::cuda::HOGDescriptor::getPeopleDetector48x96() { throw_no_cuda(); return std::vector<float>(); } |
|
|
|
|
std::vector<float> cv::cuda::HOGDescriptor::getPeopleDetector64x128() { throw_no_cuda(); return std::vector<float>(); } |
|
|
|
|
void cv::cuda::HOGDescriptor::computeConfidence(const GpuMat&, std::vector<Point>&, double, Size, Size, std::vector<Point>&, std::vector<double>&) { throw_no_cuda(); } |
|
|
|
|
void cv::cuda::HOGDescriptor::computeConfidenceMultiScale(const GpuMat&, std::vector<Rect>&, double, Size, Size, std::vector<HOGConfidence>&, int) { throw_no_cuda(); } |
|
|
|
|
Ptr<cuda::HOG> cv::cuda::HOG::create(Size, Size, Size, Size, int) { throw_no_cuda(); return Ptr<cuda::HOG>(); } |
|
|
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
|
@ -102,244 +91,323 @@ namespace cv { namespace cuda { namespace device |
|
|
|
|
} |
|
|
|
|
}}} |
|
|
|
|
|
|
|
|
|
using namespace ::cv::cuda::device; |
|
|
|
|
|
|
|
|
|
cv::cuda::HOGDescriptor::HOGDescriptor(Size win_size_, Size block_size_, Size block_stride_, Size cell_size_, |
|
|
|
|
int nbins_, double win_sigma_, double threshold_L2hys_, bool gamma_correction_, int nlevels_) |
|
|
|
|
: win_size(win_size_), |
|
|
|
|
block_size(block_size_), |
|
|
|
|
block_stride(block_stride_), |
|
|
|
|
cell_size(cell_size_), |
|
|
|
|
nbins(nbins_), |
|
|
|
|
win_sigma(win_sigma_), |
|
|
|
|
threshold_L2hys(threshold_L2hys_), |
|
|
|
|
gamma_correction(gamma_correction_), |
|
|
|
|
nlevels(nlevels_) |
|
|
|
|
using namespace cv::cuda::device; |
|
|
|
|
|
|
|
|
|
namespace |
|
|
|
|
{ |
|
|
|
|
class HOG_Impl : public cv::cuda::HOG |
|
|
|
|
{ |
|
|
|
|
public: |
|
|
|
|
HOG_Impl(Size win_size, |
|
|
|
|
Size block_size, |
|
|
|
|
Size block_stride, |
|
|
|
|
Size cell_size, |
|
|
|
|
int nbins); |
|
|
|
|
|
|
|
|
|
virtual void setWinSigma(double win_sigma) { win_sigma_ = win_sigma; } |
|
|
|
|
virtual double getWinSigma() const; |
|
|
|
|
|
|
|
|
|
virtual void setL2HysThreshold(double threshold_L2hys) { threshold_L2hys_ = threshold_L2hys; } |
|
|
|
|
virtual double getL2HysThreshold() const { return threshold_L2hys_; } |
|
|
|
|
|
|
|
|
|
virtual void setGammaCorrection(bool gamma_correction) { gamma_correction_ = gamma_correction; } |
|
|
|
|
virtual bool getGammaCorrection() const { return gamma_correction_; } |
|
|
|
|
|
|
|
|
|
virtual void setNumLevels(int nlevels) { nlevels_ = nlevels; } |
|
|
|
|
virtual int getNumLevels() const { return nlevels_; } |
|
|
|
|
|
|
|
|
|
virtual void setHitThreshold(double hit_threshold) { hit_threshold_ = hit_threshold; } |
|
|
|
|
virtual double getHitThreshold() const { return hit_threshold_; } |
|
|
|
|
|
|
|
|
|
virtual void setWinStride(Size win_stride) { win_stride_ = win_stride; } |
|
|
|
|
virtual Size getWinStride() const { return win_stride_; } |
|
|
|
|
|
|
|
|
|
virtual void setScaleFactor(double scale0) { scale0_ = scale0; } |
|
|
|
|
virtual double getScaleFactor() const { return scale0_; } |
|
|
|
|
|
|
|
|
|
virtual void setGroupThreshold(int group_threshold) { group_threshold_ = group_threshold; } |
|
|
|
|
virtual int getGroupThreshold() const { return group_threshold_; } |
|
|
|
|
|
|
|
|
|
virtual void setDescriptorFormat(int descr_format) { descr_format_ = descr_format; } |
|
|
|
|
virtual int getDescriptorFormat() const { return descr_format_; } |
|
|
|
|
|
|
|
|
|
virtual size_t getDescriptorSize() const; |
|
|
|
|
|
|
|
|
|
virtual size_t getBlockHistogramSize() const; |
|
|
|
|
|
|
|
|
|
virtual void setSVMDetector(InputArray detector); |
|
|
|
|
|
|
|
|
|
virtual Mat getDefaultPeopleDetector() const; |
|
|
|
|
|
|
|
|
|
virtual void detect(InputArray img, |
|
|
|
|
std::vector<Point>& found_locations, |
|
|
|
|
std::vector<double>* confidences); |
|
|
|
|
|
|
|
|
|
virtual void detectMultiScale(InputArray img, |
|
|
|
|
std::vector<Rect>& found_locations, |
|
|
|
|
std::vector<double>* confidences); |
|
|
|
|
|
|
|
|
|
virtual void compute(InputArray img, |
|
|
|
|
OutputArray descriptors, |
|
|
|
|
Stream& stream); |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
Size win_size_; |
|
|
|
|
Size block_size_; |
|
|
|
|
Size block_stride_; |
|
|
|
|
Size cell_size_; |
|
|
|
|
int nbins_; |
|
|
|
|
|
|
|
|
|
double win_sigma_; |
|
|
|
|
double threshold_L2hys_; |
|
|
|
|
bool gamma_correction_; |
|
|
|
|
int nlevels_; |
|
|
|
|
double hit_threshold_; |
|
|
|
|
Size win_stride_; |
|
|
|
|
double scale0_; |
|
|
|
|
int group_threshold_; |
|
|
|
|
int descr_format_; |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
int getTotalHistSize(Size img_size) const; |
|
|
|
|
void computeBlockHistograms(const GpuMat& img, GpuMat& block_hists); |
|
|
|
|
void computeGradient(const GpuMat& img, GpuMat& grad, GpuMat& qangle); |
|
|
|
|
|
|
|
|
|
// Coefficients of the separating plane
|
|
|
|
|
float free_coef_; |
|
|
|
|
GpuMat detector_; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
HOG_Impl::HOG_Impl(Size win_size, |
|
|
|
|
Size block_size, |
|
|
|
|
Size block_stride, |
|
|
|
|
Size cell_size, |
|
|
|
|
int nbins) : |
|
|
|
|
win_size_(win_size), |
|
|
|
|
block_size_(block_size), |
|
|
|
|
block_stride_(block_stride), |
|
|
|
|
cell_size_(cell_size), |
|
|
|
|
nbins_(nbins), |
|
|
|
|
|
|
|
|
|
win_sigma_(-1.0), |
|
|
|
|
threshold_L2hys_(0.2), |
|
|
|
|
gamma_correction_(true), |
|
|
|
|
nlevels_(64), |
|
|
|
|
hit_threshold_(0.0), |
|
|
|
|
win_stride_(block_stride), |
|
|
|
|
scale0_(1.05), |
|
|
|
|
group_threshold_(2), |
|
|
|
|
descr_format_(DESCR_FORMAT_COL_BY_COL) |
|
|
|
|
{ |
|
|
|
|
CV_Assert((win_size.width - block_size.width ) % block_stride.width == 0 && |
|
|
|
|
(win_size.height - block_size.height) % block_stride.height == 0); |
|
|
|
|
|
|
|
|
|
CV_Assert(block_size.width % cell_size.width == 0 && block_size.height % cell_size.height == 0); |
|
|
|
|
CV_Assert(block_size.width % cell_size.width == 0 && |
|
|
|
|
block_size.height % cell_size.height == 0); |
|
|
|
|
|
|
|
|
|
CV_Assert(block_stride == cell_size); |
|
|
|
|
|
|
|
|
|
CV_Assert(cell_size == Size(8, 8)); |
|
|
|
|
|
|
|
|
|
Size cells_per_block = Size(block_size.width / cell_size.width, block_size.height / cell_size.height); |
|
|
|
|
Size cells_per_block(block_size.width / cell_size.width, block_size.height / cell_size.height); |
|
|
|
|
CV_Assert(cells_per_block == Size(2, 2)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
size_t cv::cuda::HOGDescriptor::getDescriptorSize() const |
|
|
|
|
static int numPartsWithin(int size, int part_size, int stride) |
|
|
|
|
{ |
|
|
|
|
return numPartsWithin(win_size, block_size, block_stride).area() * getBlockHistogramSize(); |
|
|
|
|
return (size - part_size + stride) / stride; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
size_t cv::cuda::HOGDescriptor::getBlockHistogramSize() const |
|
|
|
|
static Size numPartsWithin(Size size, Size part_size, Size stride) |
|
|
|
|
{ |
|
|
|
|
Size cells_per_block = Size(block_size.width / cell_size.width, block_size.height / cell_size.height); |
|
|
|
|
return (size_t)(nbins * cells_per_block.area()); |
|
|
|
|
return Size(numPartsWithin(size.width, part_size.width, stride.width), |
|
|
|
|
numPartsWithin(size.height, part_size.height, stride.height)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
double cv::cuda::HOGDescriptor::getWinSigma() const |
|
|
|
|
size_t HOG_Impl::getDescriptorSize() const |
|
|
|
|
{ |
|
|
|
|
return win_sigma >= 0 ? win_sigma : (block_size.width + block_size.height) / 8.0; |
|
|
|
|
return numPartsWithin(win_size_, block_size_, block_stride_).area() * getBlockHistogramSize(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool cv::cuda::HOGDescriptor::checkDetectorSize() const |
|
|
|
|
size_t HOG_Impl::getBlockHistogramSize() const |
|
|
|
|
{ |
|
|
|
|
size_t detector_size = detector.rows * detector.cols; |
|
|
|
|
size_t descriptor_size = getDescriptorSize(); |
|
|
|
|
return detector_size == 0 || detector_size == descriptor_size || detector_size == descriptor_size + 1; |
|
|
|
|
Size cells_per_block(block_size_.width / cell_size_.width, block_size_.height / cell_size_.height); |
|
|
|
|
return nbins_ * cells_per_block.area(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void cv::cuda::HOGDescriptor::setSVMDetector(const std::vector<float>& _detector) |
|
|
|
|
double HOG_Impl::getWinSigma() const |
|
|
|
|
{ |
|
|
|
|
std::vector<float> detector_reordered(_detector.size()); |
|
|
|
|
|
|
|
|
|
size_t block_hist_size = getBlockHistogramSize(); |
|
|
|
|
cv::Size blocks_per_img = numPartsWithin(win_size, block_size, block_stride); |
|
|
|
|
return win_sigma_ >= 0 ? win_sigma_ : (block_size_.width + block_size_.height) / 8.0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < blocks_per_img.height; ++i) |
|
|
|
|
for (int j = 0; j < blocks_per_img.width; ++j) |
|
|
|
|
void HOG_Impl::setSVMDetector(InputArray _detector) |
|
|
|
|
{ |
|
|
|
|
const float* src = &_detector[0] + (j * blocks_per_img.height + i) * block_hist_size; |
|
|
|
|
float* dst = &detector_reordered[0] + (i * blocks_per_img.width + j) * block_hist_size; |
|
|
|
|
for (size_t k = 0; k < block_hist_size; ++k) |
|
|
|
|
dst[k] = src[k]; |
|
|
|
|
} |
|
|
|
|
const int descriptor_size = static_cast<int>(getDescriptorSize()); |
|
|
|
|
|
|
|
|
|
this->detector.upload(Mat(detector_reordered).reshape(1, 1)); |
|
|
|
|
const Mat detector = _detector.getMat(); |
|
|
|
|
|
|
|
|
|
size_t descriptor_size = getDescriptorSize(); |
|
|
|
|
free_coef = _detector.size() > descriptor_size ? _detector[descriptor_size] : 0; |
|
|
|
|
CV_Assert( detector.type() == CV_32FC1 ); |
|
|
|
|
CV_Assert( detector.rows == 1 ); |
|
|
|
|
CV_Assert( detector.cols == descriptor_size || detector.cols == descriptor_size + 1 ); |
|
|
|
|
|
|
|
|
|
CV_Assert(checkDetectorSize()); |
|
|
|
|
} |
|
|
|
|
std::vector<float> detector_reordered(detector.ptr<float>(), detector.ptr<float>() + detector.cols); |
|
|
|
|
|
|
|
|
|
cv::cuda::GpuMat cv::cuda::HOGDescriptor::getBuffer(const Size& sz, int type, GpuMat& buf) |
|
|
|
|
{ |
|
|
|
|
if (buf.empty() || buf.type() != type) |
|
|
|
|
buf.create(sz, type); |
|
|
|
|
else |
|
|
|
|
if (buf.cols < sz.width || buf.rows < sz.height) |
|
|
|
|
buf.create(std::max(buf.rows, sz.height), std::max(buf.cols, sz.width), type); |
|
|
|
|
size_t block_hist_size = getBlockHistogramSize(); |
|
|
|
|
Size blocks_per_win = numPartsWithin(win_size_, block_size_, block_stride_); |
|
|
|
|
|
|
|
|
|
return buf(Rect(Point(0,0), sz)); |
|
|
|
|
for (int i = 0; i < blocks_per_win.height; ++i) |
|
|
|
|
{ |
|
|
|
|
for (int j = 0; j < blocks_per_win.width; ++j) |
|
|
|
|
{ |
|
|
|
|
const float* src = detector.ptr<float>() + (j * blocks_per_win.height + i) * block_hist_size; |
|
|
|
|
float* dst = &detector_reordered[0] + (i * blocks_per_win.width + j) * block_hist_size; |
|
|
|
|
for (size_t k = 0; k < block_hist_size; ++k) |
|
|
|
|
dst[k] = src[k]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
cv::cuda::GpuMat cv::cuda::HOGDescriptor::getBuffer(int rows, int cols, int type, GpuMat& buf) |
|
|
|
|
{ |
|
|
|
|
return getBuffer(Size(cols, rows), type, buf); |
|
|
|
|
detector_.upload(Mat(detector_reordered).reshape(1, 1)); |
|
|
|
|
free_coef_ = detector.cols > descriptor_size ? detector.at<float>(0, descriptor_size) : 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static Mat getPeopleDetector64x128(); |
|
|
|
|
static Mat getPeopleDetector48x96(); |
|
|
|
|
|
|
|
|
|
void cv::cuda::HOGDescriptor::computeGradient(const GpuMat& img, GpuMat& _grad, GpuMat& _qangle) |
|
|
|
|
Mat HOG_Impl::getDefaultPeopleDetector() const |
|
|
|
|
{ |
|
|
|
|
CV_Assert(img.type() == CV_8UC1 || img.type() == CV_8UC4); |
|
|
|
|
|
|
|
|
|
// grad.create(img.size(), CV_32FC2);
|
|
|
|
|
_grad = getBuffer(img.size(), CV_32FC2, grad_buf); |
|
|
|
|
|
|
|
|
|
// qangle.create(img.size(), CV_8UC2);
|
|
|
|
|
_qangle = getBuffer(img.size(), CV_8UC2, qangle_buf); |
|
|
|
|
CV_Assert( win_size_ == Size(64, 128) || win_size_ == Size(48, 96) ); |
|
|
|
|
|
|
|
|
|
float angleScale = (float)(nbins / CV_PI); |
|
|
|
|
switch (img.type()) |
|
|
|
|
{ |
|
|
|
|
case CV_8UC1: |
|
|
|
|
hog::compute_gradients_8UC1(nbins, img.rows, img.cols, img, angleScale, _grad, _qangle, gamma_correction); |
|
|
|
|
break; |
|
|
|
|
case CV_8UC4: |
|
|
|
|
hog::compute_gradients_8UC4(nbins, img.rows, img.cols, img, angleScale, _grad, _qangle, gamma_correction); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
if (win_size_ == Size(64, 128)) |
|
|
|
|
return getPeopleDetector64x128(); |
|
|
|
|
else |
|
|
|
|
return getPeopleDetector48x96(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cv::cuda::HOGDescriptor::computeBlockHistograms(const GpuMat& img) |
|
|
|
|
void HOG_Impl::detect(InputArray _img, std::vector<Point>& hits, std::vector<double>* confidences) |
|
|
|
|
{ |
|
|
|
|
cv::Size blocks_per_win = numPartsWithin(win_size, block_size, block_stride); |
|
|
|
|
hog::set_up_constants(nbins, block_stride.width, block_stride.height, blocks_per_win.width, blocks_per_win.height); |
|
|
|
|
const GpuMat img = _img.getGpuMat(); |
|
|
|
|
|
|
|
|
|
computeGradient(img, grad, qangle); |
|
|
|
|
|
|
|
|
|
size_t block_hist_size = getBlockHistogramSize(); |
|
|
|
|
Size blocks_per_img = numPartsWithin(img.size(), block_size, block_stride); |
|
|
|
|
CV_Assert( img.type() == CV_8UC1 || img.type() == CV_8UC4 ); |
|
|
|
|
CV_Assert( win_stride_.width % block_stride_.width == 0 && win_stride_.height % block_stride_.height == 0 ); |
|
|
|
|
|
|
|
|
|
// block_hists.create(1, block_hist_size * blocks_per_img.area(), CV_32F);
|
|
|
|
|
block_hists = getBuffer(1, static_cast<int>(block_hist_size * blocks_per_img.area()), CV_32F, block_hists_buf); |
|
|
|
|
hits.clear(); |
|
|
|
|
if (detector_.empty()) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
hog::compute_hists(nbins, block_stride.width, block_stride.height, img.rows, img.cols, |
|
|
|
|
grad, qangle, (float)getWinSigma(), block_hists.ptr<float>()); |
|
|
|
|
BufferPool pool(Stream::Null()); |
|
|
|
|
|
|
|
|
|
hog::normalize_hists(nbins, block_stride.width, block_stride.height, img.rows, img.cols, |
|
|
|
|
block_hists.ptr<float>(), (float)threshold_L2hys); |
|
|
|
|
} |
|
|
|
|
GpuMat block_hists = pool.getBuffer(1, getTotalHistSize(img.size()), CV_32FC1); |
|
|
|
|
computeBlockHistograms(img, block_hists); |
|
|
|
|
|
|
|
|
|
Size wins_per_img = numPartsWithin(img.size(), win_size_, win_stride_); |
|
|
|
|
|
|
|
|
|
void cv::cuda::HOGDescriptor::getDescriptors(const GpuMat& img, Size win_stride, GpuMat& descriptors, int descr_format) |
|
|
|
|
if (confidences == NULL) |
|
|
|
|
{ |
|
|
|
|
CV_Assert(win_stride.width % block_stride.width == 0 && win_stride.height % block_stride.height == 0); |
|
|
|
|
|
|
|
|
|
computeBlockHistograms(img); |
|
|
|
|
|
|
|
|
|
const size_t block_hist_size = getBlockHistogramSize(); |
|
|
|
|
Size blocks_per_win = numPartsWithin(win_size, block_size, block_stride); |
|
|
|
|
Size wins_per_img = numPartsWithin(img.size(), win_size, win_stride); |
|
|
|
|
|
|
|
|
|
descriptors.create(wins_per_img.area(), static_cast<int>(blocks_per_win.area() * block_hist_size), CV_32F); |
|
|
|
|
GpuMat labels = pool.getBuffer(1, wins_per_img.area(), CV_8UC1); |
|
|
|
|
|
|
|
|
|
hog::classify_hists(win_size_.height, win_size_.width, |
|
|
|
|
block_stride_.height, block_stride_.width, |
|
|
|
|
win_stride_.height, win_stride_.width, |
|
|
|
|
img.rows, img.cols, |
|
|
|
|
block_hists.ptr<float>(), |
|
|
|
|
detector_.ptr<float>(), |
|
|
|
|
(float)free_coef_, |
|
|
|
|
(float)hit_threshold_, |
|
|
|
|
labels.ptr()); |
|
|
|
|
|
|
|
|
|
Mat labels_host; |
|
|
|
|
labels.download(labels_host); |
|
|
|
|
unsigned char* vec = labels_host.ptr(); |
|
|
|
|
|
|
|
|
|
switch (descr_format) |
|
|
|
|
for (int i = 0; i < wins_per_img.area(); i++) |
|
|
|
|
{ |
|
|
|
|
case DESCR_FORMAT_ROW_BY_ROW: |
|
|
|
|
hog::extract_descrs_by_rows(win_size.height, win_size.width, block_stride.height, block_stride.width, |
|
|
|
|
win_stride.height, win_stride.width, img.rows, img.cols, block_hists.ptr<float>(), descriptors); |
|
|
|
|
break; |
|
|
|
|
case DESCR_FORMAT_COL_BY_COL: |
|
|
|
|
hog::extract_descrs_by_cols(win_size.height, win_size.width, block_stride.height, block_stride.width, |
|
|
|
|
win_stride.height, win_stride.width, img.rows, img.cols, block_hists.ptr<float>(), descriptors); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
CV_Error(cv::Error::StsBadArg, "Unknown descriptor format"); |
|
|
|
|
int y = i / wins_per_img.width; |
|
|
|
|
int x = i - wins_per_img.width * y; |
|
|
|
|
if (vec[i]) |
|
|
|
|
hits.push_back(Point(x * win_stride_.width, y * win_stride_.height)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void cv::cuda::HOGDescriptor::computeConfidence(const GpuMat& img, std::vector<Point>& hits, double hit_threshold, |
|
|
|
|
Size win_stride, Size padding, std::vector<Point>& locations, std::vector<double>& confidences) |
|
|
|
|
{ |
|
|
|
|
CV_Assert(padding == Size(0, 0)); |
|
|
|
|
|
|
|
|
|
hits.clear(); |
|
|
|
|
if (detector.empty()) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
computeBlockHistograms(img); |
|
|
|
|
|
|
|
|
|
if (win_stride == Size()) |
|
|
|
|
win_stride = block_stride; |
|
|
|
|
else |
|
|
|
|
CV_Assert(win_stride.width % block_stride.width == 0 && |
|
|
|
|
win_stride.height % block_stride.height == 0); |
|
|
|
|
|
|
|
|
|
Size wins_per_img = numPartsWithin(img.size(), win_size, win_stride); |
|
|
|
|
labels.create(1, wins_per_img.area(), CV_32F); |
|
|
|
|
|
|
|
|
|
hog::compute_confidence_hists(win_size.height, win_size.width, block_stride.height, block_stride.width, |
|
|
|
|
win_stride.height, win_stride.width, img.rows, img.cols, block_hists.ptr<float>(), |
|
|
|
|
detector.ptr<float>(), (float)free_coef, (float)hit_threshold, labels.ptr<float>()); |
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
GpuMat labels = pool.getBuffer(1, wins_per_img.area(), CV_32FC1); |
|
|
|
|
|
|
|
|
|
hog::compute_confidence_hists(win_size_.height, win_size_.width, |
|
|
|
|
block_stride_.height, block_stride_.width, |
|
|
|
|
win_stride_.height, win_stride_.width, |
|
|
|
|
img.rows, img.cols, |
|
|
|
|
block_hists.ptr<float>(), |
|
|
|
|
detector_.ptr<float>(), |
|
|
|
|
(float)free_coef_, |
|
|
|
|
(float)hit_threshold_, |
|
|
|
|
labels.ptr<float>()); |
|
|
|
|
|
|
|
|
|
Mat labels_host; |
|
|
|
|
labels.download(labels_host); |
|
|
|
|
float* vec = labels_host.ptr<float>(); |
|
|
|
|
|
|
|
|
|
// does not support roi for now..
|
|
|
|
|
locations.clear(); |
|
|
|
|
confidences.clear(); |
|
|
|
|
confidences->clear(); |
|
|
|
|
for (int i = 0; i < wins_per_img.area(); i++) |
|
|
|
|
{ |
|
|
|
|
int y = i / wins_per_img.width; |
|
|
|
|
int x = i - wins_per_img.width * y; |
|
|
|
|
if (vec[i] >= hit_threshold) |
|
|
|
|
hits.push_back(Point(x * win_stride.width, y * win_stride.height)); |
|
|
|
|
|
|
|
|
|
Point pt(win_stride.width * x, win_stride.height * y); |
|
|
|
|
locations.push_back(pt); |
|
|
|
|
confidences.push_back((double)vec[i]); |
|
|
|
|
if (vec[i] >= hit_threshold_) |
|
|
|
|
{ |
|
|
|
|
hits.push_back(Point(x * win_stride_.width, y * win_stride_.height)); |
|
|
|
|
confidences->push_back((double)vec[i]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void cv::cuda::HOGDescriptor::computeConfidenceMultiScale(const GpuMat& img, std::vector<Rect>& found_locations, |
|
|
|
|
double hit_threshold, Size win_stride, Size padding, |
|
|
|
|
std::vector<HOGConfidence> &conf_out, int group_threshold) |
|
|
|
|
void HOG_Impl::detectMultiScale(InputArray _img, |
|
|
|
|
std::vector<Rect>& found_locations, |
|
|
|
|
std::vector<double>* confidences) |
|
|
|
|
{ |
|
|
|
|
const GpuMat img = _img.getGpuMat(); |
|
|
|
|
|
|
|
|
|
CV_Assert( img.type() == CV_8UC1 || img.type() == CV_8UC4 ); |
|
|
|
|
CV_Assert( confidences == NULL || group_threshold_ == 0 ); |
|
|
|
|
|
|
|
|
|
std::vector<double> level_scale; |
|
|
|
|
double scale = 1.; |
|
|
|
|
double scale = 1.0; |
|
|
|
|
int levels = 0; |
|
|
|
|
|
|
|
|
|
for (levels = 0; levels < (int)conf_out.size(); levels++) |
|
|
|
|
for (levels = 0; levels < nlevels_; levels++) |
|
|
|
|
{ |
|
|
|
|
scale = conf_out[levels].scale; |
|
|
|
|
level_scale.push_back(scale); |
|
|
|
|
if (cvRound(img.cols/scale) < win_size.width || cvRound(img.rows/scale) < win_size.height) |
|
|
|
|
|
|
|
|
|
if (cvRound(img.cols / scale) < win_size_.width || |
|
|
|
|
cvRound(img.rows / scale) < win_size_.height || |
|
|
|
|
scale0_ <= 1) |
|
|
|
|
{ |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
scale *= scale0_; |
|
|
|
|
} |
|
|
|
|
levels = std::max(levels, 1); |
|
|
|
|
level_scale.resize(levels); |
|
|
|
|
|
|
|
|
|
std::vector<Rect> all_candidates; |
|
|
|
|
std::vector<Point> locations; |
|
|
|
|
std::vector<Point> level_hits; |
|
|
|
|
std::vector<double> level_confidences; |
|
|
|
|
|
|
|
|
|
BufferPool pool(Stream::Null()); |
|
|
|
|
|
|
|
|
|
found_locations.clear(); |
|
|
|
|
for (size_t i = 0; i < level_scale.size(); i++) |
|
|
|
|
{ |
|
|
|
|
scale = level_scale[i]; |
|
|
|
|
|
|
|
|
|
Size sz(cvRound(img.cols / scale), cvRound(img.rows / scale)); |
|
|
|
|
GpuMat smaller_img; |
|
|
|
|
|
|
|
|
|
GpuMat smaller_img; |
|
|
|
|
if (sz == img.size()) |
|
|
|
|
{ |
|
|
|
|
smaller_img = img; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
smaller_img.create(sz, img.type()); |
|
|
|
|
smaller_img = pool.getBuffer(sz, img.type()); |
|
|
|
|
switch (img.type()) |
|
|
|
|
{ |
|
|
|
|
case CV_8UC1: hog::resize_8UC1(img, smaller_img); break; |
|
|
|
@ -347,127 +415,137 @@ void cv::cuda::HOGDescriptor::computeConfidenceMultiScale(const GpuMat& img, std |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
computeConfidence(smaller_img, locations, hit_threshold, win_stride, padding, conf_out[i].locations, conf_out[i].confidences); |
|
|
|
|
detect(smaller_img, level_hits, |
|
|
|
|
confidences ? &level_confidences : NULL); |
|
|
|
|
|
|
|
|
|
Size scaled_win_size(cvRound(win_size.width * scale), cvRound(win_size.height * scale)); |
|
|
|
|
for (size_t j = 0; j < locations.size(); j++) |
|
|
|
|
all_candidates.push_back(Rect(Point2d(locations[j]) * scale, scaled_win_size)); |
|
|
|
|
} |
|
|
|
|
Size scaled_win_size(cvRound(win_size_.width * scale), |
|
|
|
|
cvRound(win_size_.height * scale)); |
|
|
|
|
|
|
|
|
|
found_locations.assign(all_candidates.begin(), all_candidates.end()); |
|
|
|
|
groupRectangles(found_locations, group_threshold, 0.2/*magic number copied from CPU version*/); |
|
|
|
|
for (size_t j = 0; j < level_hits.size(); j++) |
|
|
|
|
{ |
|
|
|
|
found_locations.push_back(Rect(Point2d(level_hits[j]) * scale, scaled_win_size)); |
|
|
|
|
if (confidences) |
|
|
|
|
confidences->push_back(level_confidences[j]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (group_threshold_ > 0) |
|
|
|
|
{ |
|
|
|
|
groupRectangles(found_locations, group_threshold_, 0.2/*magic number copied from CPU version*/); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void cv::cuda::HOGDescriptor::detect(const GpuMat& img, std::vector<Point>& hits, double hit_threshold, Size win_stride, Size padding) |
|
|
|
|
void HOG_Impl::compute(InputArray _img, |
|
|
|
|
OutputArray _descriptors, |
|
|
|
|
Stream& stream) |
|
|
|
|
{ |
|
|
|
|
CV_Assert(img.type() == CV_8UC1 || img.type() == CV_8UC4); |
|
|
|
|
CV_Assert(padding == Size(0, 0)); |
|
|
|
|
const GpuMat img = _img.getGpuMat(); |
|
|
|
|
|
|
|
|
|
hits.clear(); |
|
|
|
|
if (detector.empty()) |
|
|
|
|
return; |
|
|
|
|
CV_Assert( img.type() == CV_8UC1 || img.type() == CV_8UC4 ); |
|
|
|
|
CV_Assert( win_stride_.width % block_stride_.width == 0 && win_stride_.height % block_stride_.height == 0 ); |
|
|
|
|
CV_Assert( !stream ); |
|
|
|
|
|
|
|
|
|
computeBlockHistograms(img); |
|
|
|
|
BufferPool pool(stream); |
|
|
|
|
|
|
|
|
|
if (win_stride == Size()) |
|
|
|
|
win_stride = block_stride; |
|
|
|
|
else |
|
|
|
|
CV_Assert(win_stride.width % block_stride.width == 0 && win_stride.height % block_stride.height == 0); |
|
|
|
|
GpuMat block_hists = pool.getBuffer(1, getTotalHistSize(img.size()), CV_32FC1); |
|
|
|
|
computeBlockHistograms(img, block_hists); |
|
|
|
|
|
|
|
|
|
Size wins_per_img = numPartsWithin(img.size(), win_size, win_stride); |
|
|
|
|
// labels.create(1, wins_per_img.area(), CV_8U);
|
|
|
|
|
labels = getBuffer(1, wins_per_img.area(), CV_8U, labels_buf); |
|
|
|
|
const size_t block_hist_size = getBlockHistogramSize(); |
|
|
|
|
Size blocks_per_win = numPartsWithin(win_size_, block_size_, block_stride_); |
|
|
|
|
Size wins_per_img = numPartsWithin(img.size(), win_size_, win_stride_); |
|
|
|
|
|
|
|
|
|
hog::classify_hists(win_size.height, win_size.width, block_stride.height, block_stride.width, |
|
|
|
|
win_stride.height, win_stride.width, img.rows, img.cols, block_hists.ptr<float>(), |
|
|
|
|
detector.ptr<float>(), (float)free_coef, (float)hit_threshold, labels.ptr()); |
|
|
|
|
_descriptors.create(wins_per_img.area(), static_cast<int>(blocks_per_win.area() * block_hist_size), CV_32FC1); |
|
|
|
|
GpuMat descriptors = _descriptors.getGpuMat(); |
|
|
|
|
|
|
|
|
|
labels.download(labels_host); |
|
|
|
|
unsigned char* vec = labels_host.ptr(); |
|
|
|
|
for (int i = 0; i < wins_per_img.area(); i++) |
|
|
|
|
switch (descr_format_) |
|
|
|
|
{ |
|
|
|
|
int y = i / wins_per_img.width; |
|
|
|
|
int x = i - wins_per_img.width * y; |
|
|
|
|
if (vec[i]) |
|
|
|
|
hits.push_back(Point(x * win_stride.width, y * win_stride.height)); |
|
|
|
|
case DESCR_FORMAT_ROW_BY_ROW: |
|
|
|
|
hog::extract_descrs_by_rows(win_size_.height, win_size_.width, |
|
|
|
|
block_stride_.height, block_stride_.width, |
|
|
|
|
win_stride_.height, win_stride_.width, |
|
|
|
|
img.rows, img.cols, |
|
|
|
|
block_hists.ptr<float>(), |
|
|
|
|
descriptors); |
|
|
|
|
break; |
|
|
|
|
case DESCR_FORMAT_COL_BY_COL: |
|
|
|
|
hog::extract_descrs_by_cols(win_size_.height, win_size_.width, |
|
|
|
|
block_stride_.height, block_stride_.width, |
|
|
|
|
win_stride_.height, win_stride_.width, |
|
|
|
|
img.rows, img.cols, |
|
|
|
|
block_hists.ptr<float>(), |
|
|
|
|
descriptors); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
CV_Error(cv::Error::StsBadArg, "Unknown descriptor format"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int HOG_Impl::getTotalHistSize(Size img_size) const |
|
|
|
|
{ |
|
|
|
|
size_t block_hist_size = getBlockHistogramSize(); |
|
|
|
|
Size blocks_per_img = numPartsWithin(img_size, block_size_, block_stride_); |
|
|
|
|
return static_cast<int>(block_hist_size * blocks_per_img.area()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cv::cuda::HOGDescriptor::detectMultiScale(const GpuMat& img, std::vector<Rect>& found_locations, double hit_threshold, |
|
|
|
|
Size win_stride, Size padding, double scale0, int group_threshold) |
|
|
|
|
void HOG_Impl::computeBlockHistograms(const GpuMat& img, GpuMat& block_hists) |
|
|
|
|
{ |
|
|
|
|
cv::Size blocks_per_win = numPartsWithin(win_size_, block_size_, block_stride_); |
|
|
|
|
hog::set_up_constants(nbins_, block_stride_.width, block_stride_.height, blocks_per_win.width, blocks_per_win.height); |
|
|
|
|
|
|
|
|
|
CV_Assert(img.type() == CV_8UC1 || img.type() == CV_8UC4); |
|
|
|
|
BufferPool pool(Stream::Null()); |
|
|
|
|
|
|
|
|
|
std::vector<double> level_scale; |
|
|
|
|
double scale = 1.; |
|
|
|
|
int levels = 0; |
|
|
|
|
GpuMat grad = pool.getBuffer(img.size(), CV_32FC2); |
|
|
|
|
GpuMat qangle = pool.getBuffer(img.size(), CV_8UC2); |
|
|
|
|
computeGradient(img, grad, qangle); |
|
|
|
|
|
|
|
|
|
for (levels = 0; levels < nlevels; levels++) |
|
|
|
|
{ |
|
|
|
|
level_scale.push_back(scale); |
|
|
|
|
if (cvRound(img.cols/scale) < win_size.width || |
|
|
|
|
cvRound(img.rows/scale) < win_size.height || scale0 <= 1) |
|
|
|
|
break; |
|
|
|
|
scale *= scale0; |
|
|
|
|
} |
|
|
|
|
levels = std::max(levels, 1); |
|
|
|
|
level_scale.resize(levels); |
|
|
|
|
image_scales.resize(levels); |
|
|
|
|
block_hists.create(1, getTotalHistSize(img.size()), CV_32FC1); |
|
|
|
|
|
|
|
|
|
std::vector<Rect> all_candidates; |
|
|
|
|
std::vector<Point> locations; |
|
|
|
|
hog::compute_hists(nbins_, |
|
|
|
|
block_stride_.width, block_stride_.height, |
|
|
|
|
img.rows, img.cols, |
|
|
|
|
grad, qangle, |
|
|
|
|
(float)getWinSigma(), |
|
|
|
|
block_hists.ptr<float>()); |
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < level_scale.size(); i++) |
|
|
|
|
{ |
|
|
|
|
scale = level_scale[i]; |
|
|
|
|
Size sz(cvRound(img.cols / scale), cvRound(img.rows / scale)); |
|
|
|
|
GpuMat smaller_img; |
|
|
|
|
hog::normalize_hists(nbins_, |
|
|
|
|
block_stride_.width, block_stride_.height, |
|
|
|
|
img.rows, img.cols, |
|
|
|
|
block_hists.ptr<float>(), |
|
|
|
|
(float)threshold_L2hys_); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (sz == img.size()) |
|
|
|
|
smaller_img = img; |
|
|
|
|
else |
|
|
|
|
void HOG_Impl::computeGradient(const GpuMat& img, GpuMat& grad, GpuMat& qangle) |
|
|
|
|
{ |
|
|
|
|
image_scales[i].create(sz, img.type()); |
|
|
|
|
grad.create(img.size(), CV_32FC2); |
|
|
|
|
qangle.create(img.size(), CV_8UC2); |
|
|
|
|
|
|
|
|
|
float angleScale = (float)(nbins_ / CV_PI); |
|
|
|
|
switch (img.type()) |
|
|
|
|
{ |
|
|
|
|
case CV_8UC1: hog::resize_8UC1(img, image_scales[i]); break; |
|
|
|
|
case CV_8UC4: hog::resize_8UC4(img, image_scales[i]); break; |
|
|
|
|
} |
|
|
|
|
smaller_img = image_scales[i]; |
|
|
|
|
case CV_8UC1: |
|
|
|
|
hog::compute_gradients_8UC1(nbins_, img.rows, img.cols, img, angleScale, grad, qangle, gamma_correction_); |
|
|
|
|
break; |
|
|
|
|
case CV_8UC4: |
|
|
|
|
hog::compute_gradients_8UC4(nbins_, img.rows, img.cols, img, angleScale, grad, qangle, gamma_correction_); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
detect(smaller_img, locations, hit_threshold, win_stride, padding); |
|
|
|
|
Size scaled_win_size(cvRound(win_size.width * scale), cvRound(win_size.height * scale)); |
|
|
|
|
for (size_t j = 0; j < locations.size(); j++) |
|
|
|
|
all_candidates.push_back(Rect(Point2d(locations[j]) * scale, scaled_win_size)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
found_locations.assign(all_candidates.begin(), all_candidates.end()); |
|
|
|
|
groupRectangles(found_locations, group_threshold, 0.2/*magic number copied from CPU version*/); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int cv::cuda::HOGDescriptor::numPartsWithin(int size, int part_size, int stride) |
|
|
|
|
Ptr<cuda::HOG> cv::cuda::HOG::create(Size win_size, |
|
|
|
|
Size block_size, |
|
|
|
|
Size block_stride, |
|
|
|
|
Size cell_size, |
|
|
|
|
int nbins) |
|
|
|
|
{ |
|
|
|
|
return (size - part_size + stride) / stride; |
|
|
|
|
return makePtr<HOG_Impl>(win_size, block_size, block_stride, cell_size, nbins); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
cv::Size cv::cuda::HOGDescriptor::numPartsWithin(cv::Size size, cv::Size part_size, cv::Size stride) |
|
|
|
|
namespace |
|
|
|
|
{ |
|
|
|
|
return Size(numPartsWithin(size.width, part_size.width, stride.width), numPartsWithin(size.height, part_size.height, stride.height)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::vector<float> cv::cuda::HOGDescriptor::getDefaultPeopleDetector() |
|
|
|
|
static Mat getPeopleDetector48x96() |
|
|
|
|
{ |
|
|
|
|
return getPeopleDetector64x128(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::vector<float> cv::cuda::HOGDescriptor::getPeopleDetector48x96() |
|
|
|
|
{ |
|
|
|
|
static const float detector[] = { |
|
|
|
|
static float detector[] = { |
|
|
|
|
0.294350f, -0.098796f, -0.129522f, 0.078753f, 0.387527f, 0.261529f, |
|
|
|
|
0.145939f, 0.061520f, 0.328699f, 0.227148f, -0.066467f, -0.086723f, |
|
|
|
|
0.047559f, 0.106714f, 0.037897f, 0.111461f, -0.024406f, 0.304769f, |
|
|
|
@ -799,15 +877,13 @@ std::vector<float> cv::cuda::HOGDescriptor::getPeopleDetector48x96() |
|
|
|
|
-0.119002f, 0.026722f, 0.034853f, -0.060934f, -0.025054f, -0.093026f, |
|
|
|
|
-0.035372f, -0.233209f, -0.049869f, -0.039151f, -0.022279f, -0.065380f, |
|
|
|
|
-9.063785f }; |
|
|
|
|
return std::vector<float>(detector, detector + sizeof(detector)/sizeof(detector[0])); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return Mat(1, static_cast<int>(sizeof(detector)/sizeof(detector[0])), CV_32FC1, detector); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::vector<float> cv::cuda::HOGDescriptor::getPeopleDetector64x128() |
|
|
|
|
Mat getPeopleDetector64x128() |
|
|
|
|
{ |
|
|
|
|
static const float detector[] = { |
|
|
|
|
static float detector[] = { |
|
|
|
|
0.05359386f, -0.14721455f, -0.05532170f, 0.05077307f, |
|
|
|
|
0.11547081f, -0.04268804f, 0.04635834f, -0.05468199f, 0.08232084f, |
|
|
|
|
0.10424068f, -0.02294518f, 0.01108519f, 0.01378693f, 0.11193510f, |
|
|
|
@ -1613,7 +1689,9 @@ std::vector<float> cv::cuda::HOGDescriptor::getPeopleDetector64x128() |
|
|
|
|
-0.01612278f, -1.46097376e-003f, 0.14013411f, -8.96181818e-003f, |
|
|
|
|
-0.03250246f, 3.38630192e-003f, 2.64779478e-003f, 0.03359732f, |
|
|
|
|
-0.02411991f, -0.04229729f, 0.10666174f, -6.66579151f }; |
|
|
|
|
return std::vector<float>(detector, detector + sizeof(detector)/sizeof(detector[0])); |
|
|
|
|
|
|
|
|
|
return Mat(1, static_cast<int>(sizeof(detector)/sizeof(detector[0])), CV_32FC1, detector); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
|