merged ICFPreprocessor and Channels -> ChannelFeatureBuilder

This commit is contained in:
marina.kolpakova 2013-01-29 16:55:01 +04:00
parent 49ec664238
commit f3227c3f1a
10 changed files with 151 additions and 241 deletions

View File

@ -51,11 +51,12 @@ sft::ICFFeaturePool::ICFFeaturePool(cv::Size m, int n) : FeaturePool(), model(m)
{ {
CV_Assert(m != cv::Size() && n > 0); CV_Assert(m != cv::Size() && n > 0);
fill(nfeatures); fill(nfeatures);
builder = cv::ChannelFeatureBuilder::create();
} }
void sft::ICFFeaturePool::preprocess(cv::InputArray frame, cv::OutputArray integrals) const void sft::ICFFeaturePool::preprocess(cv::InputArray frame, cv::OutputArray integrals) const
{ {
preprocessor.apply(frame, integrals); (*builder)(frame, integrals);
} }
float sft::ICFFeaturePool::apply(int fi, int si, const Mat& integrals) const float sft::ICFFeaturePool::apply(int fi, int si, const Mat& integrals) const

View File

@ -119,7 +119,7 @@ private:
static const unsigned int seed = 0; static const unsigned int seed = 0;
cv::ICFPreprocessor preprocessor; cv::Ptr<cv::ChannelFeatureBuilder> builder;
enum { N_CHANNELS = 10 }; enum { N_CHANNELS = 10 };
}; };

View File

@ -10,7 +10,7 @@ if(ANDROID OR IOS OR NOT PYTHONLIBS_FOUND OR NOT PYTHON_USE_NUMPY)
endif() endif()
set(the_description "The python bindings") set(the_description "The python bindings")
ocv_add_module(python BINDINGS opencv_core opencv_flann opencv_imgproc opencv_video opencv_ml opencv_features2d opencv_highgui opencv_calib3d opencv_photo opencv_objdetect opencv_contrib opencv_legacy OPTIONAL opencv_nonfree) ocv_add_module(python BINDINGS opencv_core opencv_flann opencv_imgproc opencv_video opencv_ml opencv_features2d opencv_highgui opencv_calib3d opencv_photo opencv_objdetect opencv_contrib opencv_legacy opencv_softcascade OPTIONAL opencv_nonfree)
add_definitions(-DPYTHON_USE_NUMPY=1) add_definitions(-DPYTHON_USE_NUMPY=1)

View File

@ -16,6 +16,7 @@
#include "opencv2/ml/ml.hpp" #include "opencv2/ml/ml.hpp"
#include "opencv2/features2d/features2d.hpp" #include "opencv2/features2d/features2d.hpp"
#include "opencv2/objdetect/objdetect.hpp" #include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/softcascade/softcascade.hpp"
#include "opencv2/video/tracking.hpp" #include "opencv2/video/tracking.hpp"
#include "opencv2/video/background_segm.hpp" #include "opencv2/video/background_segm.hpp"
#include "opencv2/photo/photo.hpp" #include "opencv2/photo/photo.hpp"
@ -124,6 +125,8 @@ typedef Ptr<DescriptorExtractor> Ptr_DescriptorExtractor;
typedef Ptr<Feature2D> Ptr_Feature2D; typedef Ptr<Feature2D> Ptr_Feature2D;
typedef Ptr<DescriptorMatcher> Ptr_DescriptorMatcher; typedef Ptr<DescriptorMatcher> Ptr_DescriptorMatcher;
typedef Ptr<ChannelFeatureBuilder> Ptr_ChannelFeatureBuilder;
typedef SimpleBlobDetector::Params SimpleBlobDetector_Params; typedef SimpleBlobDetector::Params SimpleBlobDetector_Params;
typedef cvflann::flann_distance_t cvflann_flann_distance_t; typedef cvflann::flann_distance_t cvflann_flann_distance_t;

View File

