Moved PlanarObjectDetector to the objdetect module

This commit is contained in:
Ilya Lysenkov 2010-12-27 08:25:31 +00:00
parent 8f0d36b8b6
commit dc9e5eda19
8 changed files with 279 additions and 224 deletions

View File

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

View File

@ -577,54 +577,6 @@ protected:
}; };
class CV_EXPORTS PlanarObjectDetector
{
public:
PlanarObjectDetector();
PlanarObjectDetector(const FileNode& node);
PlanarObjectDetector(const vector<Mat>& 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<Mat>& 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<Mat>& pyr, const vector<KeyPoint>& 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<KeyPoint> 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<Point2f>& corners) const;
bool operator()(const vector<Mat>& pyr, const vector<KeyPoint>& keypoints,
CV_OUT Mat& H, CV_OUT vector<Point2f>& corners,
CV_OUT vector<int>* pairs=0) const;
protected:
bool verbose;
Rect modelROI;
vector<KeyPoint> modelPoints;
LDetector ldetector;
FernClassifier fernClassifier;
};
/****************************************************************************************\ /****************************************************************************************\
* Calonder Classifier * * Calonder Classifier *
\****************************************************************************************/ \****************************************************************************************/

View File

@ -41,7 +41,6 @@
//M*/ //M*/
#include "precomp.hpp" #include "precomp.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include <stdio.h> #include <stdio.h>
namespace cv namespace cv
@ -1213,176 +1212,4 @@ void FernClassifier::setVerbose(bool _verbose)
verbose = _verbose; verbose = _verbose;
} }
////////////////////////////////////// Planar Object Detector ////////////////////////////////////
PlanarObjectDetector::PlanarObjectDetector()
{
}
PlanarObjectDetector::PlanarObjectDetector(const FileNode& node)
{
read(node);
}
PlanarObjectDetector::PlanarObjectDetector(const vector<Mat>& 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<KeyPoint> PlanarObjectDetector::getModelPoints() const
{
return modelPoints;
}
void PlanarObjectDetector::train(const vector<Mat>& 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<Mat>& pyr, const vector<KeyPoint>& 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<Point2f>& corners) const
{
vector<Mat> pyr;
buildPyramid(image, pyr, ldetector.nOctaves - 1);
vector<KeyPoint> keypoints;
ldetector(pyr, keypoints);
return (*this)(pyr, keypoints, H, corners);
}
bool PlanarObjectDetector::operator()(const vector<Mat>& pyr, const vector<KeyPoint>& keypoints,
Mat& matH, vector<Point2f>& corners, vector<int>* pairs) const
{
int i, j, m = (int)modelPoints.size(), n = (int)keypoints.size();
vector<int> bestMatches(m, -1);
vector<float> maxLogProb(m, -FLT_MAX);
vector<float> signature;
vector<Point2f> 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<uchar> mask;
matH = findHomography(Mat(fromPt), Mat(toPt), mask, RANSAC, 10);
if( matH.data )
{
const Mat_<double>& 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;
}
} }

View File

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

View File

@ -44,6 +44,7 @@
#define __OPENCV_OBJDETECT_HPP__ #define __OPENCV_OBJDETECT_HPP__
#include "opencv2/core/core.hpp" #include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -467,7 +468,58 @@ public:
CV_PROP int nlevels; CV_PROP int nlevels;
}; };
/****************************************************************************************\
* Planar Object Detection *
\****************************************************************************************/
class CV_EXPORTS PlanarObjectDetector
{
public:
PlanarObjectDetector();
PlanarObjectDetector(const FileNode& node);
PlanarObjectDetector(const vector<Mat>& 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<Mat>& 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<Mat>& pyr, const vector<KeyPoint>& 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<KeyPoint> 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<Point2f>& corners) const;
bool operator()(const vector<Mat>& pyr, const vector<KeyPoint>& keypoints,
CV_OUT Mat& H, CV_OUT vector<Point2f>& corners,
CV_OUT vector<int>* pairs=0) const;
protected:
bool verbose;
Rect modelROI;
vector<KeyPoint> modelPoints;
LDetector ldetector;
FernClassifier fernClassifier;
};
} }
#endif #endif

View File

@ -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 <stdio.h>
namespace cv
{
////////////////////////////////////// Planar Object Detector ////////////////////////////////////
PlanarObjectDetector::PlanarObjectDetector()
{
}
PlanarObjectDetector::PlanarObjectDetector(const FileNode& node)
{
read(node);
}
PlanarObjectDetector::PlanarObjectDetector(const vector<Mat>& 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<KeyPoint> PlanarObjectDetector::getModelPoints() const
{
return modelPoints;
}
void PlanarObjectDetector::train(const vector<Mat>& 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<Mat>& pyr, const vector<KeyPoint>& 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<Point2f>& corners) const
{
vector<Mat> pyr;
buildPyramid(image, pyr, ldetector.nOctaves - 1);
vector<KeyPoint> keypoints;
ldetector(pyr, keypoints);
return (*this)(pyr, keypoints, H, corners);
}
bool PlanarObjectDetector::operator()(const vector<Mat>& pyr, const vector<KeyPoint>& keypoints,
Mat& matH, vector<Point2f>& corners, vector<int>* pairs) const
{
int i, j, m = (int)modelPoints.size(), n = (int)keypoints.size();
vector<int> bestMatches(m, -1);
vector<float> maxLogProb(m, -FLT_MAX);
vector<float> signature;
vector<Point2f> 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<uchar> mask;
matH = findHomography(Mat(fromPt), Mat(toPt), mask, RANSAC, 10);
if( matH.data )
{
const Mat_<double>& 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;
}
}

View File

@ -57,5 +57,7 @@
#include "opencv2/core/core_c.h" #include "opencv2/core/core_c.h"
#include "opencv2/highgui/highgui.hpp" #include "opencv2/highgui/highgui.hpp"
#include "opencv2/core/internal.hpp" #include "opencv2/core/internal.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#endif #endif

View File

@ -2,6 +2,7 @@
#include "opencv2/core/core.hpp" #include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp" #include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/features2d/features2d.hpp" #include "opencv2/features2d/features2d.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include <algorithm> #include <algorithm>
#include <iostream> #include <iostream>