From f3227c3f1ae69455d16de04bc0cc6e463284fdb8 Mon Sep 17 00:00:00 2001 From: "marina.kolpakova" Date: Tue, 29 Jan 2013 16:55:01 +0400 Subject: [PATCH] merged ICFPreprocessor and Channels -> ChannelFeatureBuilder --- apps/sft/fpool.cpp | 3 +- apps/sft/include/sft/fpool.hpp | 2 +- modules/python/CMakeLists.txt | 2 +- modules/python/src2/cv2.cpp | 3 + .../include/opencv2/softcascade/softcascade.hpp | 48 +----- modules/softcascade/src/icf.cpp | 170 --------------------- .../softcascade/src/integral_channel_builder.cpp | 73 ++++++++- modules/softcascade/src/softcascade.cpp | 27 ++-- modules/softcascade/src/softcascade_init.cpp | 4 +- modules/softcascade/test/test_channel_features.cpp | 60 ++++++++ 10 files changed, 151 insertions(+), 241 deletions(-) delete mode 100644 modules/softcascade/src/icf.cpp create mode 100644 modules/softcascade/test/test_channel_features.cpp diff --git a/apps/sft/fpool.cpp b/apps/sft/fpool.cpp index c241a75..1bfde2c 100644 --- a/apps/sft/fpool.cpp +++ b/apps/sft/fpool.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 diff --git a/apps/sft/include/sft/fpool.hpp b/apps/sft/include/sft/fpool.hpp index ba95b6a..d531a76 100644 --- a/apps/sft/include/sft/fpool.hpp +++ b/apps/sft/include/sft/fpool.hpp @@ -119,7 +119,7 @@ private: static const unsigned int seed = 0; - cv::ICFPreprocessor preprocessor; + cv::Ptr builder; enum { N_CHANNELS = 10 }; }; diff --git a/modules/python/CMakeLists.txt b/modules/python/CMakeLists.txt index 9db2c8a..4d07221 100644 --- a/modules/python/CMakeLists.txt +++ b/modules/python/CMakeLists.txt @@ -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) diff --git a/modules/python/src2/cv2.cpp b/modules/python/src2/cv2.cpp index 1129675..1eed747 100644 --- a/modules/python/src2/cv2.cpp +++ b/modules/python/src2/cv2.cpp @@ -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 Ptr_DescriptorExtractor; typedef Ptr Ptr_Feature2D; typedef Ptr Ptr_DescriptorMatcher; +typedef Ptr Ptr_ChannelFeatureBuilder; + typedef SimpleBlobDetector::Params SimpleBlobDetector_Params; typedef cvflann::flann_distance_t cvflann_flann_distance_t; diff --git a/modules/softcascade/include/opencv2/softcascade/softcascade.hpp b/modules/softcascade/include/opencv2/softcascade/softcascade.hpp index 9015770..24455cf 100644 --- a/modules/softcascade/include/opencv2/softcascade/softcascade.hpp +++ b/modules/softcascade/include/opencv2/softcascade/softcascade.hpp @@ -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; - -}; - -// 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& 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& 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 create(); }; // ========================================================================== // diff --git a/modules/softcascade/src/icf.cpp b/modules/softcascade/src/icf.cpp deleted file mode 100644 index b58a384..0000000 --- a/modules/softcascade/src/icf.cpp +++ /dev/null @@ -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(y); - float* ang = angle.ptr(y); - - for (int x = 0; x < w; ++x) - { - channels.ptr(y + (h * (int)ang[x]))[x] = magnitude[x]; - } - } - - cv::Mat luv, shrunk; - cv::cvtColor(frame, luv, CV_BGR2Luv); - - std::vector 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(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& 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 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(y); - float* ang = angle.ptr(y); - - for (int x = 0; x < w; ++x) - { - hist[ (int)ang[x] ].ptr(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& 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 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); - } -} \ No newline at end of file diff --git a/modules/softcascade/src/integral_channel_builder.cpp b/modules/softcascade/src/integral_channel_builder.cpp index f7eb621..3d07df4 100644 --- a/modules/softcascade/src/integral_channel_builder.cpp +++ b/modules/softcascade/src/integral_channel_builder.cpp @@ -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(y); + float* ang = angle.ptr(y); + + for (int x = 0; x < w; ++x) + { + channels.ptr(y + (h * (int)ang[x]))[x] = magnitude[x]; + } + } + + cv::Mat luv, shrunk; + cv::cvtColor(frame, luv, CV_BGR2Luv); + + std::vector 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(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::create() { - Algorithm::read(fn); + cv::Ptr builder(new ICF()); + return builder; } \ No newline at end of file diff --git a/modules/softcascade/src/softcascade.cpp b/modules/softcascade/src/softcascade.cpp index 3755965..46811d5 100644 --- a/modules/softcascade/src/softcascade.cpp +++ b/modules/softcascade/src/softcascade.cpp @@ -169,37 +169,30 @@ struct Level return (sarea == 0.0f)? threshold : (threshold * scaling[idx] * sarea); } }; - struct ChannelStorage { - std::vector hog; + cv::Mat hog; int shrinkage; int offset; int step; + int model_height; + + cv::Ptr 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(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& objects) const diff --git a/modules/softcascade/src/softcascade_init.cpp b/modules/softcascade/src/softcascade_init.cpp index e31abbc..f9606c1 100644 --- a/modules/softcascade/src/softcascade_init.cpp +++ b/modules/softcascade/src/softcascade_init.cpp @@ -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 sc1 = createSoftCascadeDetector(); - Ptr sc2 = createIntegralChannelBuilder(); - return (sc1->info() != 0) && (sc2->info() != 0); + return (sc1->info() != 0); } } \ No newline at end of file diff --git a/modules/softcascade/test/test_channel_features.cpp b/modules/softcascade/test/test_channel_features.cpp new file mode 100644 index 0000000..65249b7 --- /dev/null +++ b/modules/softcascade/test/test_channel_features.cpp @@ -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 builder = cv::ChannelFeatureBuilder::create(); + ASSERT_TRUE(builder->info() != 0); +} + +TEST(ChannelFeatureBuilderTest, compute) +{ + cv::Ptr 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()); +} -- 2.7.4