@ -93,53 +93,15 @@ public:
// Implementation of Integral Channel Feature. // Implementation of Integral Channel Feature.
// ========================================================================== // // ========================================================================== //
class CV_EXPORTS_W IntegralChannelBuilder : public Algorithm class CV_EXPORTS_W ChannelFeatureBuilder : public Algorithm
{ {
public: public:
CV_WRAP IntegralChannelBuilder(); virtual ~ChannelFeatureBuilder();
CV_WRAP virtual ~IntegralChannelBuilder();
cv::AlgorithmInfo* info() const; // apply channels to source frame
CV_WRAP_AS(compute) virtual void operator()(InputArray src, CV_OUT OutputArray channels) const = 0;
// Load channel builder config. CV_WRAP static cv::Ptr<ChannelFeatureBuilder> create();
CV_WRAP virtual void read(const FileNode& fileNode);
private:
struct Fields;
cv::Ptr<Fields> fields;
};
// Create channel integrals for Soft Cascade detector.
class CV_EXPORTS Channels
{
public:
// constrictor form resizing factor.
// Param shrinkage is a resizing factor. Resize is applied before the computing integral sum
Channels(const int shrinkage);
// Appends specified number of HOG first-order features integrals into given vector.
// Param gray is an input 1-channel gray image.
// Param integrals is a vector of integrals. Hog-channels will be appended to it.
// Param bins is a number of hog-bins
void appendHogBins(const cv::Mat& gray, std::vector<cv::Mat>& integrals, int bins) const;
// Converts 3-channel BGR input frame in Luv and appends each channel to the integrals.
// Param frame is an input 3-channel BGR colored image.
// Param integrals is a vector of integrals. Computed from the frame luv-channels will be appended to it.
void appendLuvBins(const cv::Mat& frame, std::vector<cv::Mat>& integrals) const;
private:
int shrinkage;
};
class CV_EXPORTS_W ICFPreprocessor
{
public:
CV_WRAP ICFPreprocessor();
CV_WRAP void apply(cv::InputArray _frame, cv::OutputArray _integrals) const;
protected:
enum {BINS = 10};
}; };
// ========================================================================== // // ========================================================================== //

View File

