diff --git a/modules/features2d/CMakeLists.txt b/modules/features2d/CMakeLists.txt index ebfd436ad4..8065e65685 100644 --- a/modules/features2d/CMakeLists.txt +++ b/modules/features2d/CMakeLists.txt @@ -1,2 +1,2 @@ -define_opencv_module(features2d opencv_core opencv_imgproc opencv_calib3d opencv_highgui opencv_flann) +define_opencv_module(features2d opencv_core opencv_imgproc opencv_highgui opencv_flann) diff --git a/modules/features2d/include/opencv2/features2d/features2d.hpp b/modules/features2d/include/opencv2/features2d/features2d.hpp index c246335bd3..ee83f0afaf 100644 --- a/modules/features2d/include/opencv2/features2d/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d/features2d.hpp @@ -577,54 +577,6 @@ protected: }; -class CV_EXPORTS PlanarObjectDetector -{ -public: - PlanarObjectDetector(); - PlanarObjectDetector(const FileNode& node); - PlanarObjectDetector(const vector& pyr, int _npoints=300, - int _patchSize=FernClassifier::PATCH_SIZE, - int _nstructs=FernClassifier::DEFAULT_STRUCTS, - int _structSize=FernClassifier::DEFAULT_STRUCT_SIZE, - int _nviews=FernClassifier::DEFAULT_VIEWS, - const LDetector& detector=LDetector(), - const PatchGenerator& patchGenerator=PatchGenerator()); - virtual ~PlanarObjectDetector(); - virtual void train(const vector& pyr, int _npoints=300, - int _patchSize=FernClassifier::PATCH_SIZE, - int _nstructs=FernClassifier::DEFAULT_STRUCTS, - int _structSize=FernClassifier::DEFAULT_STRUCT_SIZE, - int _nviews=FernClassifier::DEFAULT_VIEWS, - const LDetector& detector=LDetector(), - const PatchGenerator& patchGenerator=PatchGenerator()); - virtual void train(const vector& pyr, const vector& keypoints, - int _patchSize=FernClassifier::PATCH_SIZE, - int _nstructs=FernClassifier::DEFAULT_STRUCTS, - int _structSize=FernClassifier::DEFAULT_STRUCT_SIZE, - int _nviews=FernClassifier::DEFAULT_VIEWS, - const LDetector& detector=LDetector(), - const PatchGenerator& patchGenerator=PatchGenerator()); - Rect getModelROI() const; - vector getModelPoints() const; - const LDetector& getDetector() const; - const FernClassifier& getClassifier() const; - void setVerbose(bool verbose); - - void read(const FileNode& node); - void write(FileStorage& fs, const String& name=String()) const; - bool operator()(const Mat& image, CV_OUT Mat& H, CV_OUT vector& corners) const; - bool operator()(const vector& pyr, const vector& keypoints, - CV_OUT Mat& H, CV_OUT vector& corners, - CV_OUT vector* pairs=0) const; - -protected: - bool verbose; - Rect modelROI; - vector modelPoints; - LDetector ldetector; - FernClassifier fernClassifier; -}; - /****************************************************************************************\ * Calonder Classifier * \****************************************************************************************/ diff --git a/modules/features2d/src/planardetect.cpp b/modules/features2d/src/planardetect.cpp index 0d8963a3ce..767407e66d 100644 --- a/modules/features2d/src/planardetect.cpp +++ b/modules/features2d/src/planardetect.cpp @@ -41,7 +41,6 @@ //M*/ #include "precomp.hpp" -#include "opencv2/calib3d/calib3d.hpp" #include namespace cv @@ -1213,176 +1212,4 @@ void FernClassifier::setVerbose(bool _verbose) verbose = _verbose; } -////////////////////////////////////// Planar Object Detector //////////////////////////////////// - -PlanarObjectDetector::PlanarObjectDetector() -{ -} - -PlanarObjectDetector::PlanarObjectDetector(const FileNode& node) -{ - read(node); -} - -PlanarObjectDetector::PlanarObjectDetector(const vector& pyr, int npoints, - int patchSize, int nstructs, int structSize, - int nviews, const LDetector& detector, - const PatchGenerator& patchGenerator) -{ - train(pyr, npoints, patchSize, nstructs, - structSize, nviews, detector, patchGenerator); -} - -PlanarObjectDetector::~PlanarObjectDetector() -{ -} - -vector PlanarObjectDetector::getModelPoints() const -{ - return modelPoints; -} - -void PlanarObjectDetector::train(const vector& pyr, int npoints, - int patchSize, int nstructs, int structSize, - int nviews, const LDetector& detector, - const PatchGenerator& patchGenerator) -{ - modelROI = Rect(0, 0, pyr[0].cols, pyr[0].rows); - ldetector = detector; - ldetector.setVerbose(verbose); - ldetector.getMostStable2D(pyr[0], modelPoints, npoints, patchGenerator); - - npoints = (int)modelPoints.size(); - fernClassifier.setVerbose(verbose); - fernClassifier.trainFromSingleView(pyr[0], modelPoints, - patchSize, (int)modelPoints.size(), nstructs, structSize, nviews, - FernClassifier::COMPRESSION_NONE, patchGenerator); -} - -void PlanarObjectDetector::train(const vector& pyr, const vector& keypoints, - int patchSize, int nstructs, int structSize, - int nviews, const LDetector& detector, - const PatchGenerator& patchGenerator) -{ - modelROI = Rect(0, 0, pyr[0].cols, pyr[0].rows); - ldetector = detector; - ldetector.setVerbose(verbose); - modelPoints.resize(keypoints.size()); - std::copy(keypoints.begin(), keypoints.end(), modelPoints.begin()); - - fernClassifier.setVerbose(verbose); - fernClassifier.trainFromSingleView(pyr[0], modelPoints, - patchSize, (int)modelPoints.size(), nstructs, structSize, nviews, - FernClassifier::COMPRESSION_NONE, patchGenerator); -} - -void PlanarObjectDetector::read(const FileNode& node) -{ - FileNodeIterator it = node["model-roi"].begin(), it_end; - it >> modelROI.x >> modelROI.y >> modelROI.width >> modelROI.height; - ldetector.read(node["detector"]); - fernClassifier.read(node["fern-classifier"]); - cv::read(node["model-points"], modelPoints); - CV_Assert(modelPoints.size() == (size_t)fernClassifier.getClassCount()); -} - - -void PlanarObjectDetector::write(FileStorage& fs, const String& objname) const -{ - WriteStructContext ws(fs, objname, CV_NODE_MAP); - - { - WriteStructContext wsroi(fs, "model-roi", CV_NODE_SEQ + CV_NODE_FLOW); - cv::write(fs, modelROI.x); - cv::write(fs, modelROI.y); - cv::write(fs, modelROI.width); - cv::write(fs, modelROI.height); - } - ldetector.write(fs, "detector"); - cv::write(fs, "model-points", modelPoints); - fernClassifier.write(fs, "fern-classifier"); -} - - -bool PlanarObjectDetector::operator()(const Mat& image, Mat& H, vector& corners) const -{ - vector pyr; - buildPyramid(image, pyr, ldetector.nOctaves - 1); - vector keypoints; - ldetector(pyr, keypoints); - - return (*this)(pyr, keypoints, H, corners); -} - -bool PlanarObjectDetector::operator()(const vector& pyr, const vector& keypoints, - Mat& matH, vector& corners, vector* pairs) const -{ - int i, j, m = (int)modelPoints.size(), n = (int)keypoints.size(); - vector bestMatches(m, -1); - vector maxLogProb(m, -FLT_MAX); - vector signature; - vector fromPt, toPt; - - for( i = 0; i < n; i++ ) - { - KeyPoint kpt = keypoints[i]; - CV_Assert(0 <= kpt.octave && kpt.octave < (int)pyr.size()); - kpt.pt.x /= (float)(1 << kpt.octave); - kpt.pt.y /= (float)(1 << kpt.octave); - int k = fernClassifier(pyr[kpt.octave], kpt.pt, signature); - if( k >= 0 && (bestMatches[k] < 0 || signature[k] > maxLogProb[k]) ) - { - maxLogProb[k] = signature[k]; - bestMatches[k] = i; - } - } - - if(pairs) - pairs->resize(0); - - for( i = 0; i < m; i++ ) - if( bestMatches[i] >= 0 ) - { - fromPt.push_back(modelPoints[i].pt); - toPt.push_back(keypoints[bestMatches[i]].pt); - } - - if( fromPt.size() < 4 ) - return false; - - vector mask; - matH = findHomography(Mat(fromPt), Mat(toPt), mask, RANSAC, 10); - if( matH.data ) - { - const Mat_& H = matH; - corners.resize(4); - for( i = 0; i < 4; i++ ) - { - Point2f pt((float)(modelROI.x + (i == 0 || i == 3 ? 0 : modelROI.width)), - (float)(modelROI.y + (i <= 1 ? 0 : modelROI.height))); - double w = 1./(H(2,0)*pt.x + H(2,1)*pt.y + H(2,2)); - corners[i] = Point2f((float)((H(0,0)*pt.x + H(0,1)*pt.y + H(0,2))*w), - (float)((H(1,0)*pt.x + H(1,1)*pt.y + H(1,2))*w)); - } - } - - if( pairs ) - { - for( i = j = 0; i < m; i++ ) - if( bestMatches[i] >= 0 && mask[j++] ) - { - pairs->push_back(i); - pairs->push_back(bestMatches[i]); - } - } - - return matH.data != 0; -} - - -void PlanarObjectDetector::setVerbose(bool _verbose) -{ - verbose = _verbose; -} - } diff --git a/modules/objdetect/CMakeLists.txt b/modules/objdetect/CMakeLists.txt index 65f4795fdc..92f47cbd37 100644 --- a/modules/objdetect/CMakeLists.txt +++ b/modules/objdetect/CMakeLists.txt @@ -1 +1 @@ -define_opencv_module(objdetect opencv_core opencv_imgproc opencv_highgui) +define_opencv_module(objdetect opencv_core opencv_imgproc opencv_highgui opencv_features2d opencv_calib3d) diff --git a/modules/objdetect/include/opencv2/objdetect/objdetect.hpp b/modules/objdetect/include/opencv2/objdetect/objdetect.hpp index c836b5b48d..9afd46aca6 100644 --- a/modules/objdetect/include/opencv2/objdetect/objdetect.hpp +++ b/modules/objdetect/include/opencv2/objdetect/objdetect.hpp @@ -44,6 +44,7 @@ #define __OPENCV_OBJDETECT_HPP__ #include "opencv2/core/core.hpp" +#include "opencv2/features2d/features2d.hpp" #ifdef __cplusplus extern "C" { @@ -467,7 +468,58 @@ public: CV_PROP int nlevels; }; - +/****************************************************************************************\ +* Planar Object Detection * +\****************************************************************************************/ + +class CV_EXPORTS PlanarObjectDetector +{ +public: + PlanarObjectDetector(); + PlanarObjectDetector(const FileNode& node); + PlanarObjectDetector(const vector& pyr, int _npoints=300, + int _patchSize=FernClassifier::PATCH_SIZE, + int _nstructs=FernClassifier::DEFAULT_STRUCTS, + int _structSize=FernClassifier::DEFAULT_STRUCT_SIZE, + int _nviews=FernClassifier::DEFAULT_VIEWS, + const LDetector& detector=LDetector(), + const PatchGenerator& patchGenerator=PatchGenerator()); + virtual ~PlanarObjectDetector(); + virtual void train(const vector& pyr, int _npoints=300, + int _patchSize=FernClassifier::PATCH_SIZE, + int _nstructs=FernClassifier::DEFAULT_STRUCTS, + int _structSize=FernClassifier::DEFAULT_STRUCT_SIZE, + int _nviews=FernClassifier::DEFAULT_VIEWS, + const LDetector& detector=LDetector(), + const PatchGenerator& patchGenerator=PatchGenerator()); + virtual void train(const vector& pyr, const vector& keypoints, + int _patchSize=FernClassifier::PATCH_SIZE, + int _nstructs=FernClassifier::DEFAULT_STRUCTS, + int _structSize=FernClassifier::DEFAULT_STRUCT_SIZE, + int _nviews=FernClassifier::DEFAULT_VIEWS, + const LDetector& detector=LDetector(), + const PatchGenerator& patchGenerator=PatchGenerator()); + Rect getModelROI() const; + vector getModelPoints() const; + const LDetector& getDetector() const; + const FernClassifier& getClassifier() const; + void setVerbose(bool verbose); + + void read(const FileNode& node); + void write(FileStorage& fs, const String& name=String()) const; + bool operator()(const Mat& image, CV_OUT Mat& H, CV_OUT vector& corners) const; + bool operator()(const vector& pyr, const vector& keypoints, + CV_OUT Mat& H, CV_OUT vector& corners, + CV_OUT vector* pairs=0) const; + +protected: + bool verbose; + Rect modelROI; + vector modelPoints; + LDetector ldetector; + FernClassifier fernClassifier; +}; + } #endif diff --git a/modules/objdetect/src/planardetect.cpp b/modules/objdetect/src/planardetect.cpp new file mode 100644 index 0000000000..dbc7a4add4 --- /dev/null +++ b/modules/objdetect/src/planardetect.cpp @@ -0,0 +1,221 @@ +/*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) 2009, 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" +#include + +namespace cv +{ + +////////////////////////////////////// Planar Object Detector //////////////////////////////////// + +PlanarObjectDetector::PlanarObjectDetector() +{ +} + +PlanarObjectDetector::PlanarObjectDetector(const FileNode& node) +{ + read(node); +} + +PlanarObjectDetector::PlanarObjectDetector(const vector& pyr, int npoints, + int patchSize, int nstructs, int structSize, + int nviews, const LDetector& detector, + const PatchGenerator& patchGenerator) +{ + train(pyr, npoints, patchSize, nstructs, + structSize, nviews, detector, patchGenerator); +} + +PlanarObjectDetector::~PlanarObjectDetector() +{ +} + +vector PlanarObjectDetector::getModelPoints() const +{ + return modelPoints; +} + +void PlanarObjectDetector::train(const vector& pyr, int npoints, + int patchSize, int nstructs, int structSize, + int nviews, const LDetector& detector, + const PatchGenerator& patchGenerator) +{ + modelROI = Rect(0, 0, pyr[0].cols, pyr[0].rows); + ldetector = detector; + ldetector.setVerbose(verbose); + ldetector.getMostStable2D(pyr[0], modelPoints, npoints, patchGenerator); + + npoints = (int)modelPoints.size(); + fernClassifier.setVerbose(verbose); + fernClassifier.trainFromSingleView(pyr[0], modelPoints, + patchSize, (int)modelPoints.size(), nstructs, structSize, nviews, + FernClassifier::COMPRESSION_NONE, patchGenerator); +} + +void PlanarObjectDetector::train(const vector& pyr, const vector& keypoints, + int patchSize, int nstructs, int structSize, + int nviews, const LDetector& detector, + const PatchGenerator& patchGenerator) +{ + modelROI = Rect(0, 0, pyr[0].cols, pyr[0].rows); + ldetector = detector; + ldetector.setVerbose(verbose); + modelPoints.resize(keypoints.size()); + std::copy(keypoints.begin(), keypoints.end(), modelPoints.begin()); + + fernClassifier.setVerbose(verbose); + fernClassifier.trainFromSingleView(pyr[0], modelPoints, + patchSize, (int)modelPoints.size(), nstructs, structSize, nviews, + FernClassifier::COMPRESSION_NONE, patchGenerator); +} + +void PlanarObjectDetector::read(const FileNode& node) +{ + FileNodeIterator it = node["model-roi"].begin(), it_end; + it >> modelROI.x >> modelROI.y >> modelROI.width >> modelROI.height; + ldetector.read(node["detector"]); + fernClassifier.read(node["fern-classifier"]); + cv::read(node["model-points"], modelPoints); + CV_Assert(modelPoints.size() == (size_t)fernClassifier.getClassCount()); +} + + +void PlanarObjectDetector::write(FileStorage& fs, const String& objname) const +{ + WriteStructContext ws(fs, objname, CV_NODE_MAP); + + { + WriteStructContext wsroi(fs, "model-roi", CV_NODE_SEQ + CV_NODE_FLOW); + cv::write(fs, modelROI.x); + cv::write(fs, modelROI.y); + cv::write(fs, modelROI.width); + cv::write(fs, modelROI.height); + } + ldetector.write(fs, "detector"); + cv::write(fs, "model-points", modelPoints); + fernClassifier.write(fs, "fern-classifier"); +} + + +bool PlanarObjectDetector::operator()(const Mat& image, Mat& H, vector& corners) const +{ + vector pyr; + buildPyramid(image, pyr, ldetector.nOctaves - 1); + vector keypoints; + ldetector(pyr, keypoints); + + return (*this)(pyr, keypoints, H, corners); +} + +bool PlanarObjectDetector::operator()(const vector& pyr, const vector& keypoints, + Mat& matH, vector& corners, vector* pairs) const +{ + int i, j, m = (int)modelPoints.size(), n = (int)keypoints.size(); + vector bestMatches(m, -1); + vector maxLogProb(m, -FLT_MAX); + vector signature; + vector fromPt, toPt; + + for( i = 0; i < n; i++ ) + { + KeyPoint kpt = keypoints[i]; + CV_Assert(0 <= kpt.octave && kpt.octave < (int)pyr.size()); + kpt.pt.x /= (float)(1 << kpt.octave); + kpt.pt.y /= (float)(1 << kpt.octave); + int k = fernClassifier(pyr[kpt.octave], kpt.pt, signature); + if( k >= 0 && (bestMatches[k] < 0 || signature[k] > maxLogProb[k]) ) + { + maxLogProb[k] = signature[k]; + bestMatches[k] = i; + } + } + + if(pairs) + pairs->resize(0); + + for( i = 0; i < m; i++ ) + if( bestMatches[i] >= 0 ) + { + fromPt.push_back(modelPoints[i].pt); + toPt.push_back(keypoints[bestMatches[i]].pt); + } + + if( fromPt.size() < 4 ) + return false; + + vector mask; + matH = findHomography(Mat(fromPt), Mat(toPt), mask, RANSAC, 10); + if( matH.data ) + { + const Mat_& H = matH; + corners.resize(4); + for( i = 0; i < 4; i++ ) + { + Point2f pt((float)(modelROI.x + (i == 0 || i == 3 ? 0 : modelROI.width)), + (float)(modelROI.y + (i <= 1 ? 0 : modelROI.height))); + double w = 1./(H(2,0)*pt.x + H(2,1)*pt.y + H(2,2)); + corners[i] = Point2f((float)((H(0,0)*pt.x + H(0,1)*pt.y + H(0,2))*w), + (float)((H(1,0)*pt.x + H(1,1)*pt.y + H(1,2))*w)); + } + } + + if( pairs ) + { + for( i = j = 0; i < m; i++ ) + if( bestMatches[i] >= 0 && mask[j++] ) + { + pairs->push_back(i); + pairs->push_back(bestMatches[i]); + } + } + + return matH.data != 0; +} + + +void PlanarObjectDetector::setVerbose(bool _verbose) +{ + verbose = _verbose; +} + +} diff --git a/modules/objdetect/src/precomp.hpp b/modules/objdetect/src/precomp.hpp index c6e28f40db..f3d70639d9 100644 --- a/modules/objdetect/src/precomp.hpp +++ b/modules/objdetect/src/precomp.hpp @@ -57,5 +57,7 @@ #include "opencv2/core/core_c.h" #include "opencv2/highgui/highgui.hpp" #include "opencv2/core/internal.hpp" +#include "opencv2/features2d/features2d.hpp" +#include "opencv2/calib3d/calib3d.hpp" #endif diff --git a/samples/c/find_obj_ferns.cpp b/samples/c/find_obj_ferns.cpp index 287fbba4d7..ae20520b87 100644 --- a/samples/c/find_obj_ferns.cpp +++ b/samples/c/find_obj_ferns.cpp @@ -2,6 +2,7 @@ #include "opencv2/core/core.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/features2d/features2d.hpp" +#include "opencv2/objdetect/objdetect.hpp" #include #include