Commit 5120322c authored by marina.kolpakova's avatar marina.kolpakova

move gpu version of soft cascade to dedicated module

parent 9b00c14f
set(name sft) set(name sft)
set(the_target opencv_${name}) set(the_target opencv_${name})
set(OPENCV_${the_target}_DEPS opencv_core opencv_softcascade opencv_highgui opencv_imgproc opencv_ml) set(OPENCV_${the_target}_DEPS opencv_core opencv_softcascade opencv_highgui opencv_imgproc opencv_ml OPTIONAL opencv_gpu opencv_objdetect opencv_featurest2d)
ocv_check_dependencies(${OPENCV_${the_target}_DEPS}) ocv_check_dependencies(${OPENCV_${the_target}_DEPS})
if(NOT OCV_DEPENDENCIES_FOUND) if(NOT OCV_DEPENDENCIES_FOUND)
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
// //
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved. // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners. // Third party copyrights are property of their respective owners.
// //
// Redistribution and use in source and binary forms, with or without modification, // Redistribution and use in source and binary forms, with or without modification,
...@@ -23,7 +22,7 @@ ...@@ -23,7 +22,7 @@
// //
// * Redistribution's in binary form must reproduce the above copyright notice, // * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation // this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. // and/or other GpuMaterials provided with the distribution.
// //
// * The name of the copyright holders may not be used to endorse or promote products // * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission. // derived from this software without specific prior written permission.
......
macro(ocv_glob_cuda_powered_module_sources)
file(GLOB_RECURSE lib_srcs "src/*.cpp")
file(GLOB_RECURSE lib_int_hdrs "src/*.hpp" "src/*.h")
file(GLOB lib_hdrs "include/opencv2/${name}/*.hpp" "include/opencv2/${name}/*.h")
file(GLOB lib_hdrs_detail "include/opencv2/${name}/detail/*.hpp" "include/opencv2/${name}/detail/*.h")
file(GLOB_RECURSE lib_device_srcs "src/*.cu")
set(device_objs "")
set(lib_device_hdrs "")
if (HAVE_CUDA AND lib_device_srcs)
ocv_include_directories(${CUDA_INCLUDE_DIRS})
file(GLOB_RECURSE lib_device_hdrs "src/cuda/*.hpp")
ocv_cuda_compile(device_objs ${lib_device_srcs})
source_group("Src\\Cuda" FILES ${lib_device_srcs} ${lib_device_hdrs})
if (lib_device_hdrs)
list(REMOVE_ITEM lib_int_hdrs ${lib_device_hdrs})
endif()
endif()
ocv_set_module_sources(${ARGN} HEADERS ${lib_hdrs} ${lib_hdrs_detail}
SOURCES ${lib_srcs} ${lib_int_hdrs} ${device_objs} ${lib_device_srcs} ${lib_device_hdrs})
source_group("Src" FILES ${lib_srcs} ${lib_int_hdrs})
source_group("Include" FILES ${lib_hdrs})
source_group("Include\\detail" FILES ${lib_hdrs_detail})
endmacro()
set(the_description "Soft Cascade detection and training") set(the_description "Soft Cascade detection and training")
ocv_define_module(softcascade opencv_core opencv_imgproc opencv_ml) ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4310 -Wundef -Wmissing-declarations)
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4310) set(cuda_deps "")
\ No newline at end of file set(cuda_include "")
if (NAVE_CUDA)
set(cuda_deps ${CUDA_LIBRARIES} ${CUDA_npp_LIBRARY})
endif()
ocv_add_module(softcascade opencv_core opencv_imgproc opencv_ml OPTIONAL opencv_gpu ${cuda_deps})
if(HAVE_CUDA)
ocv_module_include_directories(${CUDA_INCLUDE_DIRS})
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wundef)
endif()
ocv_glob_cuda_powered_module_sources()
ocv_create_module()
ocv_add_precompiled_headers(${the_module})
ocv_add_accuracy_tests()
ocv_add_perf_tests()
...@@ -212,6 +212,96 @@ public: ...@@ -212,6 +212,96 @@ public:
CV_EXPORTS bool initModule_softcascade(void); CV_EXPORTS bool initModule_softcascade(void);
// ======================== GPU version for soft cascade ===================== //
class CV_EXPORTS ChannelsProcessor
{
public:
enum
{
GENERIC = 1 << 4,
SEPARABLE = 2 << 4
};
// Appends specified number of HOG first-order features integrals into given vector.
// Param frame is an input 3-channel bgr image.
// Param channels is a GPU matrix of optionally shrinked channels
// Param stream is stream is a high-level CUDA stream abstraction used for asynchronous execution.
virtual void apply(InputArray frame, OutputArray channels, cv::gpu::Stream& stream = cv::gpu::Stream::Null()) = 0;
// Creates a specific preprocessor implementation.
// Param shrinkage is a resizing factor. Resize is applied before the computing integral sum
// Param bins is a number of HOG-like channels.
// Param flags is a channel computing extra flags.
static cv::Ptr<ChannelsProcessor> create(const int shrinkage, const int bins, const int flags = GENERIC);
virtual ~ChannelsProcessor();
protected:
ChannelsProcessor();
};
// Implementation of soft (stage-less) cascaded detector.
class CV_EXPORTS SCascade : public cv::Algorithm
{
public:
// Representation of detectors result.
struct CV_EXPORTS Detection
{
ushort x;
ushort y;
ushort w;
ushort h;
float confidence;
int kind;
enum {PEDESTRIAN = 0};
};
enum { NO_REJECT = 1, DOLLAR = 2, /*PASCAL = 4,*/ DEFAULT = NO_REJECT, NMS_MASK = 0xF};
// 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 applied.
// Param minScale is a maximum scale relative to the original size of the image on which cascade will be applied.
// Param scales is a number of scales from minScale to maxScale.
// Param flags is an extra tuning flags.
SCascade(const double minScale = 0.4, const double maxScale = 5., const int scales = 55,
const int flags = NO_REJECT || ChannelsProcessor::GENERIC);
virtual ~SCascade();
cv::AlgorithmInfo* info() const;
// Load cascade from FileNode.
// Param fn is a root node for cascade. Should be <cascade>.
virtual bool load(const FileNode& fn);
// Load cascade config.
virtual void read(const FileNode& fn);
// Return the matrix of of detected objects.
// Param image is a frame on which detector will be applied.
// Param rois is a regions of interests mask generated by genRoi.
// Only the objects that fall into one of the regions will be returned.
// Param objects is an output array of Detections represented as GpuMat of detections (SCascade::Detection)
// The first element of the matrix is actually a count of detections.
// Param stream is stream is a high-level CUDA stream abstraction used for asynchronous execution
virtual void detect(InputArray image, InputArray rois, OutputArray objects, cv::gpu::Stream& stream = cv::gpu::Stream::Null()) const;
private:
struct Fields;
Fields* fields;
double minScale;
double maxScale;
int scales;
int flags;
};
}} // namespace cv { namespace softcascade { }} // namespace cv { namespace softcascade {
#endif #endif
\ No newline at end of file
#include "perf_precomp.hpp" #include "perf_precomp.hpp"
using std::tr1::get;
#define SC_PERF_TEST_P(fixture, name, params) \ #define SC_PERF_TEST_P(fixture, name, params) \
class fixture##_##name : public fixture {\ class fixture##_##name : public fixture {\
public:\ public:\
...@@ -25,8 +27,8 @@ void fixture##_##name::__cpu() { FAIL() << "No such CPU implementation analogy"; ...@@ -25,8 +27,8 @@ void fixture##_##name::__cpu() { FAIL() << "No such CPU implementation analogy";
namespace { namespace {
struct DetectionLess struct DetectionLess
{ {
bool operator()(const cv::gpu::SCascade::Detection& a, bool operator()(const cv::softcascade::SCascade::Detection& a,
const cv::gpu::SCascade::Detection& b) const const cv::softcascade::SCascade::Detection& b) const
{ {
if (a.x != b.x) return a.x < b.x; if (a.x != b.x) return a.x < b.x;
else if (a.y != b.y) return a.y < b.y; else if (a.y != b.y) return a.y < b.y;
...@@ -39,7 +41,7 @@ namespace { ...@@ -39,7 +41,7 @@ namespace {
{ {
cv::Mat detections(objects); cv::Mat detections(objects);
typedef cv::gpu::SCascade::Detection Detection; typedef cv::softcascade::SCascade::Detection Detection;
Detection* begin = (Detection*)(detections.ptr<char>(0)); Detection* begin = (Detection*)(detections.ptr<char>(0));
Detection* end = (Detection*)(detections.ptr<char>(0) + detections.cols); Detection* end = (Detection*)(detections.ptr<char>(0) + detections.cols);
std::sort(begin, end, DetectionLess()); std::sort(begin, end, DetectionLess());
...@@ -60,18 +62,18 @@ SC_PERF_TEST_P(SCascadeTest, detect, ...@@ -60,18 +62,18 @@ SC_PERF_TEST_P(SCascadeTest, detect,
RUN_GPU(SCascadeTest, detect) RUN_GPU(SCascadeTest, detect)
{ {
cv::Mat cpu = readImage (GET_PARAM(1)); cv::Mat cpu = cv::imread(getDataPath(get<1>(GetParam())));;
ASSERT_FALSE(cpu.empty()); ASSERT_FALSE(cpu.empty());
cv::gpu::GpuMat colored(cpu); cv::gpu::GpuMat colored(cpu);
cv::gpu::SCascade cascade; cv::softcascade::SCascade cascade;
cv::FileStorage fs(perf::TestBase::getDataPath(GET_PARAM(0)), cv::FileStorage::READ); cv::FileStorage fs(getDataPath(get<0>(GetParam())), cv::FileStorage::READ);
ASSERT_TRUE(fs.isOpened()); ASSERT_TRUE(fs.isOpened());
ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode())); ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode()));
cv::gpu::GpuMat objectBoxes(1, 10000 * sizeof(cv::gpu::SCascade::Detection), CV_8UC1), rois(colored.size(), CV_8UC1); cv::gpu::GpuMat objectBoxes(1, 10000 * sizeof(cv::softcascade::SCascade::Detection), CV_8UC1), rois(colored.size(), CV_8UC1);
rois.setTo(1); rois.setTo(1);
cascade.detect(colored, rois, objectBoxes); cascade.detect(colored, rois, objectBoxes);
...@@ -118,13 +120,13 @@ SC_PERF_TEST_P(SCascadeTestRoi, detectInRoi, ...@@ -118,13 +120,13 @@ SC_PERF_TEST_P(SCascadeTestRoi, detectInRoi,
RUN_GPU(SCascadeTestRoi, detectInRoi) RUN_GPU(SCascadeTestRoi, detectInRoi)
{ {
cv::Mat cpu = readImage (GET_PARAM(1)); cv::Mat cpu = cv::imread(getDataPath(get<1>(GetParam())));
ASSERT_FALSE(cpu.empty()); ASSERT_FALSE(cpu.empty());
cv::gpu::GpuMat colored(cpu); cv::gpu::GpuMat colored(cpu);
cv::gpu::SCascade cascade; cv::softcascade::SCascade cascade;
cv::FileStorage fs(perf::TestBase::getDataPath(GET_PARAM(0)), cv::FileStorage::READ); cv::FileStorage fs(getDataPath(get<0>(GetParam())), cv::FileStorage::READ);
ASSERT_TRUE(fs.isOpened()); ASSERT_TRUE(fs.isOpened());
ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode())); ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode()));
...@@ -132,7 +134,7 @@ RUN_GPU(SCascadeTestRoi, detectInRoi) ...@@ -132,7 +134,7 @@ RUN_GPU(SCascadeTestRoi, detectInRoi)
cv::gpu::GpuMat objectBoxes(1, 16384 * 20, CV_8UC1), rois(colored.size(), CV_8UC1); cv::gpu::GpuMat objectBoxes(1, 16384 * 20, CV_8UC1), rois(colored.size(), CV_8UC1);
rois.setTo(0); rois.setTo(0);
int nroi = GET_PARAM(2); int nroi = get<2>(GetParam());
cv::RNG rng; cv::RNG rng;
for (int i = 0; i < nroi; ++i) for (int i = 0; i < nroi; ++i)
{ {
...@@ -163,13 +165,13 @@ SC_PERF_TEST_P(SCascadeTestRoi, detectEachRoi, ...@@ -163,13 +165,13 @@ SC_PERF_TEST_P(SCascadeTestRoi, detectEachRoi,
RUN_GPU(SCascadeTestRoi, detectEachRoi) RUN_GPU(SCascadeTestRoi, detectEachRoi)
{ {
cv::Mat cpu = readImage (GET_PARAM(1)); cv::Mat cpu = cv::imread(getDataPath(get<1>(GetParam())));
ASSERT_FALSE(cpu.empty()); ASSERT_FALSE(cpu.empty());
cv::gpu::GpuMat colored(cpu); cv::gpu::GpuMat colored(cpu);
cv::gpu::SCascade cascade; cv::softcascade::SCascade cascade;
cv::FileStorage fs(perf::TestBase::getDataPath(GET_PARAM(0)), cv::FileStorage::READ); cv::FileStorage fs(getDataPath(get<0>(GetParam())), cv::FileStorage::READ);
ASSERT_TRUE(fs.isOpened()); ASSERT_TRUE(fs.isOpened());
ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode())); ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode()));
...@@ -177,7 +179,7 @@ RUN_GPU(SCascadeTestRoi, detectEachRoi) ...@@ -177,7 +179,7 @@ RUN_GPU(SCascadeTestRoi, detectEachRoi)
cv::gpu::GpuMat objectBoxes(1, 16384 * 20, CV_8UC1), rois(colored.size(), CV_8UC1); cv::gpu::GpuMat objectBoxes(1, 16384 * 20, CV_8UC1), rois(colored.size(), CV_8UC1);
rois.setTo(0); rois.setTo(0);
int idx = GET_PARAM(2); int idx = get<2>(GetParam());
cv::Rect r = getFromTable(idx); cv::Rect r = getFromTable(idx);
cv::gpu::GpuMat sub(rois, r); cv::gpu::GpuMat sub(rois, r);
sub.setTo(1); sub.setTo(1);
...@@ -202,18 +204,18 @@ SC_PERF_TEST_P(SCascadeTest, detectStream, ...@@ -202,18 +204,18 @@ SC_PERF_TEST_P(SCascadeTest, detectStream,
RUN_GPU(SCascadeTest, detectStream) RUN_GPU(SCascadeTest, detectStream)
{ {
cv::Mat cpu = readImage (GET_PARAM(1)); cv::Mat cpu = cv::imread(getDataPath(get<1>(GetParam())));
ASSERT_FALSE(cpu.empty()); ASSERT_FALSE(cpu.empty());
cv::gpu::GpuMat colored(cpu); cv::gpu::GpuMat colored(cpu);
cv::gpu::SCascade cascade; cv::softcascade::SCascade cascade;
cv::FileStorage fs(perf::TestBase::getDataPath(GET_PARAM(0)), cv::FileStorage::READ); cv::FileStorage fs(getDataPath(get<0>(GetParam())), cv::FileStorage::READ);
ASSERT_TRUE(fs.isOpened()); ASSERT_TRUE(fs.isOpened());
ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode())); ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode()));
cv::gpu::GpuMat objectBoxes(1, 10000 * sizeof(cv::gpu::SCascade::Detection), CV_8UC1), rois(colored.size(), CV_8UC1); cv::gpu::GpuMat objectBoxes(1, 10000 * sizeof(cv::softcascade::SCascade::Detection), CV_8UC1), rois(colored.size(), CV_8UC1);
rois.setTo(1); rois.setTo(1);
cv::gpu::Stream s; cv::gpu::Stream s;
......
...@@ -43,12 +43,11 @@ ...@@ -43,12 +43,11 @@
#include <opencv2/gpu/device/common.hpp> #include <opencv2/gpu/device/common.hpp>
#include <opencv2/gpu/device/saturate_cast.hpp> #include <opencv2/gpu/device/saturate_cast.hpp>
#include <icf.hpp> #include <cuda_invoker.hpp>
#include <float.h> #include <float.h>
#include <stdio.h> #include <stdio.h>
namespace cv { namespace gpu { namespace device { namespace cv { namespace softcascade { namespace device {
namespace icf {
template <int FACTOR> template <int FACTOR>
__device__ __forceinline__ uchar shrink(const uchar* ptr, const int pitch, const int y, const int x) __device__ __forceinline__ uchar shrink(const uchar* ptr, const int pitch, const int y, const int x)
...@@ -303,7 +302,7 @@ namespace icf { ...@@ -303,7 +302,7 @@ namespace icf {
excluded = excluded || (suppessed == i); excluded = excluded || (suppessed == i);
} }
#if __CUDA_ARCH__ >= 120 #if defined __CUDA_ARCH__ && (__CUDA_ARCH__ >= 120)
if (__all(excluded)) break; if (__all(excluded)) break;
#endif #endif
} }
...@@ -348,7 +347,7 @@ namespace icf { ...@@ -348,7 +347,7 @@ namespace icf {
template<typename Policy> template<typename Policy>
struct PrefixSum struct PrefixSum
{ {
__device static void apply(float& impact) __device_inline__ static void apply(float& impact)
{ {
#if defined __CUDA_ARCH__ && __CUDA_ARCH__ >= 300 #if defined __CUDA_ARCH__ && __CUDA_ARCH__ >= 300
#pragma unroll #pragma unroll
...@@ -442,6 +441,7 @@ namespace icf { ...@@ -442,6 +441,7 @@ namespace icf {
{ {
x += area.x; x += area.x;
y += area.y; y += area.y;
int a = tex2D(thogluv, x, y); int a = tex2D(thogluv, x, y);
int b = tex2D(thogluv, x + area.z, y); int b = tex2D(thogluv, x + area.z, y);
int c = tex2D(thogluv, x + area.z, y + area.w); int c = tex2D(thogluv, x + area.z, y + area.w);
...@@ -454,7 +454,7 @@ namespace icf { ...@@ -454,7 +454,7 @@ namespace icf {
template<typename Policy> template<typename Policy>
template<bool isUp> template<bool isUp>
__device void CascadeInvoker<Policy>::detect(Detection* objects, const uint ndetections, uint* ctr, const int downscales) const __device_inline__ void CascadeInvoker<Policy>::detect(Detection* objects, const uint ndetections, uint* ctr, const int downscales) const
{ {
const int y = blockIdx.y * blockDim.y + threadIdx.y; const int y = blockIdx.y * blockDim.y + threadIdx.y;
const int x = blockIdx.x; const int x = blockIdx.x;
...@@ -563,5 +563,4 @@ void CascadeInvoker<Policy>::operator()(const PtrStepSzb& roi, const PtrStepSzi& ...@@ -563,5 +563,4 @@ void CascadeInvoker<Policy>::operator()(const PtrStepSzb& roi, const PtrStepSzi&
template void CascadeInvoker<GK107PolicyX4>::operator()(const PtrStepSzb& roi, const PtrStepSzi& hogluv, template void CascadeInvoker<GK107PolicyX4>::operator()(const PtrStepSzb& roi, const PtrStepSzi& hogluv,
PtrStepSz<uchar4> objects, const int downscales, const cudaStream_t& stream) const; PtrStepSz<uchar4> objects, const int downscales, const cudaStream_t& stream) const;
}
}}} }}}
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
// //
// * Redistribution's in binary form must reproduce the above copyright notice, // * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation // this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. // and / or other materials provided with the distribution.
// //
// * The name of the copyright holders may not be used to endorse or promote products // * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission. // derived from this software without specific prior written permission.
...@@ -46,15 +46,16 @@ ...@@ -46,15 +46,16 @@
#include <opencv2/gpu/device/common.hpp> #include <opencv2/gpu/device/common.hpp>
using namespace cv::gpu::device;
#if defined __CUDACC__ #if defined __CUDACC__
# define __device __device__ __forceinline__ # define __device_inline__ __device__ __forceinline__
#else #else
# define __device # define __device_inline__
#endif #endif
namespace cv { namespace gpu { namespace device { namespace cv { namespace softcascade { namespace device {
namespace icf {
struct Octave struct Octave
{ {
...@@ -68,20 +69,19 @@ struct Octave ...@@ -68,20 +69,19 @@ struct Octave
: index(i), stages(s), shrinkage(sh), size(sz), scale(sc) {} : index(i), stages(s), shrinkage(sh), size(sz), scale(sc) {}
}; };
struct Level //is actually 24 bytes struct Level
{ {
int octave; int octave;
int step; int step;
float relScale; float relScale;
float scaling[2]; // calculated according to Dollal paper float scaling[2];// calculated according to Dollar paper
// for 640x480 we can not get overflow
uchar2 workRect; uchar2 workRect;
uchar2 objSize; uchar2 objSize;
Level(int idx, const Octave& oct, const float scale, const int w, const int h); Level(int idx, const Octave& oct, const float scale, const int w, const int h);
__device Level(){} __device_inline__ Level(){}
}; };
struct Node struct Node
...@@ -106,7 +106,7 @@ struct Detection ...@@ -106,7 +106,7 @@ struct Detection
int kind; int kind;
Detection(){} Detection(){}
__device Detection(int _x, int _y, uchar _w, uchar _h, float c) __device_inline__ Detection(int _x, int _y, uchar _w, uchar _h, float c)
: x(_x), y(_y), w(_w), h(_h), confidence(c), kind(0) {}; : x(_x), y(_y), w(_w), h(_h), confidence(c), kind(0) {};
}; };
...@@ -125,8 +125,8 @@ struct CascadeInvoker ...@@ -125,8 +125,8 @@ struct CascadeInvoker
{ {
CascadeInvoker(): levels(0), stages(0), nodes(0), leaves(0), scales(0) {} CascadeInvoker(): levels(0), stages(0), nodes(0), leaves(0), scales(0) {}
CascadeInvoker(const PtrStepSzb& _levels, const PtrStepSzf& _stages, CascadeInvoker(const cv::gpu::PtrStepSzb& _levels, const cv::gpu::PtrStepSzf& _stages,
const PtrStepSzb& _nodes, const PtrStepSzf& _leaves) const cv::gpu::PtrStepSzb& _nodes, const cv::gpu::PtrStepSzf& _leaves)
: levels((const Level*)_levels.ptr()), : levels((const Level*)_levels.ptr()),
stages((const float*)_stages.ptr()), stages((const float*)_stages.ptr()),
nodes((const Node*)_nodes.ptr()), leaves((const float*)_leaves.ptr()), nodes((const Node*)_nodes.ptr()), leaves((const float*)_leaves.ptr()),
...@@ -141,14 +141,13 @@ struct CascadeInvoker ...@@ -141,14 +141,13 @@ struct CascadeInvoker
int scales; int scales;
void operator()(const PtrStepSzb& roi, const PtrStepSzi& hogluv, PtrStepSz<uchar4> objects, void operator()(const cv::gpu::PtrStepSzb& roi, const cv::gpu::PtrStepSzi& hogluv, cv::gpu::PtrStepSz<uchar4> objects,
const int downscales, const cudaStream_t& stream = 0) const; const int downscales, const cudaStream_t& stream = 0) const;
template<bool isUp> template<bool isUp>
__device void detect(Detection* objects, const unsigned int ndetections, unsigned int* ctr, const int downscales) const; __device_inline__ void detect(Detection* objects, const unsigned int ndetections, unsigned int* ctr, const int downscales) const;
}; };
}
}}} }}}
#endif #endif
\ No newline at end of file
...@@ -51,11 +51,16 @@ CV_INIT_ALGORITHM(Detector, "SoftCascade.Detector", ...@@ -51,11 +51,16 @@ CV_INIT_ALGORITHM(Detector, "SoftCascade.Detector",
obj.info()->addParam(obj, "scales", obj.scales); obj.info()->addParam(obj, "scales", obj.scales);
obj.info()->addParam(obj, "rejCriteria", obj.rejCriteria)); obj.info()->addParam(obj, "rejCriteria", obj.rejCriteria));
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));
bool initModule_softcascade(void) bool initModule_softcascade(void)
{ {
Ptr<Algorithm> sc = createSCascade();
Ptr<Algorithm> sc1 = createDetector(); Ptr<Algorithm> sc1 = createDetector();
return (sc1->info() != 0); return (sc1->info() != 0) && (sc->info() != 0);
} }
} } } }
\ No newline at end of file
...@@ -41,10 +41,9 @@ ...@@ -41,10 +41,9 @@
//M*/ //M*/
#include "test_precomp.hpp" #include "test_precomp.hpp"
#include "opencv2/core/gpumat.hpp"
#ifdef HAVE_CUDA using std::tr1::get;
using cv::gpu::GpuMat;
// show detection results on input image with cv::imshow // show detection results on input image with cv::imshow
//#define SHOW_DETECTIONS //#define SHOW_DETECTIONS
...@@ -59,7 +58,7 @@ using cv::gpu::GpuMat; ...@@ -59,7 +58,7 @@ using cv::gpu::GpuMat;
static std::string path(std::string relative) static std::string path(std::string relative)
{ {
return cvtest::TS::ptr()->get_data_path() + "../cv/cascadeandhog/" + relative; return cvtest::TS::ptr()->get_data_path() + "cascadeandhog/" + relative;
} }
TEST(SCascadeTest, readCascade) TEST(SCascadeTest, readCascade)
...@@ -67,7 +66,7 @@ TEST(SCascadeTest, readCascade) ...@@ -67,7 +66,7 @@ TEST(SCascadeTest, readCascade)
std::string xml = path("cascades/inria_caltech-17.01.2013.xml"); std::string xml = path("cascades/inria_caltech-17.01.2013.xml");
cv::FileStorage fs(xml, cv::FileStorage::READ); cv::FileStorage fs(xml, cv::FileStorage::READ);
cv::gpu::SCascade cascade; cv::softcascade::SCascade cascade;
ASSERT_TRUE(fs.isOpened()); ASSERT_TRUE(fs.isOpened());
ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode())); ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode()));
...@@ -75,7 +74,7 @@ TEST(SCascadeTest, readCascade) ...@@ -75,7 +74,7 @@ TEST(SCascadeTest, readCascade)
namespace namespace
{ {
typedef cv::gpu::SCascade::Detection Detection; typedef cv::softcascade::SCascade::Detection Detection;
cv::Rect getFromTable(int idx) cv::Rect getFromTable(int idx)
{ {
...@@ -97,7 +96,6 @@ namespace ...@@ -97,7 +96,6 @@ namespace
return rois[idx]; return rois[idx];
} }
void print(std::ostream &out, const Detection& d) void print(std::ostream &out, const Detection& d)
{ {
#if defined SHOW_DETECTIONS #if defined SHOW_DETECTIONS
...@@ -156,36 +154,36 @@ namespace ...@@ -156,36 +154,36 @@ namespace
#endif #endif
} }
PARAM_TEST_CASE(SCascadeTestRoi, cv::gpu::DeviceInfo, std::string, std::string, int) class SCascadeTestRoi : public ::testing::TestWithParam<std::tr1::tuple<cv::gpu::DeviceInfo, std::string, std::string, int> >
{ {
virtual void SetUp() virtual void SetUp()
{ {
cv::gpu::setDevice(GET_PARAM(0).deviceID()); cv::gpu::setDevice(get<0>(GetParam()).deviceID());
} }
}; };
GPU_TEST_P(SCascadeTestRoi, Detect) TEST_P(SCascadeTestRoi, Detect)
{ {
cv::Mat coloredCpu = cv::imread(path(GET_PARAM(2))); cv::Mat coloredCpu = cv::imread(path(get<2>(GetParam())));
ASSERT_FALSE(coloredCpu.empty()); ASSERT_FALSE(coloredCpu.empty());
cv::gpu::SCascade cascade; cv::softcascade::SCascade cascade;
cv::FileStorage fs(path(GET_PARAM(1)), cv::FileStorage::READ); cv::FileStorage fs(path(get<1>(GetParam())), cv::FileStorage::READ);
ASSERT_TRUE(fs.isOpened()); ASSERT_TRUE(fs.isOpened());
ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode())); ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode()));
GpuMat colored(coloredCpu), objectBoxes(1, 16384, CV_8UC1), rois(colored.size(), CV_8UC1); cv::gpu::GpuMat colored(coloredCpu), objectBoxes(1, 16384, CV_8UC1), rois(colored.size(), CV_8UC1);
rois.setTo(0); rois.setTo(0);
int nroi = GET_PARAM(3); int nroi = get<3>(GetParam());
cv::Mat result(coloredCpu); cv::Mat result(coloredCpu);
cv::RNG rng; cv::RNG rng;
for (int i = 0; i < nroi; ++i) for (int i = 0; i < nroi; ++i)
{ {
cv::Rect r = getFromTable(rng(10)); cv::Rect r = getFromTable(rng(10));
GpuMat sub(rois, r); cv::gpu::GpuMat sub(rois, r);
sub.setTo(1); sub.setTo(1);
cv::rectangle(result, r, cv::Scalar(0, 0, 255, 255), 1); cv::rectangle(result, r, cv::Scalar(0, 0, 255, 255), 1);
} }
...@@ -194,7 +192,7 @@ GPU_TEST_P(SCascadeTestRoi, Detect) ...@@ -194,7 +192,7 @@ GPU_TEST_P(SCascadeTestRoi, Detect)
cascade.detect(colored, rois, objectBoxes); cascade.detect(colored, rois, objectBoxes);
cv::Mat dt(objectBoxes); cv::Mat dt(objectBoxes);
typedef cv::gpu::SCascade::Detection Detection; typedef cv::softcascade::SCascade::Detection Detection;
Detection* dts = ((Detection*)dt.data) + 1; Detection* dts = ((Detection*)dt.data) + 1;
int* count = dt.ptr<int>(0); int* count = dt.ptr<int>(0);
...@@ -211,15 +209,13 @@ GPU_TEST_P(SCascadeTestRoi, Detect) ...@@ -211,15 +209,13 @@ GPU_TEST_P(SCascadeTestRoi, Detect)
SHOW(result); SHOW(result);
} }
INSTANTIATE_TEST_CASE_P(GPU_SoftCascade, SCascadeTestRoi, testing::Combine( INSTANTIATE_TEST_CASE_P(cuda_accelerated, SCascadeTestRoi, testing::Combine(
ALL_DEVICES, testing::ValuesIn(DeviceManager::instance().values()),
testing::Values(std::string("cascades/inria_caltech-17.01.2013.xml"), testing::Values(std::string("cascades/inria_caltech-17.01.2013.xml"),
std::string("cascades/sc_cvpr_2012_to_opencv_new_format.xml")), std::string("cascades/sc_cvpr_2012_to_opencv_new_format.xml")),
testing::Values(std::string("images/image_00000000_0.png")), testing::Values(std::string("images/image_00000000_0.png")),
testing::Range(0, 5))); testing::Range(0, 5)));
////////////////////////////////////////
namespace { namespace {
struct Fixture struct Fixture
...@@ -232,23 +228,24 @@ struct Fixture ...@@ -232,23 +228,24 @@ struct Fixture
}; };
} }
PARAM_TEST_CASE(SCascadeTestAll, cv::gpu::DeviceInfo, Fixture) typedef std::tr1::tuple<cv::gpu::DeviceInfo, Fixture> SCascadeTestAllFixture;
class SCascadeTestAll : public ::testing::TestWithParam<SCascadeTestAllFixture>
{ {
protected:
std::string xml; std::string xml;
int expected; int expected;
virtual void SetUp() virtual void SetUp()
{ {
cv::gpu::setDevice(GET_PARAM(0).deviceID()); cv::gpu::setDevice(get<0>(GetParam()).deviceID());
xml = path(GET_PARAM(1).path); xml = path(get<1>(GetParam()).path);
expected = GET_PARAM(1).expected; expected = get<1>(GetParam()).expected;
} }
}; };
GPU_TEST_P(SCascadeTestAll, detect) TEST_P(SCascadeTestAll, detect)
{ {
cv::gpu::SCascade cascade; cv::softcascade::SCascade cascade;
cv::FileStorage fs(xml, cv::FileStorage::READ); cv::FileStorage fs(xml, cv::FileStorage::READ);
ASSERT_TRUE(fs.isOpened()); ASSERT_TRUE(fs.isOpened());
...@@ -258,12 +255,12 @@ GPU_TEST_P(SCascadeTestAll, detect) ...@@ -258,12 +255,12 @@ GPU_TEST_P(SCascadeTestAll, detect)
cv::Mat coloredCpu = cv::imread(path("images/image_00000000_0.png")); cv::Mat coloredCpu = cv::imread(path("images/image_00000000_0.png"));
ASSERT_FALSE(coloredCpu.empty()); ASSERT_FALSE(coloredCpu.empty());
GpuMat colored(coloredCpu), objectBoxes, rois(colored.size(), CV_8UC1); cv::gpu::GpuMat colored(coloredCpu), objectBoxes, rois(colored.size(), CV_8UC1);
rois.setTo(1); rois.setTo(1);
cascade.detect(colored, rois, objectBoxes); cascade.detect(colored, rois, objectBoxes);
typedef cv::gpu::SCascade::Detection Detection; typedef cv::softcascade::SCascade::Detection Detection;
cv::Mat dt(objectBoxes); cv::Mat dt(objectBoxes);
...@@ -283,9 +280,9 @@ GPU_TEST_P(SCascadeTestAll, detect) ...@@ -283,9 +280,9 @@ GPU_TEST_P(SCascadeTestAll, detect)
ASSERT_EQ(*count, expected); ASSERT_EQ(*count, expected);
} }
GPU_TEST_P(SCascadeTestAll, detectStream) TEST_P(SCascadeTestAll, detectStream)
{ {
cv::gpu::SCascade cascade; cv::softcascade::SCascade cascade;
cv::FileStorage fs(xml, cv::FileStorage::READ); cv::FileStorage fs(xml, cv::FileStorage::READ);
ASSERT_TRUE(fs.isOpened()); ASSERT_TRUE(fs.isOpened());
...@@ -295,7 +292,7 @@ GPU_TEST_P(SCascadeTestAll, detectStream) ...@@ -295,7 +292,7 @@ GPU_TEST_P(SCascadeTestAll, detectStream)
cv::Mat coloredCpu = cv::imread(path("images/image_00000000_0.png")); cv::Mat coloredCpu = cv::imread(path("images/image_00000000_0.png"));
ASSERT_FALSE(coloredCpu.empty()); ASSERT_FALSE(coloredCpu.empty());
GpuMat colored(coloredCpu), objectBoxes(1, 100000, CV_8UC1), rois(colored.size(), CV_8UC1); cv::gpu::GpuMat colored(coloredCpu), objectBoxes(1, 100000, CV_8UC1), rois(colored.size(), CV_8UC1);
rois.setTo(cv::Scalar::all(1)); rois.setTo(cv::Scalar::all(1));
cv::gpu::Stream s; cv::gpu::Stream s;
...@@ -304,14 +301,12 @@ GPU_TEST_P(SCascadeTestAll, detectStream) ...@@ -304,14 +301,12 @@ GPU_TEST_P(SCascadeTestAll, detectStream)
cascade.detect(colored, rois, objectBoxes, s); cascade.detect(colored, rois, objectBoxes, s);
s.waitForCompletion(); s.waitForCompletion();
typedef cv::gpu::SCascade::Detection Detection; typedef cv::softcascade::SCascade::Detection Detection;
cv::Mat detections(objectBoxes); cv::Mat detections(objectBoxes);
int a = *(detections.ptr<int>(0)); int a = *(detections.ptr<int>(0));
ASSERT_EQ(a, expected); ASSERT_EQ(a, expected);
} }
INSTANTIATE_TEST_CASE_P(GPU_SoftCascade, SCascadeTestAll, testing::Combine( ALL_DEVICES, INSTANTIATE_TEST_CASE_P(cuda_accelerated, SCascadeTestAll, testing::Combine( ALL_DEVICES,
testing::Values(Fixture("cascades/inria_caltech-17.01.2013.xml", 7), testing::Values(Fixture("cascades/inria_caltech-17.01.2013.xml", 7),
Fixture("cascades/sc_cvpr_2012_to_opencv_new_format.xml", 1291)))); Fixture("cascades/sc_cvpr_2012_to_opencv_new_format.xml", 1291))));
\ No newline at end of file
#endif
/*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.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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 "test_precomp.hpp"
#ifdef HAVE_CUDA
using namespace std;
using namespace cv;
using namespace cv::gpu;
using namespace cvtest;
using namespace testing;
using namespace testing::internal;
//////////////////////////////////////////////////////////////////////
// Gpu devices
bool supportFeature(const DeviceInfo& info, FeatureSet feature)
{
return TargetArchs::builtWith(feature) && info.supports(feature);
}
DeviceManager& DeviceManager::instance()
{
static DeviceManager obj;
return obj;
}
void DeviceManager::load(int i)
{
devices_.clear();
devices_.reserve(1);
std::ostringstream msg;
if (i < 0 || i >= getCudaEnabledDeviceCount())
{
msg << "Incorrect device number - " << i;
CV_Error(CV_StsBadArg, msg.str());
}
DeviceInfo info(i);
if (!info.isCompatible())
{
msg << "Device " << i << " [" << info.name() << "] is NOT compatible with current GPU module build";
CV_Error(CV_StsBadArg, msg.str());
}
devices_.push_back(info);
}
void DeviceManager::loadAll()
{
int deviceCount = getCudaEnabledDeviceCount();
devices_.clear();
devices_.reserve(deviceCount);
for (int i = 0; i < deviceCount; ++i)
{
DeviceInfo info(i);
if (info.isCompatible())
{
devices_.push_back(info);
}
}
}
#endif // HAVE_CUDA
...@@ -7,11 +7,10 @@ ...@@ -7,11 +7,10 @@
// copy or use the software. // copy or use the software.
// //
// //
// License Agreement // Intel License Agreement
// For Open Source Computer Vision Library // For Open Source Computer Vision Library
// //
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. // Copyright (C) 2000, Intel Corporation, all rights reserved.
// Copyright (C) 2008-2012, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners. // Third party copyrights are property of their respective owners.
// //
// Redistribution and use in source and binary forms, with or without modification, // Redistribution and use in source and binary forms, with or without modification,
...@@ -24,7 +23,7 @@ ...@@ -24,7 +23,7 @@
// this list of conditions and the following disclaimer in the documentation // this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. // and/or other materials provided with the distribution.
// //
// * The name of the copyright holders may not be used to endorse or promote products // * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission. // derived from this software without specific prior written permission.
// //
// This software is provided by the copyright holders and contributors "as is" and // This software is provided by the copyright holders and contributors "as is" and
...@@ -40,20 +39,35 @@ ...@@ -40,20 +39,35 @@
// //
//M*/ //M*/
#include "precomp.hpp" #ifndef __OPENCV_SOFTCASCADE_TEST_UTILITY_HPP__
#define __OPENCV_SOFTCASCADE_TEST_UTILITY_HPP__
namespace cv { namespace gpu #include "opencv2/core/core.hpp"
{ #include "opencv2/core/gpumat.hpp"
#include "opencv2/ts/ts.hpp"
#include "opencv2/ts/ts_perf.hpp"
CV_INIT_ALGORITHM(SCascade, "CascadeDetector.SCascade", //////////////////////////////////////////////////////////////////////
obj.info()->addParam(obj, "minScale", obj.minScale); // Gpu devices
obj.info()->addParam(obj, "maxScale", obj.maxScale); //! return true if device supports specified feature and gpu module was built with support the feature.
obj.info()->addParam(obj, "scales", obj.scales)); bool supportFeature(const cv::gpu::DeviceInfo& info, cv::gpu::FeatureSet feature);
bool initModule_gpu(void) class DeviceManager
{ {
Ptr<Algorithm> sc = createSCascade(); public:
return sc->info() != 0; static DeviceManager& instance();
}
void load(int i);
void loadAll();
const std::vector<cv::gpu::DeviceInfo>& values() const { return devices_; }
private:
std::vector<cv::gpu::DeviceInfo> devices_;
DeviceManager() {loadAll();}
};
#define ALL_DEVICES testing::ValuesIn(DeviceManager::instance().values())
} } #endif // __OPENCV_GPU_TEST_UTILITY_HPP__
\ No newline at end of file
SET(OPENCV_GPU_SAMPLES_REQUIRED_DEPS opencv_core opencv_flann opencv_imgproc opencv_highgui SET(OPENCV_GPU_SAMPLES_REQUIRED_DEPS opencv_core opencv_flann opencv_imgproc opencv_highgui
opencv_ml opencv_video opencv_objdetect opencv_features2d opencv_ml opencv_video opencv_objdetect opencv_features2d
opencv_calib3d opencv_legacy opencv_contrib opencv_gpu opencv_calib3d opencv_legacy opencv_contrib opencv_gpu
opencv_nonfree) opencv_nonfree opencv_softcascade)
ocv_check_dependencies(${OPENCV_GPU_SAMPLES_REQUIRED_DEPS}) ocv_check_dependencies(${OPENCV_GPU_SAMPLES_REQUIRED_DEPS})
......
#include <opencv2/gpu/gpu.hpp> #include <opencv2/gpu/gpu.hpp>
#include <opencv2/softcascade/softcascade.hpp>
#include <opencv2/highgui/highgui.hpp> #include <opencv2/highgui/highgui.hpp>
#include <iostream> #include <iostream>
...@@ -46,7 +47,7 @@ int main(int argc, char** argv) ...@@ -46,7 +47,7 @@ int main(int argc, char** argv)
float maxScale = parser.get<float>("max_scale"); float maxScale = parser.get<float>("max_scale");
int scales = parser.get<int>("total_scales"); int scales = parser.get<int>("total_scales");
using cv::gpu::SCascade; using cv::softcascade::SCascade;
SCascade cascade(minScale, maxScale, scales); SCascade cascade(minScale, maxScale, scales);
if (!cascade.load(fs.getFirstTopLevelNode())) if (!cascade.load(fs.getFirstTopLevelNode()))
...@@ -79,7 +80,7 @@ int main(int argc, char** argv) ...@@ -79,7 +80,7 @@ int main(int argc, char** argv)
cascade.detect(dframe, roi, objects); cascade.detect(dframe, roi, objects);
cv::Mat dt(objects); cv::Mat dt(objects);
typedef cv::gpu::SCascade::Detection Detection; typedef cv::softcascade::SCascade::Detection Detection;
Detection* dts = ((Detection*)dt.data) + 1; Detection* dts = ((Detection*)dt.data) + 1;
int* count = dt.ptr<int>(0); int* count = dt.ptr<int>(0);
......
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