@ -1,170 +0,0 @@
/*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-2013, 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"
cv::ICFPreprocessor::ICFPreprocessor() {}
void cv::ICFPreprocessor::apply(cv::InputArray _frame, cv::OutputArray _integrals) const
{
CV_Assert(_frame.type() == CV_8UC3);
cv::Mat frame = _frame.getMat();
cv::Mat& integrals = _integrals.getMatRef();
int h = frame.rows;
int w = frame.cols;
cv::Mat channels, gray;
channels.create(h * BINS, w, CV_8UC1);
channels.setTo(0);
cvtColor(frame, gray, CV_BGR2GRAY);
cv::Mat df_dx, df_dy, mag, angle;
cv::Sobel(gray, df_dx, CV_32F, 1, 0);
cv::Sobel(gray, df_dy, CV_32F, 0, 1);
cv::cartToPolar(df_dx, df_dy, mag, angle, true);
mag *= (1.f / (8 * sqrt(2.f)));
cv::Mat nmag;
mag.convertTo(nmag, CV_8UC1);
angle *= 6 / 360.f;
for (int y = 0; y < h; ++y)
{
uchar* magnitude = nmag.ptr<uchar>(y);
float* ang = angle.ptr<float>(y);
for (int x = 0; x < w; ++x)
{
channels.ptr<uchar>(y + (h * (int)ang[x]))[x] = magnitude[x];
}
}
cv::Mat luv, shrunk;
cv::cvtColor(frame, luv, CV_BGR2Luv);
std::vector<cv::Mat> splited;
for (int i = 0; i < 3; ++i)
splited.push_back(channels(cv::Rect(0, h * (7 + i), w, h)));
split(luv, splited);
float shrinkage = static_cast<float>(integrals.cols - 1) / channels.cols;
CV_Assert(shrinkage == 0.25);
cv::resize(channels, shrunk, cv::Size(), shrinkage, shrinkage, CV_INTER_AREA);
cv::integral(shrunk, integrals, cv::noArray(), CV_32S);
}
cv::Channels::Channels(int shr) : shrinkage(shr) {}
void cv::Channels::appendHogBins(const cv::Mat& gray, std::vector<cv::Mat>& integrals, int bins) const
{
CV_Assert(gray.type() == CV_8UC1);
int h = gray.rows;
int w = gray.cols;
CV_Assert(!(w % shrinkage) && !(h % shrinkage));
cv::Mat df_dx, df_dy, mag, angle;
cv::Sobel(gray, df_dx, CV_32F, 1, 0);
cv::Sobel(gray, df_dy, CV_32F, 0, 1);
cv::cartToPolar(df_dx, df_dy, mag, angle, true);
mag *= (1.f / (8 * sqrt(2.f)));
cv::Mat nmag;
mag.convertTo(nmag, CV_8UC1);
angle *= bins/360.f;
std::vector<cv::Mat> hist;
for (int bin = 0; bin < bins; ++bin)
hist.push_back(cv::Mat::zeros(h, w, CV_8UC1));
for (int y = 0; y < h; ++y)
{
uchar* magnitude = nmag.ptr<uchar>(y);
float* ang = angle.ptr<float>(y);
for (int x = 0; x < w; ++x)
{
hist[ (int)ang[x] ].ptr<uchar>(y)[x] = magnitude[x];
}
}
for(int i = 0; i < bins; ++i)
{
cv::Mat shrunk, sum;
cv::resize(hist[i], shrunk, cv::Size(), 1.0 / shrinkage, 1.0 / shrinkage, CV_INTER_AREA);
cv::integral(shrunk, sum, cv::noArray(), CV_32S);
integrals.push_back(sum);
}
cv::Mat shrMag;
cv::resize(nmag, shrMag, cv::Size(), 1.0 / shrinkage, 1.0 / shrinkage, CV_INTER_AREA);
cv::integral(shrMag, mag, cv::noArray(), CV_32S);
integrals.push_back(mag);
}
void cv::Channels::appendLuvBins(const cv::Mat& frame, std::vector<cv::Mat>& integrals) const
{
CV_Assert(frame.type() == CV_8UC3);
CV_Assert(!(frame.cols % shrinkage) && !(frame.rows % shrinkage));
cv::Mat luv, shrunk;
cv::cvtColor(frame, luv, CV_BGR2Luv);
cv::resize(luv, shrunk, cv::Size(), 1.0 / shrinkage, 1.0 / shrinkage, CV_INTER_AREA);
std::vector<cv::Mat> splited;
split(shrunk, splited);
for (size_t i = 0; i < splited.size(); ++i)
{
cv::Mat sum;
cv::integral(splited[i], sum, cv::noArray(), CV_32S);
integrals.push_back(sum);
}
}

View File

@ -42,14 +42,77 @@
#include "precomp.hpp" #include "precomp.hpp"
struct cv::IntegralChannelBuilder::Fields namespace {
class ICF : public cv::ChannelFeatureBuilder
{ {
virtual ~ICF() {}
virtual cv::AlgorithmInfo* info() const;
virtual void operator()(cv::InputArray _frame, CV_OUT cv::OutputArray _integrals) const
{
CV_Assert(_frame.type() == CV_8UC3);
cv::Mat frame = _frame.getMat();
int h = frame.rows;
int w = frame.cols;
_integrals.create(h / 4 * 10 + 1, w / 4 + 1, CV_32SC1);
cv::Mat& integrals = _integrals.getMatRef();
cv::Mat channels, gray;
channels.create(h * 10, w, CV_8UC1);
channels.setTo(0);
cvtColor(frame, gray, CV_BGR2GRAY);
cv::Mat df_dx, df_dy, mag, angle;
cv::Sobel(gray, df_dx, CV_32F, 1, 0);
cv::Sobel(gray, df_dy, CV_32F, 0, 1);
cv::cartToPolar(df_dx, df_dy, mag, angle, true);
mag *= (1.f / (8 * sqrt(2.f)));
cv::Mat nmag;
mag.convertTo(nmag, CV_8UC1);
angle *= 6 / 360.f;
for (int y = 0; y < h; ++y)
{
uchar* magnitude = nmag.ptr<uchar>(y);
float* ang = angle.ptr<float>(y);
for (int x = 0; x < w; ++x)
{
channels.ptr<uchar>(y + (h * (int)ang[x]))[x] = magnitude[x];
}
}
cv::Mat luv, shrunk;
cv::cvtColor(frame, luv, CV_BGR2Luv);
std::vector<cv::Mat> splited;
for (int i = 0; i < 3; ++i)
splited.push_back(channels(cv::Rect(0, h * (7 + i), w, h)));
split(luv, splited);
float shrinkage = static_cast<float>(integrals.cols - 1) / channels.cols;
CV_Assert(shrinkage == 0.25);
cv::resize(channels, shrunk, cv::Size(), shrinkage, shrinkage, CV_INTER_AREA);
cv::integral(shrunk, integrals, cv::noArray(), CV_32S);
}
}; };
cv::IntegralChannelBuilder::IntegralChannelBuilder() : fields(new Fields()) {} }
cv::IntegralChannelBuilder::~IntegralChannelBuilder() {}
CV_INIT_ALGORITHM(ICF, "ChannelFeatureBuilder.ICF", );
void cv::IntegralChannelBuilder::read(const FileNode& fn)
{ cv::ChannelFeatureBuilder::~ChannelFeatureBuilder() {}
Algorithm::read(fn);
cv::Ptr<cv::ChannelFeatureBuilder> cv::ChannelFeatureBuilder::create()
{
cv::Ptr<cv::ChannelFeatureBuilder> builder(new ICF());
return builder;
} }

View File

@ -169,37 +169,30 @@ struct Level
return (sarea == 0.0f)? threshold : (threshold * scaling[idx] * sarea); return (sarea == 0.0f)? threshold : (threshold * scaling[idx] * sarea);
} }
}; };
struct ChannelStorage struct ChannelStorage
{ {
std::vector<cv::Mat> hog; cv::Mat hog;
int shrinkage; int shrinkage;
int offset; int offset;
int step; int step;
int model_height;
cv::Ptr<cv::ChannelFeatureBuilder> builder;
enum {HOG_BINS = 6, HOG_LUV_BINS = 10}; enum {HOG_BINS = 6, HOG_LUV_BINS = 10};
ChannelStorage(const cv::Mat& colored, int shr) : shrinkage(shr) ChannelStorage(const cv::Mat& colored, int shr) : shrinkage(shr)
{ {
hog.clear(); builder = cv::ChannelFeatureBuilder::create();
hog.reserve(10); (*builder)(colored, hog);
cv::Channels ints(shr);
// convert to gray step = hog.step1();
cv::Mat grey; model_height = colored.rows / shrinkage;
cv::cvtColor(colored, grey, CV_BGR2GRAY);
ints.appendHogBins(grey, hog, 6);
ints.appendLuvBins(colored, hog);
step = hog[0].cols;
} }
float get(const int channel, const cv::Rect& area) const float get(const int channel, const cv::Rect& area) const
{ {
// CV_Assert(channel < HOG_LUV_BINS); const int *ptr = hog.ptr<const int>(0) + model_height * channel * step + offset;
const cv::Mat& m = hog[channel];
int *ptr = ((int*)(m.data)) + offset;
int a = ptr[area.y * step + area.x]; int a = ptr[area.y * step + area.x];
int b = ptr[area.y * step + area.width]; int b = ptr[area.y * step + area.width];
@ -509,7 +502,7 @@ void cv::SoftCascadeDetector::detectNoRoi(const cv::Mat& image, std::vector<Dete
} }
} }
if (rejCriteria != NO_REJECT) suppress(rejCriteria, objects); // if (rejCriteria != NO_REJECT) suppress(rejCriteria, objects);
} }
void cv::SoftCascadeDetector::detect(cv::InputArray _image, cv::InputArray _rois, std::vector<Detection>& objects) const void cv::SoftCascadeDetector::detect(cv::InputArray _image, cv::InputArray _rois, std::vector<Detection>& objects) const

View File

@ -51,13 +51,11 @@ CV_INIT_ALGORITHM(SoftCascadeDetector, "SoftCascade.SoftCascadeDetector",
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(IntegralChannelBuilder, "SoftCascade.IntegralChannelBuilder", );
bool initModule_softcascade(void) bool initModule_softcascade(void)
{ {
Ptr<Algorithm> sc1 = createSoftCascadeDetector(); Ptr<Algorithm> sc1 = createSoftCascadeDetector();
Ptr<Algorithm> sc2 = createIntegralChannelBuilder(); return (sc1->info() != 0);
return (sc1->info() != 0) && (sc2->info() != 0);
} }
} }

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-2013, 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 "test_precomp.hpp"
TEST(ChannelFeatureBuilderTest, info)
{
cv::Ptr<cv::ChannelFeatureBuilder> builder = cv::ChannelFeatureBuilder::create();
ASSERT_TRUE(builder->info() != 0);
}
TEST(ChannelFeatureBuilderTest, compute)
{
cv::Ptr<cv::ChannelFeatureBuilder> builder = cv::ChannelFeatureBuilder::create();
cv::Mat colored = cv::imread(cvtest::TS::ptr()->get_data_path() + "cascadeandhog/images/image_00000000_0.png");
cv::Mat ints;
(*builder)(colored, ints);
ASSERT_FALSE(ints.empty());
}