merged ICFPreprocessor and Channels -> ChannelFeatureBuilder

pull/322/head
marina.kolpakova 12 years ago
parent 49ec664238
commit f3227c3f1a
  1. 3
      apps/sft/fpool.cpp
  2. 2
      apps/sft/include/sft/fpool.hpp
  3. 2
      modules/python/CMakeLists.txt
  4. 3
      modules/python/src2/cv2.cpp
  5. 48
      modules/softcascade/include/opencv2/softcascade/softcascade.hpp
  6. 170
      modules/softcascade/src/icf.cpp
  7. 73
      modules/softcascade/src/integral_channel_builder.cpp
  8. 27
      modules/softcascade/src/softcascade.cpp
  9. 4
      modules/softcascade/src/softcascade_init.cpp
  10. 60
      modules/softcascade/test/test_channel_features.cpp

@ -51,11 +51,12 @@ sft::ICFFeaturePool::ICFFeaturePool(cv::Size m, int n) : FeaturePool(), model(m)
{
CV_Assert(m != cv::Size() && n > 0);
fill(nfeatures);
builder = cv::ChannelFeatureBuilder::create();
}
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

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

@ -10,7 +10,7 @@ if(ANDROID OR IOS OR NOT PYTHONLIBS_FOUND OR NOT PYTHON_USE_NUMPY)
endif()
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)

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

@ -93,53 +93,15 @@ public:
// Implementation of Integral Channel Feature.
// ========================================================================== //
class CV_EXPORTS_W IntegralChannelBuilder : public Algorithm
class CV_EXPORTS_W ChannelFeatureBuilder : public Algorithm
{
public:
CV_WRAP IntegralChannelBuilder();
CV_WRAP virtual ~IntegralChannelBuilder();
virtual ~ChannelFeatureBuilder();
cv::AlgorithmInfo* info() const;
// Load channel builder config.
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;
};
// apply channels to source frame
CV_WRAP_AS(compute) virtual void operator()(InputArray src, CV_OUT OutputArray channels) const = 0;
class CV_EXPORTS_W ICFPreprocessor
{
public:
CV_WRAP ICFPreprocessor();
CV_WRAP void apply(cv::InputArray _frame, cv::OutputArray _integrals) const;
protected:
enum {BINS = 10};
CV_WRAP static cv::Ptr<ChannelFeatureBuilder> create();
};
// ========================================================================== //

@ -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);
}
}

@ -42,14 +42,77 @@
#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", );
cv::ChannelFeatureBuilder::~ChannelFeatureBuilder() {}
void cv::IntegralChannelBuilder::read(const FileNode& fn)
cv::Ptr<cv::ChannelFeatureBuilder> cv::ChannelFeatureBuilder::create()
{
Algorithm::read(fn);
cv::Ptr<cv::ChannelFeatureBuilder> builder(new ICF());
return builder;
}

@ -169,37 +169,30 @@ struct Level
return (sarea == 0.0f)? threshold : (threshold * scaling[idx] * sarea);
}
};
struct ChannelStorage
{
std::vector<cv::Mat> hog;
cv::Mat hog;
int shrinkage;
int offset;
int step;
int model_height;
cv::Ptr<cv::ChannelFeatureBuilder> builder;
enum {HOG_BINS = 6, HOG_LUV_BINS = 10};
ChannelStorage(const cv::Mat& colored, int shr) : shrinkage(shr)
{
hog.clear();
hog.reserve(10);
cv::Channels ints(shr);
// convert to gray
cv::Mat grey;
cv::cvtColor(colored, grey, CV_BGR2GRAY);
builder = cv::ChannelFeatureBuilder::create();
(*builder)(colored, hog);
ints.appendHogBins(grey, hog, 6);
ints.appendLuvBins(colored, hog);
step = hog[0].cols;
step = hog.step1();
model_height = colored.rows / shrinkage;
}
float get(const int channel, const cv::Rect& area) const
{
// CV_Assert(channel < HOG_LUV_BINS);
const cv::Mat& m = hog[channel];
int *ptr = ((int*)(m.data)) + offset;
const int *ptr = hog.ptr<const int>(0) + model_height * channel * step + offset;
int a = ptr[area.y * step + area.x];
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

@ -51,13 +51,11 @@ CV_INIT_ALGORITHM(SoftCascadeDetector, "SoftCascade.SoftCascadeDetector",
obj.info()->addParam(obj, "scales", obj.scales);
obj.info()->addParam(obj, "rejCriteria", obj.rejCriteria));
CV_INIT_ALGORITHM(IntegralChannelBuilder, "SoftCascade.IntegralChannelBuilder", );
bool initModule_softcascade(void)
{
Ptr<Algorithm> sc1 = createSoftCascadeDetector();
Ptr<Algorithm> sc2 = createIntegralChannelBuilder();
return (sc1->info() != 0) && (sc2->info() != 0);
return (sc1->info() != 0);
}
}

@ -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());
}
Loading…
Cancel
Save