GPU version becomes algorithm

This commit is contained in:
marina.kolpakova 2012-11-10 00:49:51 +04:00
parent e6eb1b99e1
commit 40600fa504
5 changed files with 346 additions and 235 deletions

View File

@ -1534,10 +1534,12 @@ public:
// ======================== GPU version for soft cascade ===================== //
class CV_EXPORTS SoftCascade
// Implementation of soft (stageless) cascaded detector.
class CV_EXPORTS SCascade : public Algorithm
{
public:
// Representation of detectors result.
struct CV_EXPORTS Detection
{
ushort x;
@ -1549,47 +1551,44 @@ public:
enum {PEDESTRIAN = 0};
};
//! An empty cascade will be created.
SoftCascade();
//! Cascade will be created from file for scales from minScale to maxScale.
//! Param filename is a path to xml-serialized cascade.
//! Param minScale is a minimum scale relative to the original size of the image on which cascade will be applyed.
//! Param minScale is a maximum scale relative to the original size of the image on which cascade will be applyed.
SoftCascade( const string& filename, const float minScale = 0.4f, const float maxScale = 5.f);
// An empty cascade will be created.
// Param minScale is a minimum scale relative to the original size of the image on which cascade will be applyed.
// Param minScale is a maximum scale relative to the original size of the image on which cascade will be applyed.
// Param scales is a number of scales from minScale to maxScale.
// Param rejfactor is used for NMS.
SCascade(const double minScale = 0.4, const double maxScale = 5., const int scales = 55, const int rejfactor = 1);
//! cascade will be loaded from file "filename". The previous cascade will be destroyed.
//! Param filename is a path to xml-serialized cascade.
//! Param minScale is a minimum scale relative to the original size of the image on which cascade will be applyed.
//! Param minScale is a maximum scale relative to the original size of the image on which cascade will be applyed.
bool load( const string& filename, const float minScale = 0.4f, const float maxScale = 5.f);
virtual ~SCascade();
virtual ~SoftCascade();
cv::AlgorithmInfo* info() const;
//! detect specific objects on in the input frame for all scales computed flom minScale and maxscale values
//! Param image is input frame for detector. Cascade will be applied to it.
//! Param rois is a mask
//! Param objects 4-channel matrix thet contain detected rectangles
//! Param rejectfactor used for final object box computing
virtual void detectMultiScale(const GpuMat& image, const GpuMat& rois, GpuMat& objects,
int rejectfactor = 1, int specificScale = -1) const;
// Load cascade from FileNode.
// Param fn is a root node for cascade. Should be <cascade>.
virtual bool load(const FileNode& fn);
//! detect specific objects on in the input frame for all scales computed flom minScale and maxscale values.
//! asynchronous version.
//! Param image is input frame for detector. Cascade will be applied to it.
//! Param rois is a mask
//! Param objects 4-channel matrix thet contain detected rectangles
//! Param rejectfactor used for final object box computing
//! Param ndet retrieves number of detections
//! Param stream wrapper for CUDA stream
virtual void detectMultiScale(const GpuMat& image, const GpuMat& rois, GpuMat& objects,
int rejectfactor, GpuMat& ndet, Stream stream) const;
// Load cascade config.
virtual void read(const FileNode& fn);
cv::Size getRoiSize() const;
// Return the vector of Decection objcts.
// Param image is a frame on which detector will be applied.
// Param rois is a vector of regions of interest. Only the objects that fall into one of the regions will be returned.
// Param objects is an output array of Detections
virtual void detect(InputArray image, InputArray rois, OutputArray objects, Stream& stream = Stream::Null()) const;
virtual void detect(InputArray image, InputArray rois, OutputArray objects, const int level, Stream& stream = Stream::Null()) const;
void genRoi(InputArray roi, OutputArray mask) const;
private:
struct Filds;
Filds* filds;
struct Fields;
Fields* fields;
double minScale;
double maxScale;
int scales;
int rejfactor;
};
////////////////////////////////// SURF //////////////////////////////////////////

View File

@ -25,8 +25,8 @@ void fixture##_##name::__cpu() { FAIL() << "No such CPU implementation analogy";
namespace {
struct DetectionLess
{
bool operator()(const cv::gpu::SoftCascade::Detection& a,
const cv::gpu::SoftCascade::Detection& b) const
bool operator()(const cv::gpu::SCascade::Detection& a,
const cv::gpu::SCascade::Detection& b) const
{
if (a.x != b.x) return a.x < b.x;
else if (a.y != b.y) return a.y < b.y;
@ -51,7 +51,7 @@ namespace {
{
cv::Mat detections(objects);
typedef cv::gpu::SoftCascade::Detection Detection;
typedef cv::gpu::SCascade::Detection Detection;
Detection* begin = (Detection*)(detections.ptr<char>(0));
Detection* end = (Detection*)(detections.ptr<char>(0) + detections.cols);
std::sort(begin, end, DetectionLess());
@ -62,52 +62,54 @@ namespace {
typedef std::tr1::tuple<std::string, std::string> fixture_t;
typedef perf::TestBaseWithParam<fixture_t> SoftCascadeTest;
typedef perf::TestBaseWithParam<fixture_t> SCascadeTest;
GPU_PERF_TEST_P(SoftCascadeTest, detect,
GPU_PERF_TEST_P(SCascadeTest, detect,
testing::Combine(
testing::Values(std::string("cv/cascadeandhog/sc_cvpr_2012_to_opencv.xml")),
testing::Values(std::string("cv/cascadeandhog/bahnhof/image_00000000_0.png"))))
{ }
RUN_GPU(SoftCascadeTest, detect)
RUN_GPU(SCascadeTest, detect)
{
cv::Mat cpu = readImage (GET_PARAM(1));
ASSERT_FALSE(cpu.empty());
cv::gpu::GpuMat colored(cpu);
cv::gpu::SoftCascade cascade;
ASSERT_TRUE(cascade.load(perf::TestBase::getDataPath(GET_PARAM(0))));
cv::gpu::SCascade cascade;
cv::gpu::GpuMat objectBoxes(1, 10000 * sizeof(cv::gpu::SoftCascade::Detection), CV_8UC1), rois(cascade.getRoiSize(), CV_8UC1), trois;
cv::FileStorage fs(perf::TestBase::getDataPath(GET_PARAM(0)), cv::FileStorage::READ);
ASSERT_TRUE(fs.isOpened());
ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode()));
cv::gpu::GpuMat objectBoxes(1, 10000 * sizeof(cv::gpu::SCascade::Detection), CV_8UC1), rois(colored.size(), CV_8UC1), trois;
rois.setTo(1);
cv::gpu::transpose(rois, trois);
cascade.genRoi(rois, trois);
cv::gpu::GpuMat curr = objectBoxes;
cascade.detectMultiScale(colored, trois, curr);
cascade.detect(colored, trois, objectBoxes);
TEST_CYCLE()
{
curr = objectBoxes;
cascade.detectMultiScale(colored, trois, curr);
cascade.detect(colored, trois, objectBoxes);
}
SANITY_CHECK(sortDetections(curr));
SANITY_CHECK(sortDetections(objectBoxes));
}
NO_CPU(SoftCascadeTest, detect)
NO_CPU(SCascadeTest, detect)
// RUN_CPU(SoftCascadeTest, detect)
// RUN_CPU(SCascadeTest, detect)
// {
// cv::Mat colored = readImage(GET_PARAM(1));
// ASSERT_FALSE(colored.empty());
// cv::SoftCascade cascade;
// cv::SCascade cascade;
// ASSERT_TRUE(cascade.load(getDataPath(GET_PARAM(0))));
// std::vector<cv::Rect> rois;
// typedef cv::SoftCascade::Detection Detection;
// typedef cv::SCascade::Detection Detection;
// std::vector<Detection>objects;
// cascade.detectMultiScale(colored, rois, objects);
@ -124,42 +126,46 @@ static cv::Rect getFromTable(int idx)
{
static const cv::Rect rois[] =
{
cv::Rect( 65, 20, 35, 80),
cv::Rect( 95, 35, 45, 40),
cv::Rect( 45, 35, 45, 40),
cv::Rect( 25, 27, 50, 45),
cv::Rect(100, 50, 45, 40),
cv::Rect( 65 * 4, 20 * 4, 35 * 4, 80 * 4),
cv::Rect( 95 * 4, 35 * 4, 45 * 4, 40 * 4),
cv::Rect( 45 * 4, 35 * 4, 45 * 4, 40 * 4),
cv::Rect( 25 * 4, 27 * 4, 50 * 4, 45 * 4),
cv::Rect(100 * 4, 50 * 4, 45 * 4, 40 * 4),
cv::Rect( 60, 30, 45, 40),
cv::Rect( 40, 55, 50, 40),
cv::Rect( 48, 37, 72, 80),
cv::Rect( 48, 32, 85, 58),
cv::Rect( 48, 0, 32, 27)
cv::Rect( 60 * 4, 30 * 4, 45 * 4, 40 * 4),
cv::Rect( 40 * 4, 55 * 4, 50 * 4, 40 * 4),
cv::Rect( 48 * 4, 37 * 4, 72 * 4, 80 * 4),
cv::Rect( 48 * 4, 32 * 4, 85 * 4, 58 * 4),
cv::Rect( 48 * 4, 0 * 4, 32 * 4, 27 * 4)
};
return rois[idx];
}
typedef std::tr1::tuple<std::string, std::string, int> roi_fixture_t;
typedef perf::TestBaseWithParam<roi_fixture_t> SoftCascadeTestRoi;
typedef perf::TestBaseWithParam<roi_fixture_t> SCascadeTestRoi;
GPU_PERF_TEST_P(SoftCascadeTestRoi, detectInRoi,
GPU_PERF_TEST_P(SCascadeTestRoi, detectInRoi,
testing::Combine(
testing::Values(std::string("cv/cascadeandhog/sc_cvpr_2012_to_opencv.xml")),
testing::Values(std::string("cv/cascadeandhog/bahnhof/image_00000000_0.png")),
testing::Range(0, 5)))
{}
RUN_GPU(SoftCascadeTestRoi, detectInRoi)
RUN_GPU(SCascadeTestRoi, detectInRoi)
{
cv::Mat cpu = readImage (GET_PARAM(1));
ASSERT_FALSE(cpu.empty());
cv::gpu::GpuMat colored(cpu);
cv::gpu::SoftCascade cascade;
ASSERT_TRUE(cascade.load(perf::TestBase::getDataPath(GET_PARAM(0))));
cv::gpu::SCascade cascade;
cv::gpu::GpuMat objectBoxes(1, 16384 * 20, CV_8UC1), rois(cascade.getRoiSize(), CV_8UC1);
cv::FileStorage fs(perf::TestBase::getDataPath(GET_PARAM(0)), cv::FileStorage::READ);
ASSERT_TRUE(fs.isOpened());
ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode()));
cv::gpu::GpuMat objectBoxes(1, 16384 * 20, CV_8UC1), rois(colored.size(), CV_8UC1);
rois.setTo(0);
int nroi = GET_PARAM(2);
@ -172,40 +178,42 @@ RUN_GPU(SoftCascadeTestRoi, detectInRoi)
}
cv::gpu::GpuMat trois;
cv::gpu::transpose(rois, trois);
cascade.genRoi(rois, trois);
cv::gpu::GpuMat curr = objectBoxes;
cascade.detectMultiScale(colored, trois, curr);
cascade.detect(colored, trois, objectBoxes);
TEST_CYCLE()
{
curr = objectBoxes;
cascade.detectMultiScale(colored, trois, curr);
cascade.detect(colored, trois, objectBoxes);
}
SANITY_CHECK(sortDetections(curr));
SANITY_CHECK(sortDetections(objectBoxes));
}
NO_CPU(SoftCascadeTestRoi, detectInRoi)
NO_CPU(SCascadeTestRoi, detectInRoi)
GPU_PERF_TEST_P(SoftCascadeTestRoi, detectEachRoi,
GPU_PERF_TEST_P(SCascadeTestRoi, detectEachRoi,
testing::Combine(
testing::Values(std::string("cv/cascadeandhog/sc_cvpr_2012_to_opencv.xml")),
testing::Values(std::string("cv/cascadeandhog/bahnhof/image_00000000_0.png")),
testing::Range(0, 10)))
{}
RUN_GPU(SoftCascadeTestRoi, detectEachRoi)
RUN_GPU(SCascadeTestRoi, detectEachRoi)
{
cv::Mat cpu = readImage (GET_PARAM(1));
ASSERT_FALSE(cpu.empty());
cv::gpu::GpuMat colored(cpu);
cv::gpu::SoftCascade cascade;
ASSERT_TRUE(cascade.load(perf::TestBase::getDataPath(GET_PARAM(0))));
cv::gpu::SCascade cascade;
cv::gpu::GpuMat objectBoxes(1, 16384 * 20, CV_8UC1), rois(cascade.getRoiSize(), CV_8UC1);
cv::FileStorage fs(perf::TestBase::getDataPath(GET_PARAM(0)), cv::FileStorage::READ);
ASSERT_TRUE(fs.isOpened());
ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode()));
cv::gpu::GpuMat objectBoxes(1, 16384 * 20, CV_8UC1), rois(colored.size(), CV_8UC1);
rois.setTo(0);
int idx = GET_PARAM(2);
@ -213,24 +221,22 @@ RUN_GPU(SoftCascadeTestRoi, detectEachRoi)
cv::gpu::GpuMat sub(rois, r);
sub.setTo(1);
cv::gpu::GpuMat curr = objectBoxes;
cv::gpu::GpuMat trois;
cv::gpu::transpose(rois, trois);
cascade.genRoi(rois, trois);
cascade.detectMultiScale(colored, trois, curr);
cascade.detect(colored, trois, objectBoxes);
TEST_CYCLE()
{
curr = objectBoxes;
cascade.detectMultiScale(colored, trois, curr);
cascade.detect(colored, trois, objectBoxes);
}
SANITY_CHECK(sortDetections(curr));
SANITY_CHECK(sortDetections(objectBoxes));
}
NO_CPU(SoftCascadeTestRoi, detectEachRoi)
NO_CPU(SCascadeTestRoi, detectEachRoi)
GPU_PERF_TEST_P(SoftCascadeTest, detectOnIntegral,
GPU_PERF_TEST_P(SCascadeTest, detectOnIntegral,
testing::Combine(
testing::Values(std::string("cv/cascadeandhog/sc_cvpr_2012_to_opencv.xml")),
testing::Values(std::string("cv/cascadeandhog/integrals.xml"))))
@ -243,37 +249,39 @@ GPU_PERF_TEST_P(SoftCascadeTest, detectOnIntegral,
return std::string(s);
}
RUN_GPU(SoftCascadeTest, detectOnIntegral)
RUN_GPU(SCascadeTest, detectOnIntegral)
{
cv::FileStorage fs(perf::TestBase::getDataPath(GET_PARAM(1)), cv::FileStorage::READ);
ASSERT_TRUE(fs.isOpened());
cv::FileStorage fsi(perf::TestBase::getDataPath(GET_PARAM(1)), cv::FileStorage::READ);
ASSERT_TRUE(fsi.isOpened());
cv::gpu::GpuMat hogluv(121 * 10, 161, CV_32SC1);
for (int i = 0; i < 10; ++i)
{
cv::Mat channel;
fs[std::string("channel") + itoa(i)] >> channel;
fsi[std::string("channel") + itoa(i)] >> channel;
cv::gpu::GpuMat gchannel(hogluv, cv::Rect(0, 121 * i, 161, 121));
gchannel.upload(channel);
}
cv::gpu::SoftCascade cascade;
ASSERT_TRUE(cascade.load(perf::TestBase::getDataPath(GET_PARAM(0))));
cv::gpu::SCascade cascade;
cv::gpu::GpuMat objectBoxes(1, 10000 * sizeof(cv::gpu::SoftCascade::Detection), CV_8UC1), rois(cascade.getRoiSize(), CV_8UC1), trois;
cv::FileStorage fs(perf::TestBase::getDataPath(GET_PARAM(0)), cv::FileStorage::READ);
ASSERT_TRUE(fs.isOpened());
ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode()));
cv::gpu::GpuMat objectBoxes(1, 10000 * sizeof(cv::gpu::SCascade::Detection), CV_8UC1), rois(cv::Size(640, 480), CV_8UC1), trois;
rois.setTo(1);
cv::gpu::transpose(rois, trois);
cascade.genRoi(rois, trois);
cv::gpu::GpuMat curr = objectBoxes;
cascade.detectMultiScale(hogluv, trois, curr);
cascade.detect(hogluv, trois, objectBoxes);
TEST_CYCLE()
{
curr = objectBoxes;
cascade.detectMultiScale(hogluv, trois, curr);
cascade.detect(hogluv, trois, objectBoxes);
}
SANITY_CHECK(sortDetections(curr));
SANITY_CHECK(sortDetections(objectBoxes));
}
NO_CPU(SoftCascadeTest, detectOnIntegral)
NO_CPU(SCascadeTest, detectOnIntegral)

View File

@ -0,0 +1,60 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2008-2012, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include <precomp.hpp>
namespace cv { namespace gpu
{
CV_INIT_ALGORITHM(SCascade, "CascadeDetector.SCascade",
obj.info()->addParam(obj, "minScale", obj.minScale);
obj.info()->addParam(obj, "maxScale", obj.maxScale);
obj.info()->addParam(obj, "scales", obj.scales);
obj.info()->addParam(obj, "rejfactor", obj.rejfactor));
bool initModule_gpu(void)
{
Ptr<Algorithm> sc = createSCascade();
return sc->info() != 0;
}
} }

View File

@ -45,21 +45,18 @@
#if !defined (HAVE_CUDA)
cv::gpu::SoftCascade::SoftCascade() : filds(0) { throw_nogpu(); }
cv::gpu::SoftCascade::SoftCascade( const string&, const float, const float) : filds(0) { throw_nogpu(); }
cv::gpu::SoftCascade::~SoftCascade() { throw_nogpu(); }
bool cv::gpu::SoftCascade::load( const string&, const float, const float) { throw_nogpu(); return false; }
void cv::gpu::SoftCascade::detectMultiScale(const GpuMat&, const GpuMat&, GpuMat&, const int, int) const
{
throw_nogpu();
}
cv::gpu::SCascade::SCascade(const double, const double, const int, const int) { throw_nogpu(); }
void cv::gpu::SoftCascade::detectMultiScale(const GpuMat&, const GpuMat&, GpuMat&, int, GpuMat&, Stream) const
{
throw_nogpu();
}
cv::gpu::SCascade::~SCascade() { throw_nogpu(); }
cv::Size cv::gpu::SoftCascade::getRoiSize() const { throw_nogpu(); return cv::Size();}
bool cv::gpu::SCascade::load(const FileNode&) { throw_nogpu(); return false;}
void cv::gpu::SCascade::detect(InputArray, InputArray, OutputArray, Stream&) const { throw_nogpu(); }
void cv::gpu::SCascade::detect(InputArray, InputArray, OutputArray, const int, Stream&) const { throw_nogpu(); }
void cv::gpu::SCascade::genRoi(InputArray, OutputArray) const { throw_nogpu(); }
void cv::gpu::SCascade::read(const FileNode& fn) { Algorithm::read(fn); }
#else
@ -92,7 +89,7 @@ namespace imgproc {
}}}
struct cv::gpu::SoftCascade::Filds
struct cv::gpu::SCascade::Fields
{
struct CascadeIntrinsics
{
@ -126,7 +123,7 @@ struct cv::gpu::SoftCascade::Filds
}
};
static Filds* parseCascade(const FileNode &root, const float mins, const float maxs)
static Fields* parseCascade(const FileNode &root, const float mins, const float maxs)
{
static const char *const SC_STAGE_TYPE = "stageType";
static const char *const SC_BOOST = "BOOST";
@ -312,13 +309,13 @@ struct cv::gpu::SoftCascade::Filds
cv::Mat hlevels(1, vlevels.size() * sizeof(Level), CV_8UC1, (uchar*)&(vlevels[0]) );
CV_Assert(!hlevels.empty());
Filds* filds = new Filds(mins, maxs, origWidth, origHeight, shrinkage, downscales,
Fields* fields = new Fields(mins, maxs, origWidth, origHeight, shrinkage, downscales,
hoctaves, hstages, hnodes, hleaves, hlevels);
return filds;
return fields;
}
Filds( const float mins, const float maxs, const int ow, const int oh, const int shr, const int ds,
Fields( const float mins, const float maxs, const int ow, const int oh, const int shr, const int ds,
cv::Mat hoctaves, cv::Mat hstages, cv::Mat hnodes, cv::Mat hleaves, cv::Mat hlevels)
: minScale(mins), maxScale(maxs), origObjWidth(ow), origObjHeight(oh), shrinkage(shr), downscales(ds)
{
@ -332,7 +329,7 @@ struct cv::gpu::SoftCascade::Filds
hogluv.create((FRAME_HEIGHT / shr) * HOG_LUV_BINS + 1, FRAME_WIDTH / shr + 1, CV_32SC1);
hogluv.setTo(cv::Scalar::all(0));
detCounter.create(1,1, CV_32SC1);
detCounter.create(sizeof(Detection) / sizeof(int),1, CV_32SC1);
octaves.upload(hoctaves);
stages.upload(hstages);
@ -344,20 +341,21 @@ struct cv::gpu::SoftCascade::Filds
}
void detect(int scale, const cv::gpu::GpuMat& roi, cv::gpu::GpuMat& objects, cudaStream_t stream) const
void detect(int scale, const cv::gpu::GpuMat& roi, const cv::gpu::GpuMat& count, cv::gpu::GpuMat& objects, cudaStream_t stream) const
{
cudaMemset(detCounter.data, 0, detCounter.step * detCounter.rows * sizeof(int));
invoker(roi, hogluv, objects, detCounter, downscales, scale);
cudaMemset(count.data, 0, sizeof(Detection));
cudaSafeCall( cudaGetLastError());
invoker(roi, hogluv, objects, count, downscales, scale);
}
void preprocess(const cv::gpu::GpuMat& colored)
{
cudaMemset(plane.data, 0, plane.step * plane.rows);
static const int fw = Filds::FRAME_WIDTH;
static const int fh = Filds::FRAME_HEIGHT;
static const int fw = Fields::FRAME_WIDTH;
static const int fh = Fields::FRAME_HEIGHT;
GpuMat gray(plane, cv::Rect(0, fh * Filds::HOG_LUV_BINS, fw, fh));
GpuMat gray(plane, cv::Rect(0, fh * Fields::HOG_LUV_BINS, fw, fh));
cv::gpu::cvtColor(colored, gray, CV_BGR2GRAY);
createHogBins(gray);
@ -390,8 +388,8 @@ private:
void createHogBins(const cv::gpu::GpuMat& gray)
{
static const int fw = Filds::FRAME_WIDTH;
static const int fh = Filds::FRAME_HEIGHT;
static const int fw = Fields::FRAME_WIDTH;
static const int fh = Fields::FRAME_HEIGHT;
GpuMat dfdx(fplane, cv::Rect(0, 0, fw, fh));
GpuMat dfdy(fplane, cv::Rect(0, fh, fw, fh));
@ -413,21 +411,21 @@ private:
cv::gpu::multiply(ang, cv::Scalar::all(1.f / 60.f), nang);
//create uchar magnitude
GpuMat cmag(plane, cv::Rect(0, fh * Filds::HOG_BINS, fw, fh));
GpuMat cmag(plane, cv::Rect(0, fh * Fields::HOG_BINS, fw, fh));
nmag.convertTo(cmag, CV_8UC1);
device::icf::fillBins(plane, nang, fw, fh, Filds::HOG_BINS);
device::icf::fillBins(plane, nang, fw, fh, Fields::HOG_BINS);
}
void createLuvBins(const cv::gpu::GpuMat& colored)
{
static const int fw = Filds::FRAME_WIDTH;
static const int fh = Filds::FRAME_HEIGHT;
static const int fw = Fields::FRAME_WIDTH;
static const int fh = Fields::FRAME_HEIGHT;
cv::gpu::cvtColor(colored, luv, CV_BGR2Luv);
std::vector<GpuMat> splited;
for(int i = 0; i < Filds::LUV_BINS; ++i)
for(int i = 0; i < Fields::LUV_BINS; ++i)
{
splited.push_back(GpuMat(plane, cv::Rect(0, fh * (7 + i), fw, fh)));
}
@ -437,10 +435,10 @@ private:
void integrate()
{
int fw = Filds::FRAME_WIDTH;
int fh = Filds::FRAME_HEIGHT;
int fw = Fields::FRAME_WIDTH;
int fh = Fields::FRAME_HEIGHT;
GpuMat channels(plane, cv::Rect(0, 0, fw, fh * Filds::HOG_LUV_BINS));
GpuMat channels(plane, cv::Rect(0, 0, fw, fh * Fields::HOG_LUV_BINS));
cv::gpu::resize(channels, shrunk, cv::Size(), 0.25, 0.25, CV_INTER_AREA);
device::imgproc::shfl_integral_gpu_buffered(shrunk, integralBuffer, hogluv, 12, 0);
}
@ -500,45 +498,33 @@ public:
};
};
cv::gpu::SoftCascade::SoftCascade() : filds(0) {}
cv::gpu::SCascade::SCascade(const double mins, const double maxs, const int sc, const int rjf)
: fields(0), minScale(mins), maxScale(maxs), scales(sc), rejfactor(rjf) {}
cv::gpu::SoftCascade::SoftCascade( const string& filename, const float minScale, const float maxScale) : filds(0)
cv::gpu::SCascade::~SCascade() { delete fields; }
bool cv::gpu::SCascade::load(const FileNode& fn)
{
load(filename, minScale, maxScale);
if (fields) delete fields;
fields = Fields::parseCascade(fn, minScale, maxScale);
return fields != 0;
}
cv::gpu::SoftCascade::~SoftCascade()
{
delete filds;
}
bool cv::gpu::SoftCascade::load( const string& filename, const float minScale, const float maxScale)
{
if (filds) delete filds;
cv::FileStorage fs(filename, FileStorage::READ);
if (!fs.isOpened()) return false;
filds = Filds::parseCascade(fs.getFirstTopLevelNode(), minScale, maxScale);
return filds != 0;
}
void cv::gpu::SoftCascade::detectMultiScale(const GpuMat& colored, const GpuMat& rois,
GpuMat& objects, const int /*rejectfactor*/, int specificScale) const
void cv::gpu::SCascade::detect(InputArray image, InputArray _rois, OutputArray _objects, Stream& s) const
{
const GpuMat colored = image.getGpuMat();
// only color images are supperted
CV_Assert(colored.type() == CV_8UC3 || colored.type() == CV_32SC1);
// we guess user knows about shrincage
CV_Assert((rois.size().width == getRoiSize().height) && (rois.type() == CV_8UC1));
// CV_Assert((rois.size().width == getRoiSize().height) && (rois.type() == CV_8UC1));
Filds& flds = *filds;
Fields& flds = *fields;
if (colored.type() == CV_8UC3)
{
// only this window size allowed
CV_Assert(colored.cols == Filds::FRAME_WIDTH && colored.rows == Filds::FRAME_HEIGHT);
CV_Assert(colored.cols == Fields::FRAME_WIDTH && colored.rows == Fields::FRAME_HEIGHT);
flds.preprocess(colored);
}
else
@ -546,25 +532,60 @@ void cv::gpu::SoftCascade::detectMultiScale(const GpuMat& colored, const GpuMat&
colored.copyTo(flds.hogluv);
}
flds.detect(specificScale, rois, objects, 0);
GpuMat rois = _rois.getGpuMat(), objects = _objects.getGpuMat();
cv::Mat out(flds.detCounter);
int ndetections = *(out.ptr<int>(0));
GpuMat tmp = GpuMat(objects, cv::Rect(0, 0, sizeof(Detection), 1));
objects = GpuMat(objects, cv::Rect( sizeof(Detection), 0, objects.cols - sizeof(Detection), 1));
cudaStream_t stream = StreamAccessor::getStream(s);
if (! ndetections)
objects = GpuMat();
flds.detect(-1, rois, tmp, objects, stream);
}
void cv::gpu::SCascade::detect(InputArray image, InputArray _rois, OutputArray _objects, const int level, Stream& s) const
{
const GpuMat colored = image.getGpuMat();
// only color images are supperted
CV_Assert(colored.type() == CV_8UC3 || colored.type() == CV_32SC1);
// we guess user knows about shrincage
// CV_Assert((rois.size().width == getRoiSize().height) && (rois.type() == CV_8UC1));
Fields& flds = *fields;
if (colored.type() == CV_8UC3)
{
// only this window size allowed
CV_Assert(colored.cols == Fields::FRAME_WIDTH && colored.rows == Fields::FRAME_HEIGHT);
flds.preprocess(colored);
}
else
objects = GpuMat(objects, cv::Rect(0, 0, ndetections * sizeof(Detection), 1));
{
colored.copyTo(flds.hogluv);
}
GpuMat rois = _rois.getGpuMat(), objects = _objects.getGpuMat();
GpuMat tmp = GpuMat(objects, cv::Rect(0, 0, sizeof(Detection), 1));
objects = GpuMat(objects, cv::Rect( sizeof(Detection), 0, objects.cols - sizeof(Detection), 1));
cudaStream_t stream = StreamAccessor::getStream(s);
flds.detect(level, rois, tmp, objects, stream);
}
void cv::gpu::SoftCascade::detectMultiScale(const GpuMat&, const GpuMat&, GpuMat&, int, GpuMat&, Stream) const
void cv::gpu::SCascade::genRoi(InputArray _roi, OutputArray _mask) const
{
// cudaStream_t stream = StreamAccessor::getStream(s);
const GpuMat roi = _roi.getGpuMat();
_mask.create( roi.cols / 4, roi.rows / 4, roi.type() );
GpuMat mask = _mask.getGpuMat();
cv::gpu::GpuMat tmp;
cv::gpu::resize(roi, tmp, cv::Size(), 0.25, 0.25, CV_INTER_AREA);
cv::gpu::transpose(tmp, mask);
}
cv::Size cv::gpu::SoftCascade::getRoiSize() const
void cv::gpu::SCascade::read(const FileNode& fn)
{
return cv::Size(Filds::FRAME_WIDTH / (*filds).shrinkage, Filds::FRAME_HEIGHT / (*filds).shrinkage);
Algorithm::read(fn);
}
#endif

View File

@ -70,23 +70,23 @@ using cv::gpu::GpuMat;
namespace {
typedef cv::gpu::SoftCascade::Detection Detection;
typedef cv::gpu::SCascade::Detection Detection;
static cv::Rect getFromTable(int idx)
{
static const cv::Rect rois[] =
{
cv::Rect( 65, 20, 35, 80),
cv::Rect( 95, 35, 45, 40),
cv::Rect( 45, 35, 45, 40),
cv::Rect( 25, 27, 50, 45),
cv::Rect(100, 50, 45, 40),
cv::Rect( 65 * 4, 20 * 4, 35 * 4, 80 * 4),
cv::Rect( 95 * 4, 35 * 4, 45 * 4, 40 * 4),
cv::Rect( 45 * 4, 35 * 4, 45 * 4, 40 * 4),
cv::Rect( 25 * 4, 27 * 4, 50 * 4, 45 * 4),
cv::Rect(100 * 4, 50 * 4, 45 * 4, 40 * 4),
cv::Rect( 60, 30, 45, 40),
cv::Rect( 40, 55, 50, 40),
cv::Rect( 48, 37, 72, 80),
cv::Rect( 48, 32, 85, 58),
cv::Rect( 48, 0, 32, 27)
cv::Rect( 60 * 4, 30 * 4, 45 * 4, 40 * 4),
cv::Rect( 40 * 4, 55 * 4, 50 * 4, 40 * 4),
cv::Rect( 48 * 4, 37 * 4, 72 * 4, 80 * 4),
cv::Rect( 48 * 4, 32 * 4, 85 * 4, 58 * 4),
cv::Rect( 48 * 4, 0 * 4, 32 * 4, 27 * 4)
};
return rois[idx];
@ -140,11 +140,11 @@ namespace {
}
}
typedef ::testing::TestWithParam<std::tr1::tuple<cv::gpu::DeviceInfo, std::string, std::string, int> > SoftCascadeTestRoi;
GPU_TEST_P(SoftCascadeTestRoi, detect,
typedef ::testing::TestWithParam<std::tr1::tuple<cv::gpu::DeviceInfo, std::string, std::string, int> > SCascadeTestRoi;
GPU_TEST_P(SCascadeTestRoi, detect,
testing::Combine(
ALL_DEVICES,
testing::Values(std::string("../cv/cascadeandhog/sc_cvpr_2012_to_opencv.xml")),
testing::Values(std::string("cv/cascadeandhog/sc_cvpr_2012_to_opencv.xml")),
testing::Values(std::string("../cv/cascadeandhog/bahnhof/image_00000000_0.png")),
testing::Range(0, 5)))
{
@ -152,10 +152,14 @@ GPU_TEST_P(SoftCascadeTestRoi, detect,
cv::Mat coloredCpu = cv::imread(cvtest::TS::ptr()->get_data_path() + GET_PARAM(2));
ASSERT_FALSE(coloredCpu.empty());
cv::gpu::SoftCascade cascade;
ASSERT_TRUE(cascade.load(cvtest::TS::ptr()->get_data_path() + GET_PARAM(1)));
cv::gpu::SCascade cascade;
GpuMat colored(coloredCpu), objectBoxes(1, 16384, CV_8UC1), rois(cascade.getRoiSize(), CV_8UC1), trois;
cv::FileStorage fs(perf::TestBase::getDataPath(GET_PARAM(1)), cv::FileStorage::READ);
ASSERT_TRUE(fs.isOpened());
ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode()));
GpuMat colored(coloredCpu), objectBoxes(1, 16384, CV_8UC1), rois(colored.size(), CV_8UC1), trois;
rois.setTo(0);
int nroi = GET_PARAM(3);
@ -166,21 +170,21 @@ GPU_TEST_P(SoftCascadeTestRoi, detect,
cv::Rect r = getFromTable(rng(10));
GpuMat sub(rois, r);
sub.setTo(1);
r.x *= 4; r.y *= 4; r.width *= 4; r.height *= 4;
cv::rectangle(result, r, cv::Scalar(0, 0, 255, 255), 1);
}
cv::gpu::transpose(rois, trois);
cascade.detectMultiScale(colored, trois, objectBoxes);
cascade.genRoi(rois, trois);
cascade.detect(colored, trois, objectBoxes);
cv::Mat dt(objectBoxes);
typedef cv::gpu::SoftCascade::Detection Detection;
typedef cv::gpu::SCascade::Detection Detection;
Detection* dts = (Detection*)dt.data;
Detection* dts = ((Detection*)dt.data) + 1;
int* count = dt.ptr<int>(0);
printTotal(std::cout, dt.cols);
for (int i = 0; i < (int)(dt.cols / sizeof(Detection)); ++i)
printTotal(std::cout, *count);
for (int i = 0; i < *count; ++i)
{
Detection d = dts[i];
print(std::cout, d);
@ -188,43 +192,49 @@ GPU_TEST_P(SoftCascadeTestRoi, detect,
}
SHOW(result);
}
typedef ::testing::TestWithParam<std::tr1::tuple<cv::gpu::DeviceInfo, std::string, std::string, int> > SoftCascadeTestLevel;
GPU_TEST_P(SoftCascadeTestLevel, detect,
typedef ::testing::TestWithParam<std::tr1::tuple<cv::gpu::DeviceInfo, std::string, std::string, int> > SCascadeTestLevel;
GPU_TEST_P(SCascadeTestLevel, detect,
testing::Combine(
ALL_DEVICES,
testing::Values(std::string("../cv/cascadeandhog/sc_cvpr_2012_to_opencv.xml")),
testing::Values(std::string("cv/cascadeandhog/sc_cvpr_2012_to_opencv.xml")),
testing::Values(std::string("../cv/cascadeandhog/bahnhof/image_00000000_0.png")),
testing::Range(0, 47)
))
{
cv::gpu::setDevice(GET_PARAM(0).deviceID());
std::string xml = cvtest::TS::ptr()->get_data_path() + GET_PARAM(1);
cv::gpu::SoftCascade cascade;
ASSERT_TRUE(cascade.load(xml));
cv::gpu::SCascade cascade;
cv::FileStorage fs(perf::TestBase::getDataPath(GET_PARAM(1)), cv::FileStorage::READ);
ASSERT_TRUE(fs.isOpened());
ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode()));
cv::Mat coloredCpu = cv::imread(cvtest::TS::ptr()->get_data_path() + GET_PARAM(2));
ASSERT_FALSE(coloredCpu.empty());
typedef cv::gpu::SoftCascade::Detection Detection;
GpuMat colored(coloredCpu), objectBoxes(1, 100 * sizeof(Detection), CV_8UC1), rois(cascade.getRoiSize(), CV_8UC1);
typedef cv::gpu::SCascade::Detection Detection;
GpuMat colored(coloredCpu), objectBoxes(1, 100 * sizeof(Detection), CV_8UC1), rois(colored.size(), CV_8UC1);
rois.setTo(1);
cv::gpu::GpuMat trois;
cv::gpu::transpose(rois, trois);
cascade.genRoi(rois, trois);
int level = GET_PARAM(3);
cascade.detectMultiScale(colored, trois, objectBoxes, 1, level);
cascade.detect(colored, trois, objectBoxes, level);
cv::Mat dt(objectBoxes);
Detection* dts = (Detection*)dt.data;
Detection* dts = ((Detection*)dt.data) + 1;
int* count = dt.ptr<int>(0);
cv::Mat result(coloredCpu);
printTotal(std::cout, dt.cols);
for (int i = 0; i < (int)(dt.cols / sizeof(Detection)); ++i)
printTotal(std::cout, *count);
for (int i = 0; i < *count; ++i)
{
Detection d = dts[i];
print(std::cout, d);
@ -235,76 +245,89 @@ GPU_TEST_P(SoftCascadeTestLevel, detect,
SHOW(result);
}
TEST(SoftCascadeTest, readCascade)
TEST(SCascadeTest, readCascade)
{
std::string xml = cvtest::TS::ptr()->get_data_path() + "../cv/cascadeandhog/icf-template.xml";
cv::gpu::SoftCascade cascade;
ASSERT_TRUE(cascade.load(xml));
cv::gpu::SCascade cascade;
cv::FileStorage fs(xml, cv::FileStorage::READ);
ASSERT_TRUE(fs.isOpened());
ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode()));
}
typedef ::testing::TestWithParam<cv::gpu::DeviceInfo > SoftCascadeTestAll;
GPU_TEST_P(SoftCascadeTestAll, detect,
typedef ::testing::TestWithParam<cv::gpu::DeviceInfo > SCascadeTestAll;
GPU_TEST_P(SCascadeTestAll, detect,
ALL_DEVICES
)
{
cv::gpu::setDevice(GetParam().deviceID());
std::string xml = cvtest::TS::ptr()->get_data_path() + "../cv/cascadeandhog/sc_cvpr_2012_to_opencv.xml";
cv::gpu::SoftCascade cascade;
ASSERT_TRUE(cascade.load(xml));
cv::gpu::SCascade cascade;
cv::FileStorage fs(xml, cv::FileStorage::READ);
ASSERT_TRUE(fs.isOpened());
ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode()));
cv::Mat coloredCpu = cv::imread(cvtest::TS::ptr()->get_data_path()
+ "../cv/cascadeandhog/bahnhof/image_00000000_0.png");
ASSERT_FALSE(coloredCpu.empty());
GpuMat colored(coloredCpu), objectBoxes(1, 100000, CV_8UC1), rois(cascade.getRoiSize(), CV_8UC1);
GpuMat colored(coloredCpu), objectBoxes(1, 100000, CV_8UC1), rois(colored.size(), CV_8UC1);
rois.setTo(0);
GpuMat sub(rois, cv::Rect(rois.cols / 4, rois.rows / 4,rois.cols / 2, rois.rows / 2));
sub.setTo(cv::Scalar::all(1));
cv::gpu::GpuMat trois;
cv::gpu::transpose(rois, trois);
cascade.genRoi(rois, trois);
cascade.detectMultiScale(colored, trois, objectBoxes);
cascade.detect(colored, trois, objectBoxes);
typedef cv::gpu::SoftCascade::Detection Detection;
typedef cv::gpu::SCascade::Detection Detection;
cv::Mat detections(objectBoxes);
ASSERT_EQ(detections.cols / sizeof(Detection) ,3670U);
int a = *(detections.ptr<int>(0));
ASSERT_EQ(a ,2460);
}
//ToDo: fix me
GPU_TEST_P(SoftCascadeTestAll, detectOnIntegral,
GPU_TEST_P(SCascadeTestAll, detectOnIntegral,
ALL_DEVICES
)
{
cv::gpu::setDevice(GetParam().deviceID());
std::string xml = cvtest::TS::ptr()->get_data_path() + "../cv/cascadeandhog/sc_cvpr_2012_to_opencv.xml";
cv::gpu::SoftCascade cascade;
ASSERT_TRUE(cascade.load(xml));
cv::gpu::SCascade cascade;
cv::FileStorage fs(xml, cv::FileStorage::READ);
ASSERT_TRUE(fs.isOpened());
ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode()));
std::string intPath = cvtest::TS::ptr()->get_data_path() + "../cv/cascadeandhog/integrals.xml";
cv::FileStorage fs(intPath, cv::FileStorage::READ);
ASSERT_TRUE(fs.isOpened());
cv::FileStorage fsi(intPath, cv::FileStorage::READ);
ASSERT_TRUE(fsi.isOpened());
GpuMat hogluv(121 * 10, 161, CV_32SC1);
for (int i = 0; i < 10; ++i)
{
cv::Mat channel;
fs[std::string("channel") + itoa(i)] >> channel;
fsi[std::string("channel") + itoa(i)] >> channel;
GpuMat gchannel(hogluv, cv::Rect(0, 121 * i, 161, 121));
gchannel.upload(channel);
}
GpuMat objectBoxes(1, 100000, CV_8UC1), rois(cascade.getRoiSize(), CV_8UC1);
GpuMat objectBoxes(1, 100000, CV_8UC1), rois(cv::Size(640, 480), CV_8UC1);
rois.setTo(1);
cv::gpu::GpuMat trois;
cv::gpu::transpose(rois, trois);
cascade.genRoi(rois, trois);
cascade.detectMultiScale(hogluv, trois, objectBoxes);
cascade.detect(hogluv, trois, objectBoxes);
typedef cv::gpu::SoftCascade::Detection Detection;
typedef cv::gpu::SCascade::Detection Detection;
cv::Mat detections(objectBoxes);
int a = *(detections.ptr<int>(0));
ASSERT_EQ(detections.cols / sizeof(Detection) ,2042U);
ASSERT_EQ( a ,1024);
}
#endif