diff --git a/modules/latentsvm/CMakeLists.txt b/modules/latentsvm/CMakeLists.txt new file mode 100644 index 00000000000..99f4c952c00 --- /dev/null +++ b/modules/latentsvm/CMakeLists.txt @@ -0,0 +1,2 @@ +set(the_description "Object Detection") +ocv_define_module(latentsvm opencv_core opencv_imgproc opencv_objdetect opencv_ts OPTIONAL opencv_highgui) diff --git a/modules/latentsvm/doc/latent_svm_cascade.rst b/modules/latentsvm/doc/latent_svm_cascade.rst new file mode 100644 index 00000000000..3d945b8bbc2 --- /dev/null +++ b/modules/latentsvm/doc/latent_svm_cascade.rst @@ -0,0 +1,113 @@ +Latent SVM +=============================================================== + +Discriminatively Trained Part Based Models for Object Detection +--------------------------------------------------------------- + +The object detector described below has been initially proposed by +P.F. Felzenszwalb in [Felzenszwalb2010a]_. It is based on a +Dalal-Triggs detector that uses a single filter on histogram of +oriented gradients (HOG) features to represent an object category. +This detector uses a sliding window approach, where a filter is +applied at all positions and scales of an image. The first +innovation is enriching the Dalal-Triggs model using a +star-structured part-based model defined by a "root" filter +(analogous to the Dalal-Triggs filter) plus a set of parts filters +and associated deformation models. The score of one of star models +at a particular position and scale within an image is the score of +the root filter at the given location plus the sum over parts of the +maximum, over placements of that part, of the part filter score on +its location minus a deformation cost easuring the deviation of the +part from its ideal location relative to the root. Both root and +part filter scores are defined by the dot product between a filter +(a set of weights) and a subwindow of a feature pyramid computed +from the input image. Another improvement is a representation of the +class of models by a mixture of star models. The score of a mixture +model at a particular position and scale is the maximum over +components, of the score of that component model at the given +location. + +The detector was dramatically speeded-up with cascade algorithm +proposed by P.F. Felzenszwalb in [Felzenszwalb2010b]_. The algorithm +prunes partial hypotheses using thresholds on their scores.The basic +idea of the algorithm is to use a hierarchy of models defined by an +ordering of the original model's parts. For a model with (n+1) +parts, including the root, a sequence of (n+1) models is obtained. +The i-th model in this sequence is defined by the first i parts from +the original model. Using this hierarchy, low scoring hypotheses can be +pruned after looking at the best configuration of a subset of the parts. +Hypotheses that score high under a weak model are evaluated further using +a richer model. + +In OpenCV there is an C++ implementation of Latent SVM. + +.. highlight:: cpp + +LSVMDetector +----------------- +.. ocv:class:: LSVMDetector + +This is a C++ abstract class, it provides external user API to work with Latent SVM. + +LSVMDetector::ObjectDetection +---------------------------------- +.. ocv:struct:: LSVMDetector::ObjectDetection + + Structure contains the detection information. + + .. ocv:member:: Rect rect + + bounding box for a detected object + + .. ocv:member:: float score + + confidence level + + .. ocv:member:: int classID + + class (model or detector) ID that detect an object + +LSVMDetector::~LSVMDetector +------------------------------------- +Destructor. + +.. ocv:function:: LSVMDetector::~LSVMDetector() + +LSVMDetector::create +----------------------- +Load the trained models from given ``.xml`` files and return ``cv::Ptr``. + +.. ocv:function:: static cv::Ptr LSVMDetector::create( const vector& filenames, const vector& classNames=vector() ) + + :param filenames: A set of filenames storing the trained detectors (models). Each file contains one model. See examples of such files here /opencv_extra/testdata/cv/LSVMDetector/models_VOC2007/. + + :param classNames: A set of trained models names. If it's empty then the name of each model will be constructed from the name of file containing the model. E.g. the model stored in "/home/user/cat.xml" will get the name "cat". + +LSVMDetector::detect +------------------------- +Find rectangular regions in the given image that are likely to contain objects of loaded classes (models) +and corresponding confidence levels. + +.. ocv:function:: void LSVMDetector::detect( const Mat& image, vector& objectDetections, float overlapThreshold=0.5f, int numThreads=-1 ) + + :param image: An image. + :param objectDetections: The detections: rectangulars, scores and class IDs. + :param overlapThreshold: Threshold for the non-maximum suppression algorithm. + :param numThreads: Number of threads used in parallel version of the algorithm. + +LSVMDetector::getClassNames +-------------------------------- +Return the class (model) names that were passed in constructor or method ``load`` or extracted from models filenames in those methods. + +.. ocv:function:: const vector& LSVMDetector::getClassNames() const + +LSVMDetector::getClassCount +-------------------------------- +Return a count of loaded models (classes). + +.. ocv:function:: size_t LSVMDetector::getClassCount() const + + +.. [Felzenszwalb2010a] Felzenszwalb, P. F. and Girshick, R. B. and McAllester, D. and Ramanan, D. *Object Detection with Discriminatively Trained Part Based Models*. PAMI, vol. 32, no. 9, pp. 1627-1645, September 2010 +.. [Felzenszwalb2010b] Felzenszwalb, P. F. and Girshick, R. B. and McAllester, D. *Cascade Object Detection with Deformable Part Models*. CVPR 2010, pp. 2241-2248 + diff --git a/modules/latentsvm/include/opencv2/latentsvm.hpp b/modules/latentsvm/include/opencv2/latentsvm.hpp new file mode 100644 index 00000000000..4f80ea7ce89 --- /dev/null +++ b/modules/latentsvm/include/opencv2/latentsvm.hpp @@ -0,0 +1,93 @@ +/*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) 2010-2013, University of Nizhny Novgorod, 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. +// +// SVM implementation authors: +// Evgeniy Kozinov - evgeniy.kozinov@gmail.com +// Valentina Kustikova - valentina.kustikova@gmail.com +// Nikolai Zolotykh - Nikolai.Zolotykh@gmail.com +// Iosif Meyerov - meerov@vmk.unn.ru +// Alexey Polovinkin - polovinkin.alexey@gmail.com +// +//M*/ + +#ifndef __OPENCV_LATENTSVM_HPP__ +#define __OPENCV_LATENTSVM_HPP__ + +#include "opencv2/core.hpp" + +#include +#include +#include + +namespace cv +{ + +namespace lsvm +{ + +class CV_EXPORTS_W LSVMDetector +{ +public: + + struct CV_EXPORTS_W ObjectDetection + { + ObjectDetection(); + ObjectDetection( const Rect& rect, float score, int classID=-1 ); + Rect rect; + float score; + int classID; + }; + + virtual bool isEmpty() const = 0; + virtual void detect(cv::Mat const &image, CV_OUT std::vector &objects, + float overlapThreshold=0.5f ) = 0; + + virtual std::vector const& getClassNames() const = 0; + virtual size_t getClassCount() const = 0; + + static cv::Ptr create(std::vector const &filenames, + std::vector const &classNames = std::vector()); + + virtual ~LSVMDetector(){} +}; + +} // namespace lsvm +} // namespace cv + +#endif diff --git a/modules/latentsvm/perf/perf_cascadeclassifier.cpp b/modules/latentsvm/perf/perf_cascadeclassifier.cpp new file mode 100644 index 00000000000..2823302c77d --- /dev/null +++ b/modules/latentsvm/perf/perf_cascadeclassifier.cpp @@ -0,0 +1,50 @@ +#include "perf_precomp.hpp" +#include + +using namespace std; +using namespace cv; +using namespace perf; +using std::tr1::make_tuple; +using std::tr1::get; + +typedef std::tr1::tuple ImageName_MinSize_t; +typedef perf::TestBaseWithParam ImageName_MinSize; + +PERF_TEST_P(ImageName_MinSize, CascadeClassifierLBPFrontalFace, + testing::Combine(testing::Values( std::string("cv/shared/lena.png"), + std::string("cv/shared/1_itseez-0000289.png"), + std::string("cv/shared/1_itseez-0000492.png"), + std::string("cv/shared/1_itseez-0000573.png")), + testing::Values(24, 30, 40, 50, 60, 70, 80, 90) + ) + ) +{ + const string filename = get<0>(GetParam()); + int min_size = get<1>(GetParam()); + Size minSize(min_size, min_size); + + CascadeClassifier cc(getDataPath("cv/cascadeandhog/cascades/lbpcascade_frontalface.xml")); + if (cc.empty()) + FAIL() << "Can't load cascade file"; + + Mat img = imread(getDataPath(filename), 0); + if (img.empty()) + FAIL() << "Can't load source image"; + + vector faces; + + equalizeHist(img, img); + declare.in(img); + + while(next()) + { + faces.clear(); + + startTimer(); + cc.detectMultiScale(img, faces, 1.1, 3, 0, minSize); + stopTimer(); + } + + std::sort(faces.begin(), faces.end(), comparators::RectLess()); + SANITY_CHECK(faces, 3.001 * faces.size()); +} \ No newline at end of file diff --git a/modules/latentsvm/perf/perf_main.cpp b/modules/latentsvm/perf/perf_main.cpp new file mode 100644 index 00000000000..69b8ecac5b8 --- /dev/null +++ b/modules/latentsvm/perf/perf_main.cpp @@ -0,0 +1,3 @@ +#include "perf_precomp.hpp" + +CV_PERF_TEST_MAIN(objdetect) diff --git a/modules/latentsvm/perf/perf_precomp.cpp b/modules/latentsvm/perf/perf_precomp.cpp new file mode 100644 index 00000000000..8552ac3d428 --- /dev/null +++ b/modules/latentsvm/perf/perf_precomp.cpp @@ -0,0 +1 @@ +#include "perf_precomp.hpp" diff --git a/modules/latentsvm/perf/perf_precomp.hpp b/modules/latentsvm/perf/perf_precomp.hpp new file mode 100644 index 00000000000..29427f7c767 --- /dev/null +++ b/modules/latentsvm/perf/perf_precomp.hpp @@ -0,0 +1,20 @@ +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wmissing-declarations" +# if defined __clang__ || defined __APPLE__ +# pragma GCC diagnostic ignored "-Wmissing-prototypes" +# pragma GCC diagnostic ignored "-Wextra" +# endif +#endif + +#ifndef __OPENCV_PERF_PRECOMP_HPP__ +#define __OPENCV_PERF_PRECOMP_HPP__ + +#include "opencv2/ts.hpp" +#include "opencv2/objdetect.hpp" +#include "opencv2/highgui.hpp" + +#ifdef GTEST_CREATE_SHARED_LIBRARY +#error no modules except ts should have GTEST_CREATE_SHARED_LIBRARY defined +#endif + +#endif diff --git a/modules/latentsvm/src/_lsvmc_error.h b/modules/latentsvm/src/_lsvmc_error.h new file mode 100644 index 00000000000..489d4cdd963 --- /dev/null +++ b/modules/latentsvm/src/_lsvmc_error.h @@ -0,0 +1,61 @@ +/*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) 2010-2013, University of Nizhny Novgorod, 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*/ + +#ifndef LSVM_ERROR +#define LSVM_ERROR + +#define LATENT_SVM_OK 0 +#define LATENT_SVM_MEM_NULL 2 +#define DISTANCE_TRANSFORM_OK 1 +#define DISTANCE_TRANSFORM_GET_INTERSECTION_ERROR -1 +#define DISTANCE_TRANSFORM_ERROR -2 +#define DISTANCE_TRANSFORM_EQUAL_POINTS -3 +#define LATENT_SVM_GET_FEATURE_PYRAMID_FAILED -4 +#define LATENT_SVM_SEARCH_OBJECT_FAILED -5 +#define LATENT_SVM_FAILED_SUPERPOSITION -6 +#define FILTER_OUT_OF_BOUNDARIES -7 +#define LATENT_SVM_TBB_SCHEDULE_CREATION_FAILED -8 +#define LATENT_SVM_TBB_NUMTHREADS_NOT_CORRECT -9 +#define FFT_OK 2 +#define FFT_ERROR -10 +#define LSVM_PARSER_FILE_NOT_FOUND -11 + +#endif diff --git a/modules/latentsvm/src/_lsvmc_function.h b/modules/latentsvm/src/_lsvmc_function.h new file mode 100644 index 00000000000..5fa1f2bc785 --- /dev/null +++ b/modules/latentsvm/src/_lsvmc_function.h @@ -0,0 +1,58 @@ +/*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) 2010-2013, University of Nizhny Novgorod, 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*/ + +#ifndef FUNCTION_SC +#define FUNCTION_SC + +#include "_lsvmc_types.h" + +namespace cv +{ +namespace lsvm +{ + +float calcM (int k,int di,int dj, const CvLSVMFeaturePyramidCaskade * H, const CvLSVMFilterObjectCaskade *filter); +float calcM_PCA (int k,int di,int dj, const CvLSVMFeaturePyramidCaskade * H, const CvLSVMFilterObjectCaskade *filter); +float calcM_PCA_cash(int k,int di,int dj, const CvLSVMFeaturePyramidCaskade * H, const CvLSVMFilterObjectCaskade *filter, float * cashM, int * maskM, int step); +float calcFine (const CvLSVMFilterObjectCaskade *filter, int di, int dj); +} +} +#endif \ No newline at end of file diff --git a/modules/latentsvm/src/_lsvmc_latentsvm.h b/modules/latentsvm/src/_lsvmc_latentsvm.h new file mode 100644 index 00000000000..61029567e62 --- /dev/null +++ b/modules/latentsvm/src/_lsvmc_latentsvm.h @@ -0,0 +1,379 @@ +/*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) 2010-2013, University of Nizhny Novgorod, 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*/ + +/*****************************************************************************/ +/* Latent SVM prediction API */ +/*****************************************************************************/ + +#ifndef _LATENTSVM_H_ +#define _LATENTSVM_H_ + +#include +#include "_lsvmc_types.h" +#include "_lsvmc_error.h" +#include "_lsvmc_routine.h" + +namespace cv +{ +namespace lsvm +{ + +////////////////////////////////////////////////////////////// +// Building feature pyramid +// (pyramid constructed both contrast and non-contrast image) +////////////////////////////////////////////////////////////// + +void FeaturePyramid32(CvLSVMFeaturePyramidCaskade* H, int maxX, int maxY); + +/* +// Creation PSA feature pyramid +// +// API +// featurePyramid* createPSA_FeaturePyramid(featurePyramid* H); + +// INPUT +// H - feature pyramid +// OUTPUT +// RESULT +// PSA feature pyramid +*/ +CvLSVMFeaturePyramidCaskade* createPCA_FeaturePyramid(CvLSVMFeaturePyramidCaskade* H, + CvLatentSvmDetectorCaskade* detector, + int maxX, int maxY); + +/* +// Getting feature pyramid +// +// API +// int getFeaturePyramid(IplImage * image, const CvLSVMFilterObjectCaskade **all_F, + const int n_f, + const int lambda, const int k, + const int startX, const int startY, + const int W, const int H, featurePyramid **maps); +// INPUT +// image - image +// lambda - resize scale +// k - size of cells +// startX - X coordinate of the image rectangle to search +// startY - Y coordinate of the image rectangle to search +// W - width of the image rectangle to search +// H - height of the image rectangle to search +// OUTPUT +// maps - feature maps for all levels +// RESULT +// Error status +*/ +int getFeaturePyramid(IplImage * image, CvLSVMFeaturePyramidCaskade **maps); + +/* +// Getting feature map for the selected subimage +// +// API +// int getFeatureMaps(const IplImage * image, const int k, featureMap **map); +// INPUT +// image - selected subimage +// k - size of cells +// OUTPUT +// map - feature map +// RESULT +// Error status +*/ +int getFeatureMaps(const IplImage * image, const int k, CvLSVMFeatureMapCaskade **map); + + +/* +// Feature map Normalization and Truncation +// +// API +// int normalizationAndTruncationFeatureMaps(featureMap *map, const float alfa); +// INPUT +// map - feature map +// alfa - truncation threshold +// OUTPUT +// map - truncated and normalized feature map +// RESULT +// Error status +*/ +int normalizeAndTruncate(CvLSVMFeatureMapCaskade *map, const float alfa); + +/* +// Feature map reduction +// In each cell we reduce dimension of the feature vector +// according to original paper special procedure +// +// API +// int PCAFeatureMaps(featureMap *map) +// INPUT +// map - feature map +// OUTPUT +// map - feature map +// RESULT +// Error status +*/ +int PCAFeatureMaps(CvLSVMFeatureMapCaskade *map); + +////////////////////////////////////////////////////////////// +// search object +////////////////////////////////////////////////////////////// + +/* +// Transformation filter displacement from the block space +// to the space of pixels at the initial image +// +// API +// int convertPoints(int countLevel, int lambda, + int initialImageLevel, + CvPoint *points, int *levels, + CvPoint **partsDisplacement, int kPoints, int n, + int maxXBorder, + int maxYBorder); +// INPUT +// countLevel - the number of levels in the feature pyramid +// lambda - method parameter +// initialImageLevel - level of feature pyramid that contains feature map + for initial image +// points - the set of root filter positions (in the block space) +// levels - the set of levels +// partsDisplacement - displacement of part filters (in the block space) +// kPoints - number of root filter positions +// n - number of part filters +// maxXBorder - the largest root filter size (X-direction) +// maxYBorder - the largest root filter size (Y-direction) +// OUTPUT +// points - the set of root filter positions (in the space of pixels) +// partsDisplacement - displacement of part filters (in the space of pixels) +// RESULT +// Error status +*/ +int convertPoints(int countLevel, int lambda, + int initialImageLevel, + CvPoint *points, int *levels, + CvPoint **partsDisplacement, int kPoints, int n, + int maxXBorder, + int maxYBorder); + +/* +// Elimination boxes that are outside the image boudaries +// +// API +// int clippingBoxes(int width, int height, + CvPoint *points, int kPoints); +// INPUT +// width - image wediht +// height - image heigth +// points - a set of points (coordinates of top left or + bottom right corners) +// kPoints - points number +// OUTPUT +// points - updated points (if coordinates less than zero then + set zero coordinate, if coordinates more than image + size then set coordinates equal image size) +// RESULT +// Error status +*/ +int clippingBoxes(int width, int height, + CvPoint *points, int kPoints); + +/* +// Creation feature pyramid with nullable border +// +// API +// featurePyramid* createFeaturePyramidWithBorder(const IplImage *image, + int maxXBorder, int maxYBorder); + +// INPUT +// image - initial image +// maxXBorder - the largest root filter size (X-direction) +// maxYBorder - the largest root filter size (Y-direction) +// OUTPUT +// RESULT +// Feature pyramid with nullable border +*/ +CvLSVMFeaturePyramidCaskade* createFeaturePyramidWithBorder(IplImage *image, + int maxXBorder, int maxYBorder); + +/* +// Computation root filters displacement and values of score function +// +// API +// int searchObjectThresholdSomeComponents(const featurePyramid *H, + const CvLSVMFilterObjectCaskade **filters, + int kComponents, const int *kPartFilters, + const float *b, float scoreThreshold, + CvPoint **points, CvPoint **oppPoints, + float **score, int *kPoints); +// INPUT +// H - feature pyramid +// filters - filters (root filter then it's part filters, etc.) +// kComponents - root filters number +// kPartFilters - array of part filters number for each component +// b - array of linear terms +// scoreThreshold - score threshold +// OUTPUT +// points - root filters displacement (top left corners) +// oppPoints - root filters displacement (bottom right corners) +// score - array of score values +// kPoints - number of boxes +// RESULT +// Error status +*/ +int searchObjectThresholdSomeComponents(const CvLSVMFeaturePyramidCaskade *H, + const CvLSVMFeaturePyramidCaskade *H_PCA, + const CvLSVMFilterObjectCaskade **filters, + int kComponents, const int *kPartFilters, + const float *b, float scoreThreshold, + CvPoint **points, CvPoint **oppPoints, + float **score, int *kPoints); + +/* +// Compute opposite point for filter box +// +// API +// int getOppositePoint(CvPoint point, + int sizeX, int sizeY, + float step, int degree, + CvPoint *oppositePoint); + +// INPUT +// point - coordinates of filter top left corner + (in the space of pixels) +// (sizeX, sizeY) - filter dimension in the block space +// step - scaling factor +// degree - degree of the scaling factor +// OUTPUT +// oppositePoint - coordinates of filter bottom corner + (in the space of pixels) +// RESULT +// Error status +*/ +int getOppositePoint(CvPoint point, + int sizeX, int sizeY, + float step, int degree, + CvPoint *oppositePoint); + +/* +// Drawing root filter boxes +// +// API +// int showRootFilterBoxes(const IplImage *image, + const CvLSVMFilterObjectCaskade *filter, + CvPoint *points, int *levels, int kPoints, + CvScalar color, int thickness, + int line_type, int shift); +// INPUT +// image - initial image +// filter - root filter object +// points - a set of points +// levels - levels of feature pyramid +// kPoints - number of points +// color - line color for each box +// thickness - line thickness +// line_type - line type +// shift - shift +// OUTPUT +// window contained initial image and filter boxes +// RESULT +// Error status +*/ +int showRootFilterBoxes(IplImage *image, + const CvLSVMFilterObjectCaskade *filter, + CvPoint *points, int *levels, int kPoints, + CvScalar color, int thickness, + int line_type, int shift); + +/* +// Drawing part filter boxes +// +// API +// int showPartFilterBoxes(const IplImage *image, + const CvLSVMFilterObjectCaskade *filter, + CvPoint *points, int *levels, int kPoints, + CvScalar color, int thickness, + int line_type, int shift); +// INPUT +// image - initial image +// filters - a set of part filters +// n - number of part filters +// partsDisplacement - a set of points +// levels - levels of feature pyramid +// kPoints - number of foot filter positions +// color - line color for each box +// thickness - line thickness +// line_type - line type +// shift - shift +// OUTPUT +// window contained initial image and filter boxes +// RESULT +// Error status +*/ +int showPartFilterBoxes(IplImage *image, + const CvLSVMFilterObjectCaskade **filters, + int n, CvPoint **partsDisplacement, + int *levels, int kPoints, + CvScalar color, int thickness, + int line_type, int shift); + +/* +// Drawing boxes +// +// API +// int showBoxes(const IplImage *img, + const CvPoint *points, const CvPoint *oppositePoints, int kPoints, + CvScalar color, int thickness, int line_type, int shift); +// INPUT +// img - initial image +// points - top left corner coordinates +// oppositePoints - right bottom corner coordinates +// kPoints - points number +// color - line color for each box +// thickness - line thickness +// line_type - line type +// shift - shift +// OUTPUT +// RESULT +// Error status +*/ +int showBoxes(IplImage *img, + const CvPoint *points, const CvPoint *oppositePoints, int kPoints, + CvScalar color, int thickness, int line_type, int shift); +} +} +#endif diff --git a/modules/latentsvm/src/_lsvmc_matching.h b/modules/latentsvm/src/_lsvmc_matching.h new file mode 100644 index 00000000000..3175d6047b4 --- /dev/null +++ b/modules/latentsvm/src/_lsvmc_matching.h @@ -0,0 +1,130 @@ +/*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) 2010-2013, University of Nizhny Novgorod, 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*/ + +/*****************************************************************************/ +/* Matching procedure API */ +/*****************************************************************************/ +// +#ifndef _LSVM_MATCHING_H_ +#define _LSVM_MATCHING_H_ + +#include "_lsvmc_latentsvm.h" +#include "_lsvmc_error.h" +#include "_lsvmc_routine.h" + +namespace cv +{ +namespace lsvm +{ + + +/* +// Computation border size for feature map +// +// API +// int computeBorderSize(int maxXBorder, int maxYBorder, int *bx, int *by); +// INPUT +// maxXBorder - the largest root filter size (X-direction) +// maxYBorder - the largest root filter size (Y-direction) +// OUTPUT +// bx - border size (X-direction) +// by - border size (Y-direction) +// RESULT +// Error status +*/ +int computeBorderSize(int maxXBorder, int maxYBorder, int *bx, int *by); + +/* +// Addition nullable border to the feature map +// +// API +// int addNullableBorder(featureMap *map, int bx, int by); +// INPUT +// map - feature map +// bx - border size (X-direction) +// by - border size (Y-direction) +// OUTPUT +// RESULT +// Error status +*/ +int addNullableBorder(CvLSVMFeatureMapCaskade *map, int bx, int by); + +/* +// Perform non-maximum suppression algorithm (described in original paper) +// to remove "similar" bounding boxes +// +// API +// int nonMaximumSuppression(int numBoxes, const CvPoint *points, + const CvPoint *oppositePoints, const float *score, + float overlapThreshold, + int *numBoxesout, CvPoint **pointsOut, + CvPoint **oppositePointsOut, float **scoreOut); +// INPUT +// numBoxes - number of bounding boxes +// points - array of left top corner coordinates +// oppositePoints - array of right bottom corner coordinates +// score - array of detection scores +// overlapThreshold - threshold: bounding box is removed if overlap part + is greater than passed value +// OUTPUT +// numBoxesOut - the number of bounding boxes algorithm returns +// pointsOut - array of left top corner coordinates +// oppositePointsOut - array of right bottom corner coordinates +// scoreOut - array of detection scores +// RESULT +// Error status +*/ +int nonMaximumSuppression(int numBoxes, const CvPoint *points, + const CvPoint *oppositePoints, const float *score, + float overlapThreshold, + int *numBoxesOut, CvPoint **pointsOut, + CvPoint **oppositePointsOut, float **scoreOut); +int getMaxFilterDims(const CvLSVMFilterObjectCaskade **filters, int kComponents, + const int *kPartFilters, + unsigned int *maxXBorder, unsigned int *maxYBorder); +//} + +int getMaxFilterDims(const CvLSVMFilterObjectCaskade **filters, int kComponents, + const int *kPartFilters, + unsigned int *maxXBorder, unsigned int *maxYBorder); +} +} +#endif diff --git a/modules/latentsvm/src/_lsvmc_parser.h b/modules/latentsvm/src/_lsvmc_parser.h new file mode 100644 index 00000000000..eb9a7f52ac4 --- /dev/null +++ b/modules/latentsvm/src/_lsvmc_parser.h @@ -0,0 +1,128 @@ +/*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) 2010-2013, University of Nizhny Novgorod, 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*/ + +#ifndef LSVM_PARSER +#define LSVM_PARSER + +#include "_lsvmc_types.h" + +#define MODEL 1 +#define P 2 +#define COMP 3 +#define SCORE 4 +#define RFILTER 100 +#define PFILTERs 101 +#define PFILTER 200 +#define SIZEX 150 +#define SIZEY 151 +#define WEIGHTS 152 +#define TAGV 300 +#define Vx 350 +#define Vy 351 +#define TAGD 400 +#define Dx 451 +#define Dy 452 +#define Dxx 453 +#define Dyy 454 +#define BTAG 500 + +#define PCA 5 +#define WEIGHTSPCA 162 +#define CASCADE_Th 163 +#define HYPOTHES_PCA 164 +#define DEFORM_PCA 165 +#define HYPOTHES 166 +#define DEFORM 167 + +#define PCACOEFF 6 + +#define STEP_END 1000 + +#define EMODEL (STEP_END + MODEL) +#define EP (STEP_END + P) +#define ECOMP (STEP_END + COMP) +#define ESCORE (STEP_END + SCORE) +#define ERFILTER (STEP_END + RFILTER) +#define EPFILTERs (STEP_END + PFILTERs) +#define EPFILTER (STEP_END + PFILTER) +#define ESIZEX (STEP_END + SIZEX) +#define ESIZEY (STEP_END + SIZEY) +#define EWEIGHTS (STEP_END + WEIGHTS) +#define ETAGV (STEP_END + TAGV) +#define EVx (STEP_END + Vx) +#define EVy (STEP_END + Vy) +#define ETAGD (STEP_END + TAGD) +#define EDx (STEP_END + Dx) +#define EDy (STEP_END + Dy) +#define EDxx (STEP_END + Dxx) +#define EDyy (STEP_END + Dyy) +#define EBTAG (STEP_END + BTAG) + +#define EPCA (STEP_END + PCA) +#define EWEIGHTSPCA (STEP_END + WEIGHTSPCA) +#define ECASCADE_Th (STEP_END + CASCADE_Th) +#define EHYPOTHES_PCA (STEP_END + HYPOTHES_PCA) +#define EDEFORM_PCA (STEP_END + DEFORM_PCA) +#define EHYPOTHES (STEP_END + HYPOTHES) +#define EDEFORM (STEP_END + DEFORM) + +#define EPCACOEFF (STEP_END + PCACOEFF) + +namespace cv +{ +namespace lsvm +{ + + int loadModel( + // input parametr + const char *modelPath,// model path + + // output parametrs + CvLSVMFilterObjectCaskade ***filters, + int *kFilters, + int *kComponents, + int **kPartFilters, + float **b, + float *scoreThreshold, + float ** PCAcoeff); +} +} +#endif diff --git a/modules/latentsvm/src/_lsvmc_resizeimg.h b/modules/latentsvm/src/_lsvmc_resizeimg.h new file mode 100644 index 00000000000..8c03a5ad2a3 --- /dev/null +++ b/modules/latentsvm/src/_lsvmc_resizeimg.h @@ -0,0 +1,56 @@ +/*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) 2010-2013, University of Nizhny Novgorod, 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*/ + +#ifndef _LSVM_RESIZEIMG_H_ +#define _LSVM_RESIZEIMG_H_ + +#include "_lsvmc_types.h" + +namespace cv +{ +namespace lsvm +{ + +IplImage * resize_opencv (IplImage * img, float scale); +} +} + +#endif diff --git a/modules/latentsvm/src/_lsvmc_routine.h b/modules/latentsvm/src/_lsvmc_routine.h new file mode 100644 index 00000000000..1e251e4a011 --- /dev/null +++ b/modules/latentsvm/src/_lsvmc_routine.h @@ -0,0 +1,76 @@ +/*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) 2010-2013, University of Nizhny Novgorod, 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*/ + +#ifndef _LSVM_ROUTINE_H_ +#define _LSVM_ROUTINE_H_ + +#include "_lsvmc_types.h" +#include "_lsvmc_error.h" + +namespace cv +{ +namespace lsvm +{ + + +////////////////////////////////////////////////////////////// +// Memory management routines +// All paramaters names correspond to previous data structures description +// All "alloc" functions return allocated memory for 1 object +// with all fields including arrays +// Error status is return value +////////////////////////////////////////////////////////////// +int allocFilterObject(CvLSVMFilterObjectCaskade **obj, const int sizeX, const int sizeY, + const int p); +int freeFilterObject (CvLSVMFilterObjectCaskade **obj); + +int allocFeatureMapObject(CvLSVMFeatureMapCaskade **obj, const int sizeX, const int sizeY, + const int p); +int freeFeatureMapObject (CvLSVMFeatureMapCaskade **obj); + +int allocFeaturePyramidObject(CvLSVMFeaturePyramidCaskade **obj, + const int countLevel); + +int freeFeaturePyramidObject (CvLSVMFeaturePyramidCaskade **obj); + +} +} +#endif diff --git a/modules/latentsvm/src/_lsvmc_types.h b/modules/latentsvm/src/_lsvmc_types.h new file mode 100644 index 00000000000..9c15ba0ae9f --- /dev/null +++ b/modules/latentsvm/src/_lsvmc_types.h @@ -0,0 +1,186 @@ +/*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) 2010-2013, University of Nizhny Novgorod, 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*/ + +#ifndef SVM_TYPE +#define SVM_TYPE + +#include "float.h" + +#define PI CV_PI + +#define EPS 0.000001 + +#define F_MAX FLT_MAX +#define F_MIN -FLT_MAX + +// The number of elements in bin +// The number of sectors in gradient histogram building +#define NUM_SECTOR 9 + +// The number of levels in image resize procedure +// We need Lambda levels to resize image twice +#define LAMBDA 10 + +// Block size. Used in feature pyramid building procedure +#define SIDE_LENGTH 8 + +#define VAL_OF_TRUNCATE 0.2f +namespace cv +{ +namespace lsvm +{ +////////////////////////////////////////////////////////////// +// main data structures // +////////////////////////////////////////////////////////////// + +// data type: STRUCT CvObjectDetection +// structure contains the bounding box and confidence level for detected object +// rect - bounding box for a detected object +// score - confidence level + +typedef struct CvObjectDetection +{ + cv::Rect rect; + float score; +} CvObjectDetection; + + +// DataType: STRUCT featureMap +// FEATURE MAP DESCRIPTION +// Rectangular map (sizeX x sizeY), +// every cell stores feature vector (dimension = numFeatures) +// map - matrix of feature vectors +// to set and get feature vectors (i,j) +// used formula map[(j * sizeX + i) * p + k], where +// k - component of feature vector in cell (i, j) +typedef struct{ + int sizeX; + int sizeY; + int numFeatures; + float *map; +} CvLSVMFeatureMapCaskade; + +// DataType: STRUCT featurePyramid +// +// numLevels - number of levels in the feature pyramid +// pyramid - array of pointers to feature map at different levels +typedef struct{ + int numLevels; + CvLSVMFeatureMapCaskade **pyramid; +} CvLSVMFeaturePyramidCaskade; + +// DataType: STRUCT filterDisposition +// The structure stores preliminary results in optimization process +// with objective function D +// +// x - array with X coordinates of optimization problems solutions +// y - array with Y coordinates of optimization problems solutions +// score - array with optimal objective values +typedef struct{ + float *score; + int *x; + int *y; +} CvLSVMFilterDisposition; + +// DataType: STRUCT position +// Structure describes the position of the filter in the feature pyramid +// l - level in the feature pyramid +// (x, y) - coordinate in level l + +typedef struct CvLSVMFilterPosition +{ + int x; + int y; + int l; +} CvLSVMFilterPosition; + +// DataType: STRUCT filterObject +// Description of the filter, which corresponds to the part of the object +// V - ideal (penalty = 0) position of the partial filter +// from the root filter position (V_i in the paper) +// penaltyFunction - vector describes penalty function (d_i in the paper) +// pf[0] * x + pf[1] * y + pf[2] * x^2 + pf[3] * y^2 +// FILTER DESCRIPTION +// Rectangular map (sizeX x sizeY), +// every cell stores feature vector (dimension = p) +// H - matrix of feature vectors +// to set and get feature vectors (i,j) +// used formula H[(j * sizeX + i) * p + k], where +// k - component of feature vector in cell (i, j) +// END OF FILTER DESCRIPTION + +typedef struct CvLSVMFilterObjectCaskade{ + CvLSVMFilterPosition V; + float fineFunction[4]; + int sizeX; + int sizeY; + int numFeatures; + float *H; + float *H_PCA; + float Hypothesis, Deformation; + float Hypothesis_PCA, Deformation_PCA; + int deltaX; + int deltaY; +} CvLSVMFilterObjectCaskade; + +// data type: STRUCT CvLatentSvmDetector +// structure contains internal representation of trained Latent SVM detector +// num_filters - total number of filters (root plus part) in model +// num_components - number of components in model +// num_part_filters - array containing number of part filters for each component +// filters - root and part filters for all model components +// b - biases for all model components +// score_threshold - confidence level threshold + +typedef struct CvLatentSvmDetectorCaskade +{ + int num_filters; + int num_components; + int* num_part_filters; + CvLSVMFilterObjectCaskade** filters; + float* b; + float score_threshold; + float *pca; + int pca_size; +} CvLatentSvmDetectorCaskade; +} +} +#endif diff --git a/modules/latentsvm/src/lsvmc_featurepyramid.cpp b/modules/latentsvm/src/lsvmc_featurepyramid.cpp new file mode 100644 index 00000000000..7dbfc1e5838 --- /dev/null +++ b/modules/latentsvm/src/lsvmc_featurepyramid.cpp @@ -0,0 +1,624 @@ +/*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) 2010-2013, University of Nizhny Novgorod, 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 "_lsvmc_latentsvm.h" +#include "_lsvmc_resizeimg.h" + +#ifdef HAVE_TBB +#include +#include "tbb/parallel_for.h" +#include "tbb/blocked_range.h" +#endif + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +namespace cv +{ +namespace lsvm +{ + +int getPathOfFeaturePyramid(IplImage * image, + float step, int numStep, int startIndex, + int sideLength, CvLSVMFeaturePyramidCaskade **maps); + +/* +// Getting feature map for the selected subimage +// +// API +// int getFeatureMaps(const IplImage * image, const int k, featureMap **map); +// INPUT +// image - selected subimage +// k - size of cells +// OUTPUT +// map - feature map +// RESULT +// Error status +*/ +int getFeatureMaps(const IplImage* image, const int k, CvLSVMFeatureMapCaskade **map) +{ + int sizeX, sizeY; + int p, px, stringSize; + int height, width, numChannels; + int i, j, kk, c, ii, jj, d; + float * datadx, * datady; + + int ch; + float magnitude, x, y, tx, ty; + + IplImage * dx, * dy; + int *nearest; + float *w, a_x, b_x; + + float kernel[3] = {-1.f, 0.f, 1.f}; + CvMat kernel_dx = cvMat(1, 3, CV_32F, kernel); + CvMat kernel_dy = cvMat(3, 1, CV_32F, kernel); + + float * r; + int * alfa; + + float boundary_x[NUM_SECTOR + 1]; + float boundary_y[NUM_SECTOR + 1]; + float max, dotProd; + int maxi; + + height = image->height; + width = image->width ; + + numChannels = image->nChannels; + + dx = cvCreateImage(cvSize(image->width, image->height), + IPL_DEPTH_32F, 3); + dy = cvCreateImage(cvSize(image->width, image->height), + IPL_DEPTH_32F, 3); + + sizeX = width / k; + sizeY = height / k; + px = 3 * NUM_SECTOR; + p = px; + stringSize = sizeX * p; + allocFeatureMapObject(map, sizeX, sizeY, p); + + cvFilter2D(image, dx, &kernel_dx, cvPoint(-1, 0)); + cvFilter2D(image, dy, &kernel_dy, cvPoint(0, -1)); + + float arg_vector; + for(i = 0; i <= NUM_SECTOR; i++) + { + arg_vector = ( (float) i ) * ( (float)(PI) / (float)(NUM_SECTOR) ); + boundary_x[i] = cosf(arg_vector); + boundary_y[i] = sinf(arg_vector); + }/*for(i = 0; i <= NUM_SECTOR; i++) */ + + r = (float *)malloc( sizeof(float) * (width * height)); + alfa = (int *)malloc( sizeof(int ) * (width * height * 2)); + + for(j = 1; j < height - 1; j++) + { + datadx = (float*)(dx->imageData + dx->widthStep * j); + datady = (float*)(dy->imageData + dy->widthStep * j); + for(i = 1; i < width - 1; i++) + { + c = 0; + x = (datadx[i * numChannels + c]); + y = (datady[i * numChannels + c]); + + r[j * width + i] =sqrtf(x * x + y * y); + for(ch = 1; ch < numChannels; ch++) + { + tx = (datadx[i * numChannels + ch]); + ty = (datady[i * numChannels + ch]); + magnitude = sqrtf(tx * tx + ty * ty); + if(magnitude > r[j * width + i]) + { + r[j * width + i] = magnitude; + c = ch; + x = tx; + y = ty; + } + }/*for(ch = 1; ch < numChannels; ch++)*/ + + max = boundary_x[0] * x + boundary_y[0] * y; + maxi = 0; + for (kk = 0; kk < NUM_SECTOR; kk++) + { + dotProd = boundary_x[kk] * x + boundary_y[kk] * y; + if (dotProd > max) + { + max = dotProd; + maxi = kk; + } + else + { + if (-dotProd > max) + { + max = -dotProd; + maxi = kk + NUM_SECTOR; + } + } + } + alfa[j * width * 2 + i * 2 ] = maxi % NUM_SECTOR; + alfa[j * width * 2 + i * 2 + 1] = maxi; + }/*for(i = 0; i < width; i++)*/ + }/*for(j = 0; j < height; j++)*/ + + nearest = (int *)malloc(sizeof(int ) * k); + w = (float*)malloc(sizeof(float) * (k * 2)); + + for(i = 0; i < k / 2; i++) + { + nearest[i] = -1; + }/*for(i = 0; i < k / 2; i++)*/ + for(i = k / 2; i < k; i++) + { + nearest[i] = 1; + }/*for(i = k / 2; i < k; i++)*/ + + for(j = 0; j < k / 2; j++) + { + b_x = k / 2 + j + 0.5f; + a_x = k / 2 - j - 0.5f; + w[j * 2 ] = 1.0f/a_x * ((a_x * b_x) / ( a_x + b_x)); + w[j * 2 + 1] = 1.0f/b_x * ((a_x * b_x) / ( a_x + b_x)); + }/*for(j = 0; j < k / 2; j++)*/ + for(j = k / 2; j < k; j++) + { + a_x = j - k / 2 + 0.5f; + b_x =-j + k / 2 - 0.5f + k; + w[j * 2 ] = 1.0f/a_x * ((a_x * b_x) / ( a_x + b_x)); + w[j * 2 + 1] = 1.0f/b_x * ((a_x * b_x) / ( a_x + b_x)); + }/*for(j = k / 2; j < k; j++)*/ + + for(i = 0; i < sizeY; i++) + { + for(j = 0; j < sizeX; j++) + { + for(ii = 0; ii < k; ii++) + { + for(jj = 0; jj < k; jj++) + { + if ((i * k + ii > 0) && + (i * k + ii < height - 1) && + (j * k + jj > 0) && + (j * k + jj < width - 1)) + { + d = (k * i + ii) * width + (j * k + jj); + (*map)->map[ i * stringSize + j * (*map)->numFeatures + alfa[d * 2 ]] += + r[d] * w[ii * 2] * w[jj * 2]; + (*map)->map[ i * stringSize + j * (*map)->numFeatures + alfa[d * 2 + 1] + NUM_SECTOR] += + r[d] * w[ii * 2] * w[jj * 2]; + if ((i + nearest[ii] >= 0) && + (i + nearest[ii] <= sizeY - 1)) + { + (*map)->map[(i + nearest[ii]) * stringSize + j * (*map)->numFeatures + alfa[d * 2 ] ] += + r[d] * w[ii * 2 + 1] * w[jj * 2 ]; + (*map)->map[(i + nearest[ii]) * stringSize + j * (*map)->numFeatures + alfa[d * 2 + 1] + NUM_SECTOR] += + r[d] * w[ii * 2 + 1] * w[jj * 2 ]; + } + if ((j + nearest[jj] >= 0) && + (j + nearest[jj] <= sizeX - 1)) + { + (*map)->map[i * stringSize + (j + nearest[jj]) * (*map)->numFeatures + alfa[d * 2 ] ] += + r[d] * w[ii * 2] * w[jj * 2 + 1]; + (*map)->map[i * stringSize + (j + nearest[jj]) * (*map)->numFeatures + alfa[d * 2 + 1] + NUM_SECTOR] += + r[d] * w[ii * 2] * w[jj * 2 + 1]; + } + if ((i + nearest[ii] >= 0) && + (i + nearest[ii] <= sizeY - 1) && + (j + nearest[jj] >= 0) && + (j + nearest[jj] <= sizeX - 1)) + { + (*map)->map[(i + nearest[ii]) * stringSize + (j + nearest[jj]) * (*map)->numFeatures + alfa[d * 2 ] ] += + r[d] * w[ii * 2 + 1] * w[jj * 2 + 1]; + (*map)->map[(i + nearest[ii]) * stringSize + (j + nearest[jj]) * (*map)->numFeatures + alfa[d * 2 + 1] + NUM_SECTOR] += + r[d] * w[ii * 2 + 1] * w[jj * 2 + 1]; + } + } + }/*for(jj = 0; jj < k; jj++)*/ + }/*for(ii = 0; ii < k; ii++)*/ + }/*for(j = 1; j < sizeX - 1; j++)*/ + }/*for(i = 1; i < sizeY - 1; i++)*/ + + cvReleaseImage(&dx); + cvReleaseImage(&dy); + + + free(w); + free(nearest); + + free(r); + free(alfa); + + return LATENT_SVM_OK; +} + +/* +// Feature map Normalization and Truncation +// +// API +// int normalizeAndTruncate(featureMap *map, const float alfa); +// INPUT +// map - feature map +// alfa - truncation threshold +// OUTPUT +// map - truncated and normalized feature map +// RESULT +// Error status +*/ +int normalizeAndTruncate(CvLSVMFeatureMapCaskade *map, const float alfa) +{ + int i,j, ii; + int sizeX, sizeY, p, pos, pp, xp, pos1, pos2; + float * partOfNorm; // norm of C(i, j) + float * newData; + float valOfNorm; + + sizeX = map->sizeX; + sizeY = map->sizeY; + partOfNorm = (float *)malloc (sizeof(float) * (sizeX * sizeY)); + + p = NUM_SECTOR; + xp = NUM_SECTOR * 3; + pp = NUM_SECTOR * 12; + + for(i = 0; i < sizeX * sizeY; i++) + { + valOfNorm = 0.0f; + pos = i * map->numFeatures; + for(j = 0; j < p; j++) + { + valOfNorm += map->map[pos + j] * map->map[pos + j]; + }/*for(j = 0; j < p; j++)*/ + partOfNorm[i] = valOfNorm; + }/*for(i = 0; i < sizeX * sizeY; i++)*/ + + sizeX -= 2; + sizeY -= 2; + + newData = (float *)malloc (sizeof(float) * (sizeX * sizeY * pp)); +//normalization + for(i = 1; i <= sizeY; i++) + { + for(j = 1; j <= sizeX; j++) + { + valOfNorm = sqrtf( + partOfNorm[(i )*(sizeX + 2) + (j )] + + partOfNorm[(i )*(sizeX + 2) + (j + 1)] + + partOfNorm[(i + 1)*(sizeX + 2) + (j )] + + partOfNorm[(i + 1)*(sizeX + 2) + (j + 1)]) + FLT_EPSILON; + pos1 = (i ) * (sizeX + 2) * xp + (j ) * xp; + pos2 = (i-1) * (sizeX ) * pp + (j-1) * pp; + for(ii = 0; ii < p; ii++) + { + newData[pos2 + ii ] = map->map[pos1 + ii ] / valOfNorm; + }/*for(ii = 0; ii < p; ii++)*/ + for(ii = 0; ii < 2 * p; ii++) + { + newData[pos2 + ii + p * 4] = map->map[pos1 + ii + p] / valOfNorm; + }/*for(ii = 0; ii < 2 * p; ii++)*/ + valOfNorm = sqrtf( + partOfNorm[(i )*(sizeX + 2) + (j )] + + partOfNorm[(i )*(sizeX + 2) + (j + 1)] + + partOfNorm[(i - 1)*(sizeX + 2) + (j )] + + partOfNorm[(i - 1)*(sizeX + 2) + (j + 1)]) + FLT_EPSILON; + for(ii = 0; ii < p; ii++) + { + newData[pos2 + ii + p ] = map->map[pos1 + ii ] / valOfNorm; + }/*for(ii = 0; ii < p; ii++)*/ + for(ii = 0; ii < 2 * p; ii++) + { + newData[pos2 + ii + p * 6] = map->map[pos1 + ii + p] / valOfNorm; + }/*for(ii = 0; ii < 2 * p; ii++)*/ + valOfNorm = sqrtf( + partOfNorm[(i )*(sizeX + 2) + (j )] + + partOfNorm[(i )*(sizeX + 2) + (j - 1)] + + partOfNorm[(i + 1)*(sizeX + 2) + (j )] + + partOfNorm[(i + 1)*(sizeX + 2) + (j - 1)]) + FLT_EPSILON; + for(ii = 0; ii < p; ii++) + { + newData[pos2 + ii + p * 2] = map->map[pos1 + ii ] / valOfNorm; + }/*for(ii = 0; ii < p; ii++)*/ + for(ii = 0; ii < 2 * p; ii++) + { + newData[pos2 + ii + p * 8] = map->map[pos1 + ii + p] / valOfNorm; + }/*for(ii = 0; ii < 2 * p; ii++)*/ + valOfNorm = sqrtf( + partOfNorm[(i )*(sizeX + 2) + (j )] + + partOfNorm[(i )*(sizeX + 2) + (j - 1)] + + partOfNorm[(i - 1)*(sizeX + 2) + (j )] + + partOfNorm[(i - 1)*(sizeX + 2) + (j - 1)]) + FLT_EPSILON; + for(ii = 0; ii < p; ii++) + { + newData[pos2 + ii + p * 3 ] = map->map[pos1 + ii ] / valOfNorm; + }/*for(ii = 0; ii < p; ii++)*/ + for(ii = 0; ii < 2 * p; ii++) + { + newData[pos2 + ii + p * 10] = map->map[pos1 + ii + p] / valOfNorm; + }/*for(ii = 0; ii < 2 * p; ii++)*/ + }/*for(j = 1; j <= sizeX; j++)*/ + }/*for(i = 1; i <= sizeY; i++)*/ +//truncation + for(i = 0; i < sizeX * sizeY * pp; i++) + { + if(newData [i] > alfa) newData [i] = alfa; + }/*for(i = 0; i < sizeX * sizeY * pp; i++)*/ +//swop data + + map->numFeatures = pp; + map->sizeX = sizeX; + map->sizeY = sizeY; + + free (map->map); + free (partOfNorm); + + map->map = newData; + + return LATENT_SVM_OK; +} +/* +// Feature map reduction +// In each cell we reduce dimension of the feature vector +// according to original paper special procedure +// +// API +// int PCAFeatureMaps(featureMap *map) +// INPUT +// map - feature map +// OUTPUT +// map - feature map +// RESULT +// Error status +*/ +int PCAFeatureMaps(CvLSVMFeatureMapCaskade *map) +{ + int i,j, ii, jj, k; + int sizeX, sizeY, p, pp, xp, yp, pos1, pos2; + float * newData; + float val; + float nx, ny; + + sizeX = map->sizeX; + sizeY = map->sizeY; + p = map->numFeatures; + pp = NUM_SECTOR * 3 + 4; + yp = 4; + xp = NUM_SECTOR; + + nx = 1.0f / sqrtf((float)(xp * 2)); + ny = 1.0f / sqrtf((float)(yp )); + + newData = (float *)malloc (sizeof(float) * (sizeX * sizeY * pp)); + + for(i = 0; i < sizeY; i++) + { + for(j = 0; j < sizeX; j++) + { + pos1 = ((i)*sizeX + j)*p; + pos2 = ((i)*sizeX + j)*pp; + k = 0; + for(jj = 0; jj < xp * 2; jj++) + { + val = 0; + for(ii = 0; ii < yp; ii++) + { + val += map->map[pos1 + yp * xp + ii * xp * 2 + jj]; + }/*for(ii = 0; ii < yp; ii++)*/ + newData[pos2 + k] = val * ny; + k++; + }/*for(jj = 0; jj < xp * 2; jj++)*/ + for(jj = 0; jj < xp; jj++) + { + val = 0; + for(ii = 0; ii < yp; ii++) + { + val += map->map[pos1 + ii * xp + jj]; + }/*for(ii = 0; ii < yp; ii++)*/ + newData[pos2 + k] = val * ny; + k++; + }/*for(jj = 0; jj < xp; jj++)*/ + for(ii = 0; ii < yp; ii++) + { + val = 0; + for(jj = 0; jj < 2 * xp; jj++) + { + val += map->map[pos1 + yp * xp + ii * xp * 2 + jj]; + }/*for(jj = 0; jj < xp; jj++)*/ + newData[pos2 + k] = val * nx; + k++; + } /*for(ii = 0; ii < yp; ii++)*/ + }/*for(j = 0; j < sizeX; j++)*/ + }/*for(i = 0; i < sizeY; i++)*/ +//swop data + + map->numFeatures = pp; + + free (map->map); + + map->map = newData; + + return LATENT_SVM_OK; +} + +int getPathOfFeaturePyramid(IplImage * image, + float step, int numStep, int startIndex, + int sideLength, CvLSVMFeaturePyramidCaskade **maps) +{ + CvLSVMFeatureMapCaskade *map; + IplImage *scaleTmp; + float scale; + int i; + + for(i = 0; i < numStep; i++) + { + scale = 1.0f / powf(step, (float)i); + scaleTmp = resize_opencv (image, scale); + getFeatureMaps(scaleTmp, sideLength, &map); + normalizeAndTruncate(map, VAL_OF_TRUNCATE); + PCAFeatureMaps(map); + (*maps)->pyramid[startIndex + i] = map; + cvReleaseImage(&scaleTmp); + }/*for(i = 0; i < numStep; i++)*/ + return LATENT_SVM_OK; +} + +#ifdef HAVE_TBB + +class PathOfFeaturePyramid : public ParallelLoopBody{ +public: + IplImage * image; + float step; + int startIndex; + int sideLength; + CvLSVMFeaturePyramidCaskade **maps; + + void operator() (const Range& range) const + { + CvLSVMFeatureMapCaskade *map; + IplImage *scaleTmp; + float scale; + int err; + + for( int i=range.start; i!=range.end; ++i ) + { + scale = 1.0f / powf(step, (float)i); + scaleTmp = resize_opencv (image, scale); + err = getFeatureMaps(scaleTmp, sideLength, &map); + err = normalizeAndTruncate(map, VAL_OF_TRUNCATE); + err = PCAFeatureMaps(map); + (*maps)->pyramid[startIndex + i] = map; + cvReleaseImage(&scaleTmp); + } + } +}; + + +int getPathOfFeaturePyramid_TBB(IplImage * image, + float step, int numStep, int startIndex, + int sideLength, CvLSVMFeaturePyramidCaskade **maps) +{ + PathOfFeaturePyramid str; + str.step = step; + str.startIndex = startIndex; + str.sideLength = sideLength; + str.maps = maps; + str.image = image; + + cv::parallel_for_(Range( 0, numStep ), str ); + + return LATENT_SVM_OK; +} +#endif + +/* +// Getting feature pyramid +// +// API +// int getFeaturePyramid(IplImage * image, const CvLSVMFilterObjectCaskade **all_F, + const int n_f, + const int lambda, const int k, + const int startX, const int startY, + const int W, const int H, featurePyramid **maps); +// INPUT +// image - image +// OUTPUT +// maps - feature maps for all levels +// RESULT +// Error status +*/ +int getFeaturePyramid(IplImage * image, CvLSVMFeaturePyramidCaskade **maps) +{ + IplImage *imgResize; + float step; + int numStep; + int maxNumCells; + int W, H; + + if(image->depth == IPL_DEPTH_32F) + { + imgResize = image; + } + else + { + imgResize = cvCreateImage(cvSize(image->width , image->height) , + IPL_DEPTH_32F , 3); + cvConvert(image, imgResize); + } + + W = imgResize->width; + H = imgResize->height; + + step = powf(2.0f, 1.0f / ((float)LAMBDA)); + maxNumCells = W / SIDE_LENGTH; + if( maxNumCells > H / SIDE_LENGTH ) + { + maxNumCells = H / SIDE_LENGTH; + } + numStep = (int)(logf((float) maxNumCells / (5.0f)) / logf( step )) + 1; + + allocFeaturePyramidObject(maps, numStep + LAMBDA); + +#ifdef HAVE_TBB + getPathOfFeaturePyramid_TBB(imgResize, step , LAMBDA, 0, + SIDE_LENGTH / 2, maps); + getPathOfFeaturePyramid_TBB(imgResize, step, numStep, LAMBDA, + SIDE_LENGTH , maps); +#else + getPathOfFeaturePyramid(imgResize, step , LAMBDA, 0, + SIDE_LENGTH / 2, maps); + getPathOfFeaturePyramid(imgResize, step, numStep, LAMBDA, + SIDE_LENGTH , maps); +#endif + + if(image->depth != IPL_DEPTH_32F) + { + cvReleaseImage(&imgResize); + } + + return LATENT_SVM_OK; +} +} +} diff --git a/modules/latentsvm/src/lsvmc_function.cpp b/modules/latentsvm/src/lsvmc_function.cpp new file mode 100644 index 00000000000..a515db2865b --- /dev/null +++ b/modules/latentsvm/src/lsvmc_function.cpp @@ -0,0 +1,127 @@ +/*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) 2010-2013, University of Nizhny Novgorod, 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 "_lsvmc_function.h" +namespace cv +{ +namespace lsvm +{ + +float calcM (int k,int di,int dj, const CvLSVMFeaturePyramidCaskade * H, const CvLSVMFilterObjectCaskade *filter){ + int i, j; + float m = 0.0f; + for(j = dj; j < dj + filter->sizeY; j++){ + for(i = di * H->pyramid[k]->numFeatures; i < (di + filter->sizeX) * H->pyramid[k]->numFeatures; i++){ + m += H->pyramid[k]->map[(j * H->pyramid[k]->sizeX ) * H->pyramid[k]->numFeatures + i] * + filter ->H [((j - dj) * filter->sizeX - di) * H->pyramid[k]->numFeatures + i]; + } + } + return m; +} +float calcM_PCA(int k,int di,int dj, const CvLSVMFeaturePyramidCaskade * H, const CvLSVMFilterObjectCaskade *filter){ + int i, j; + float m = 0.0f; + for(j = dj; j < dj + filter->sizeY; j++){ + for(i = di * H->pyramid[k]->numFeatures; i < (di + filter->sizeX) * H->pyramid[k]->numFeatures; i++){ + m += H->pyramid[k]->map[(j * H->pyramid[k]->sizeX ) * H->pyramid[k]->numFeatures + i] * + filter ->H_PCA [((j - dj) * filter->sizeX - di) * H->pyramid[k]->numFeatures + i]; + } + } + + return m; +} +float calcM_PCA_cash(int k,int di,int dj, const CvLSVMFeaturePyramidCaskade * H, const CvLSVMFilterObjectCaskade *filter, float * cashM, int * maskM, int step){ + int i, j, n; + float m = 0.0f; + float tmp1, tmp2, tmp3, tmp4; + float res; + int pos; + float *a, *b; + + pos = dj * step + di; + + if(!((maskM[pos / (sizeof(int) * 8)]) & (1 << pos % (sizeof(int) * 8)))) + { + for(j = dj; j < dj + filter->sizeY; j++) + { + a = H->pyramid[k]->map + (j * H->pyramid[k]->sizeX) * H->pyramid[k]->numFeatures + + di * H->pyramid[k]->numFeatures; + b = filter ->H_PCA + (j - dj) * filter->sizeX * H->pyramid[k]->numFeatures; + n = ((di + filter->sizeX) * H->pyramid[k]->numFeatures) - + (di * H->pyramid[k]->numFeatures); + + res = 0.0f; + tmp1 = 0.0f; tmp2 = 0.0f; tmp3 = 0.0f; tmp4 = 0.0f; + + for (i = 0; i < (n >> 2); ++i) + { + tmp1 += a[4 * i + 0] * b[4 * i + 0]; + tmp2 += a[4 * i + 1] * b[4 * i + 1]; + tmp3 += a[4 * i + 2] * b[4 * i + 2]; + tmp4 += a[4 * i + 3] * b[4 * i + 3]; + } + + for (i = (n >> 2) << 2; i < n; ++i) //? + { + res += a[i] * b[i]; + } + + res += tmp1 + tmp2 + tmp3 + tmp4; + + m += res; + } + + cashM[pos ] = m; + maskM[pos / (sizeof(int) * 8)] |= 1 << pos % (sizeof(int) * 8); + } + else + { + m = cashM[pos]; + } + return m; +} +float calcFine (const CvLSVMFilterObjectCaskade *filter, int di, int dj){ + return filter->fineFunction[0] * di + filter->fineFunction[1] * dj + + filter->fineFunction[2] * di * di + filter->fineFunction[3] * dj * dj; +} +} +} diff --git a/modules/latentsvm/src/lsvmc_latentsvm.cpp b/modules/latentsvm/src/lsvmc_latentsvm.cpp new file mode 100644 index 00000000000..e2d65945d62 --- /dev/null +++ b/modules/latentsvm/src/lsvmc_latentsvm.cpp @@ -0,0 +1,1018 @@ +/*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) 2010-2013, University of Nizhny Novgorod, 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 "_lsvmc_latentsvm.h" +#include "_lsvmc_matching.h" +#include "_lsvmc_function.h" + +#ifdef HAVE_TBB +#include +#include "tbb/parallel_for.h" +#include "tbb/blocked_range.h" +#endif + +namespace cv +{ +namespace lsvm +{ + +int estimateBoxes(CvPoint *points, int *levels, int kPoints, + int sizeX, int sizeY, CvPoint **oppositePoints); + +int searchObjectThreshold(const CvLSVMFeaturePyramidCaskade *H, + const CvLSVMFeaturePyramidCaskade *H_PCA, + const CvLSVMFilterObjectCaskade **all_F, int n, + float b, + int maxXBorder, int maxYBorder, + float scoreThreshold, + CvPoint **points, int **levels, int *kPoints, + float **score, CvPoint ***partsDisplacement); + +void FeaturePyramid32(CvLSVMFeaturePyramidCaskade* H, int maxX, int maxY){ + CvLSVMFeatureMapCaskade *H32; + int i, j, k, l; + int p = H->pyramid[0]->numFeatures; + + for(i = 0; i < H->numLevels; i++){ + allocFeatureMapObject(&(H32), H->pyramid[i]->sizeX, H->pyramid[i]->sizeY, p + 1); + for(j = 0; j < (H->pyramid[i]->sizeX * H->pyramid[i]->sizeY); j++){ + for(k = 0; k < p; k++){ + H32->map[j * (p + 1) + k] = H->pyramid[i]->map[j * p + k]; + } + H32->map[j * (p + 1) + k] = 1.0f; + } + freeFeatureMapObject(&(H->pyramid[i])); + H->pyramid[i] = H32; + } + for(l = 0; l < H->numLevels; l++){ + for(j = maxY + 1; j < (H->pyramid[l]->sizeY - maxY - 1); j++){ + for(i = maxX + 1; i < (H->pyramid[l]->sizeX - maxX - 1); i++){ + H->pyramid[l]->map[ (j * H->pyramid[l]->sizeX + i) * (p+1) + p] = 0.0f; + } + } + } +} + +CvLSVMFeaturePyramidCaskade* createPCA_FeaturePyramid(CvLSVMFeaturePyramidCaskade* H, CvLatentSvmDetectorCaskade* detector, int maxX, int maxY){ + CvLSVMFeaturePyramidCaskade *H_PCA; + int i, j, k, l; + int max_l = detector->pca_size; + int p = H->pyramid[0]->numFeatures; + + allocFeaturePyramidObject(&H_PCA, H->numLevels); + + for(i = 0; i < H->numLevels; i++){ + allocFeatureMapObject(&(H_PCA->pyramid[i]), H->pyramid[i]->sizeX, H->pyramid[i]->sizeY, 6); + for(j = 0; j < (H->pyramid[i]->sizeX * H->pyramid[i]->sizeY); j++){ + for(k = 0; k < 5; k++){ + for(l = 0; l < max_l; l++){ + H_PCA->pyramid[i]->map[j * 6 + k] += + detector->pca[k * max_l + l] * H->pyramid[i]->map[j * p + l]; + } + } + H_PCA->pyramid[i]->map[j * 6 + k] = 1.0f; + } + } + for(l = 0; l < H->numLevels; l++){ + for(j = maxY + 1; j < (H->pyramid[l]->sizeY - maxY - 1); j++){ + for(i = maxX + 1; i < (H->pyramid[l]->sizeX - maxX - 1); i++){ + H_PCA->pyramid[l]->map[ (j * H->pyramid[l]->sizeX + i) * 6 + 5] = 0.0f; + } + } + } + + return H_PCA; +} + +/* +// Transformation filter displacement from the block space +// to the space of pixels at the initial image +// +// API +// int convertPoints(int countLevel, CvPoint *points, int *levels, + CvPoint **partsDisplacement, int kPoints, int n); +// INPUT +// countLevel - the number of levels in the feature pyramid +// points - the set of root filter positions (in the block space) +// levels - the set of levels +// partsDisplacement - displacement of part filters (in the block space) +// kPoints - number of root filter positions +// n - number of part filters +// initialImageLevel - level that contains features for initial image +// maxXBorder - the largest root filter size (X-direction) +// maxYBorder - the largest root filter size (Y-direction) +// OUTPUT +// points - the set of root filter positions (in the space of pixels) +// partsDisplacement - displacement of part filters (in the space of pixels) +// RESULT +// Error status +*/ +int convertPoints(int /*countLevel*/, int lambda, + int initialImageLevel, + CvPoint *points, int *levels, + CvPoint **partsDisplacement, int kPoints, int n, + int maxXBorder, + int maxYBorder) +{ + int i, j; + float step, scale; + step = powf( 2.0f, 1.0f / ((float)lambda) ); + + //computeBorderSize(maxXBorder, maxYBorder, &bx, &by); + + for (i = 0; i < kPoints; i++) + { + // scaling factor for root filter + scale = SIDE_LENGTH * powf(step, (float)(levels[i] - initialImageLevel)); + points[i].x = (int)((points[i].x - maxXBorder) * scale); + points[i].y = (int)((points[i].y - maxYBorder) * scale); + + // scaling factor for part filters + scale = SIDE_LENGTH * powf(step, (float)(levels[i] - lambda - initialImageLevel)); + for (j = 0; j < n; j++) + { + partsDisplacement[i][j].x = (int)((partsDisplacement[i][j].x - + maxXBorder) * scale); + partsDisplacement[i][j].y = (int)((partsDisplacement[i][j].y - + maxYBorder) * scale); + } + } + return LATENT_SVM_OK; +} + +/* +// Elimination boxes that are outside the image boudaries +// +// API +// int clippingBoxes(int width, int height, + CvPoint *points, int kPoints); +// INPUT +// width - image wediht +// height - image heigth +// points - a set of points (coordinates of top left or + bottom right corners) +// kPoints - points number +// OUTPUT +// points - updated points (if coordinates less than zero then + set zero coordinate, if coordinates more than image + size then set coordinates equal image size) +// RESULT +// Error status +*/ +int clippingBoxes(int width, int height, + CvPoint *points, int kPoints) +{ + int i; + for (i = 0; i < kPoints; i++) + { + if (points[i].x > width - 1) + { + points[i].x = width - 1; + } + if (points[i].x < 0) + { + points[i].x = 0; + } + if (points[i].y > height - 1) + { + points[i].y = height - 1; + } + if (points[i].y < 0) + { + points[i].y = 0; + } + } + return LATENT_SVM_OK; +} + +/* +// Creation feature pyramid with nullable border +// +// API +// featurePyramid* createFeaturePyramidWithBorder(const IplImage *image, + int maxXBorder, int maxYBorder); + +// INPUT +// image - initial image +// maxXBorder - the largest root filter size (X-direction) +// maxYBorder - the largest root filter size (Y-direction) +// OUTPUT +// RESULT +// Feature pyramid with nullable border +*/ +CvLSVMFeaturePyramidCaskade* createFeaturePyramidWithBorder(IplImage *image, + int maxXBorder, int maxYBorder) +{ + int opResult; + int bx, by; + int level; + CvLSVMFeaturePyramidCaskade *H; + + // Obtaining feature pyramid + opResult = getFeaturePyramid(image, &H); + + if (opResult != LATENT_SVM_OK) + { + freeFeaturePyramidObject(&H); + return NULL; + } /* if (opResult != LATENT_SVM_OK) */ + + // Addition nullable border for each feature map + // the size of the border for root filters + bx = maxXBorder + 1; + by = maxYBorder + 1; + for (level = 0; level < H->numLevels; level++) + { + addNullableBorder(H->pyramid[level], bx, by); + } + return H; +} + +/* +// Computation right bottom corners coordinates of bounding boxes +// +// API +// int estimateBoxes(CvPoint *points, int *levels, int kPoints, + int sizeX, int sizeY, CvPoint **oppositePoints); +// INPUT +// points - left top corners coordinates of bounding boxes +// levels - levels of feature pyramid where points were found +// (sizeX, sizeY) - size of root filter +// OUTPUT +// oppositePoins - right bottom corners coordinates of bounding boxes +// RESULT +// Error status +*/ +int estimateBoxes(CvPoint *points, int *levels, int kPoints, + int sizeX, int sizeY, CvPoint **oppositePoints) +{ + int i; + float step; + + step = powf( 2.0f, 1.0f / ((float)(LAMBDA))); + + *oppositePoints = (CvPoint *)malloc(sizeof(CvPoint) * kPoints); + for (i = 0; i < kPoints; i++) + { + getOppositePoint(points[i], sizeX, sizeY, step, levels[i] - LAMBDA, &((*oppositePoints)[i])); + } + return LATENT_SVM_OK; +} + +/* +// Computation of the root filter displacement and values of score function +// +// API +// int searchObjectThreshold(const featurePyramid *H, + const CvLSVMFilterObjectCaskade **all_F, int n, + float b, + int maxXBorder, int maxYBorder, + float scoreThreshold, + CvPoint **points, int **levels, int *kPoints, + float **score, CvPoint ***partsDisplacement); +// INPUT +// H - feature pyramid +// all_F - the set of filters (the first element is root filter, + other elements - part filters) +// n - the number of part filters +// b - linear term of the score function +// maxXBorder - the largest root filter size (X-direction) +// maxYBorder - the largest root filter size (Y-direction) +// scoreThreshold - score threshold +// OUTPUT +// points - positions (x, y) of the upper-left corner + of root filter frame +// levels - levels that correspond to each position +// kPoints - number of positions +// score - values of the score function +// partsDisplacement - part filters displacement for each position + of the root filter +// RESULT +// Error status +*/ +int searchObjectThreshold(const CvLSVMFeaturePyramidCaskade *H, + const CvLSVMFeaturePyramidCaskade *H_PCA, + const CvLSVMFilterObjectCaskade **all_F, int n, + float b, + int maxXBorder, int maxYBorder, + float scoreThreshold, + CvPoint **points, int **levels, int *kPoints, + float **score, CvPoint ***partsDisplacement) +{ + int opResult = LATENT_SVM_OK; + + int i, j, k, path; + int di, dj, ii; + + //int *map,jj, nomer; + //FILE *dump; + + float p; + float fine; + float mpath; + + CvPoint *tmpPoints; + int *tmpLevels; + float **tmpAScore; + + int flag,flag2; + + CvPoint *PCAPoints; + int *PCALevels; + float **PCAAScore; + int PCAkPoints; + float PCAScore; + int tmpSize = 10; + int tmpStep = 10; + + float *rootScoreForLevel; + int maxX, maxY, maxPathX, maxPathY, step; + int pathX, pathY; + int ai; + + + float **cashM; + int **maskM; + int sizeM; + + sizeM = H_PCA->pyramid[0]->sizeX - maxXBorder + 1; + sizeM *= H_PCA->pyramid[0]->sizeY - maxYBorder + 1; + + cashM = (float**)malloc(sizeof(float *) * n); + maskM = (int **)malloc(sizeof(int *) * n); + for(ai = 0; ai < n; ai++){ + cashM[ai] = (float*)malloc(sizeof(float) * sizeM); + maskM[ai] = (int *)malloc(sizeof(int) * (sizeM/(sizeof(int) * 8) + 1)); + } + + + PCAPoints = (CvPoint*)malloc(sizeof(CvPoint) * tmpSize); + PCALevels = (int*)malloc(sizeof(int) * tmpSize); + PCAAScore = (float **)malloc(sizeof(float *) * tmpSize); + for(ai = 0; ai < tmpSize; ai++){ + PCAAScore[ai] = (float *)malloc(sizeof(float) * (n + 2)); + } + + PCAkPoints = 0; + for(k = LAMBDA; k < H_PCA->numLevels; k++){ + maxX = H_PCA->pyramid[k]->sizeX - maxXBorder + 1; + maxY = H_PCA->pyramid[k]->sizeY - maxYBorder + 1; + maxPathX = H_PCA->pyramid[k - LAMBDA]->sizeX - maxXBorder + 1; + maxPathY = H_PCA->pyramid[k - LAMBDA]->sizeY - maxYBorder + 1; + rootScoreForLevel = (float *) malloc(sizeof(float) + * (maxX - (int)ceil(maxXBorder/2.0)) + * (maxY - (int)ceil(maxYBorder/2.0))); + + step = maxX - (int)ceil(maxXBorder/2.0); + //dump = fopen("map_10.csv", "w"); + for(j = (int)ceil(maxYBorder/2.0) ; j < maxY; j++){ + for(i = (int)ceil(maxXBorder/2.0) ; i < maxX; i++){ + rootScoreForLevel[(j - (int)ceil(maxYBorder/2.0)) * step + i - (int)ceil(maxXBorder/2.0)] + = calcM_PCA(k, i, j, H_PCA, all_F[0]); + // fprintf(dump, "%f;", rootScoreForLevel[j * maxX + i]); + } + // fprintf(dump, "\n"); + } + // fclose(dump); + + sizeM = maxPathX * maxPathY; + for(path = 0 ; path < n; path++){ + memset(maskM[path], 0, sizeof(int) * (sizeM/(sizeof(int) * 8) + 1)); + } + + for(j = (int)ceil(maxYBorder/2.0) ; j < maxY; j++){ + for(i = (int)ceil(maxXBorder/2.0) ; i < maxX; i++){ + // PCAScore = calcM_PCA(k, i, j, H_PCA, all_F[0]); + PCAScore = + rootScoreForLevel[(j - (int)ceil(maxYBorder/2.0)) * step + i - (int)ceil(maxXBorder/2.0)]; + PCAScore += b; + PCAAScore[PCAkPoints][0] = PCAScore - b; + + flag2=0; + for(path = 1 ; (path <= n) && (!flag2); path++){ + if(PCAScore > all_F[path - 1]->Deformation_PCA) + { + p = F_MIN ; + //pathX = (i - maxXBorder - 1) * 2 + maxXBorder + 1 + all_F[path]->V.x; + //pathY = (j - maxYBorder - 1) * 2 + maxYBorder + 1 + all_F[path]->V.y; + pathX = i * 2 - maxXBorder + all_F[path]->V.x; + pathY = j * 2 - maxYBorder + all_F[path]->V.y; + flag = 1; + for(dj = max(0, pathY - all_F[path]->deltaY); + dj < min(maxPathY, pathY + all_F[path]->deltaY); + dj++){ + for(di = max(0, pathX - all_F[path]->deltaX); + di < min(maxPathX, pathX + all_F[path]->deltaX); + di++){ + //fine = calcFine(all_F[path], abs(pathX - di), abs(pathY - dj)); + fine = calcFine(all_F[path], pathX - di, pathY - dj); + if((PCAScore - fine) > all_F[path - 1]->Hypothesis_PCA) + { + flag = 0; + mpath = calcM_PCA_cash(k - LAMBDA, di, dj, H_PCA, all_F[path], cashM[path - 1], maskM[path - 1], maxPathX) - fine; + if( mpath > p){ + p = mpath; + } + } + } + } + if(flag==0){ + PCAAScore[PCAkPoints][path] = p;// + pfine; + PCAScore += p;// + pfine; + } else flag2 = 1; + } + else flag2 = 1; + } + if((PCAScore > all_F[n]->Hypothesis_PCA)&&(flag2==0)){ + PCALevels[PCAkPoints] = k; + PCAPoints[PCAkPoints].x = i; + PCAPoints[PCAkPoints].y = j; + PCAAScore[PCAkPoints][n + 1] = PCAScore; + PCAkPoints ++; + if(PCAkPoints >= tmpSize){ + tmpPoints = (CvPoint*)malloc(sizeof(CvPoint) * (tmpSize + tmpStep)); + tmpLevels = (int*)malloc(sizeof(int) * (tmpSize + tmpStep)); + tmpAScore = (float **)malloc(sizeof(float *) * (tmpSize + tmpStep)); + for(ai = tmpSize; ai < tmpSize + tmpStep; ai++){ + tmpAScore[ai] = (float *)malloc(sizeof(float) * (n + 2)); + } + for(ii = 0; ii < PCAkPoints; ii++){ + tmpLevels[ii] = PCALevels[ii] ; + tmpPoints[ii].x = PCAPoints[ii].x; + tmpPoints[ii].y = PCAPoints[ii].y; + tmpAScore[ii] = PCAAScore[ii] ; + } + free(PCALevels); + free(PCAPoints); + free(PCAAScore); + PCALevels = tmpLevels; + PCAPoints = tmpPoints; + PCAAScore = tmpAScore; + tmpSize += tmpStep; + } + } + } + } + free (rootScoreForLevel); + } + + (*points) = (CvPoint *)malloc(sizeof(CvPoint) * PCAkPoints); + (*levels) = (int *)malloc(sizeof(int ) * PCAkPoints); + (*score ) = (float *)malloc(sizeof(float ) * PCAkPoints); + (*partsDisplacement) = (CvPoint **)malloc(sizeof(CvPoint *) * (PCAkPoints + 1)); + + (*kPoints) = 0; + if(PCAkPoints > 0) + (*partsDisplacement)[(*kPoints)] = (CvPoint *)malloc(sizeof(CvPoint) * (n + 1)); + for(ii = 0; ii < PCAkPoints; ii++) + { + k = PCALevels[ii] ; + i = PCAPoints[ii].x; + j = PCAPoints[ii].y; + + maxPathX = H_PCA->pyramid[k - LAMBDA]->sizeX - maxXBorder + 1; + maxPathY = H_PCA->pyramid[k - LAMBDA]->sizeY - maxYBorder + 1; + + (*score )[(*kPoints)] = PCAAScore[ii][n + 1] + calcM(k, i, j, H, all_F[0]) - PCAAScore[ii][0]; + (*partsDisplacement)[(*kPoints)][0].x = i; + (*partsDisplacement)[(*kPoints)][0].y = j; + for(path = 1 ; path <= n; path++){ + if((*score )[(*kPoints)] < all_F[path - 1]->Deformation) break; + // { + p = F_MIN ; + flag = 1; + //pathX = (i - maxXBorder - 1) * 2 + maxXBorder + 1 + all_F[path]->V.x; + //pathY = (j - maxYBorder - 1) * 2 + maxYBorder + 1 + all_F[path]->V.y; + pathX = i * 2 - maxXBorder + all_F[path]->V.x; + pathY = j * 2 - maxYBorder + all_F[path]->V.y; + for(dj = max(0, pathY - all_F[path]->deltaY); + dj < min(maxPathY, pathY + all_F[path]->deltaY); + dj++){ + for(di = max(0, pathX - all_F[path]->deltaX); + di < min(maxPathX, pathX + all_F[path]->deltaX); + di++){ + //fine = calcFine(all_F[path], abs(pathX - di), abs(pathY - dj)); + fine = calcFine(all_F[path], pathX - di, pathY - dj); + if(((*score )[(*kPoints)] - fine) > all_F[path - 1]->Hypothesis) + { + flag = 0; + mpath = calcM(k - LAMBDA, di, dj, H, all_F[path]) - fine; + if(mpath > p){ + p = mpath; + (*partsDisplacement)[(*kPoints)][path].x = di; + (*partsDisplacement)[(*kPoints)][path].y = dj; + } + } + } + } + if(flag == 0) + (*score )[(*kPoints)] += p - PCAAScore[ii][path];// + pfine; + // } + } + if((*score )[(*kPoints)] > scoreThreshold) + { + (*levels)[(*kPoints)] = k; + (*points)[(*kPoints)].x = i; + (*points)[(*kPoints)].y = j; + (*kPoints) ++; + (*partsDisplacement)[(*kPoints)] = (CvPoint*) malloc(sizeof(CvPoint) * (n + 1)); + } + } + if((*kPoints) > 0){ + free((*partsDisplacement)[(*kPoints)]); + } + // Matching end + + free(PCAPoints); + free(PCALevels); + for(ai = 0; ai < tmpSize; ai++){ + free(PCAAScore[ai]); + } + free(PCAAScore); + + for(ai = 0; ai < n; ai++){ + free(cashM[ai]); + free(maskM[ai]); + } + free(cashM); + free(maskM); + + if (opResult != (LATENT_SVM_OK)) + { + return LATENT_SVM_SEARCH_OBJECT_FAILED; + } + + // Transformation filter displacement from the block space + // to the space of pixels at the initial image + // that settles at the level number LAMBDA + convertPoints(H->numLevels, LAMBDA, LAMBDA, (*points), + (*levels), (*partsDisplacement), (*kPoints), n, + maxXBorder, maxYBorder); + + return LATENT_SVM_OK; +} + +/* +// Compute opposite point for filter box +// +// API +// int getOppositePoint(CvPoint point, + int sizeX, int sizeY, + float step, int degree, + CvPoint *oppositePoint); + +// INPUT +// point - coordinates of filter top left corner + (in the space of pixels) +// (sizeX, sizeY) - filter dimension in the block space +// step - scaling factor +// degree - degree of the scaling factor +// OUTPUT +// oppositePoint - coordinates of filter bottom corner + (in the space of pixels) +// RESULT +// Error status +*/ +int getOppositePoint(CvPoint point, + int sizeX, int sizeY, + float step, int degree, + CvPoint *oppositePoint) +{ + float scale; + scale = SIDE_LENGTH * powf(step, (float)degree); + oppositePoint->x = (int)(point.x + sizeX * scale); + oppositePoint->y = (int)(point.y + sizeY * scale); + return LATENT_SVM_OK; +} + + +/* +// Drawing root filter boxes +// +// API +// int showRootFilterBoxes(const IplImage *image, + const CvLSVMFilterObjectCaskade *filter, + CvPoint *points, int *levels, int kPoints, + CvScalar color, int thickness, + int line_type, int shift); +// INPUT +// image - initial image +// filter - root filter object +// points - a set of points +// levels - levels of feature pyramid +// kPoints - number of points +// color - line color for each box +// thickness - line thickness +// line_type - line type +// shift - shift +// OUTPUT +// window contained initial image and filter boxes +// RESULT +// Error status +*/ +int showRootFilterBoxes(IplImage *image, + const CvLSVMFilterObjectCaskade *filter, + CvPoint *points, int *levels, int kPoints, + CvScalar color, int thickness, + int line_type, int shift) +{ + int i; + float step; + CvPoint oppositePoint; + step = powf( 2.0f, 1.0f / ((float)LAMBDA)); + + for (i = 0; i < kPoints; i++) + { + // Drawing rectangle for filter + getOppositePoint(points[i], filter->sizeX, filter->sizeY, + step, levels[i] - LAMBDA, &oppositePoint); + cvRectangle(image, points[i], oppositePoint, + color, thickness, line_type, shift); + } +#ifdef HAVE_OPENCV_HIGHGUI + cvShowImage("Initial image", image); +#endif + return LATENT_SVM_OK; +} + +/* +// Drawing part filter boxes +// +// API +// int showPartFilterBoxes(const IplImage *image, + const CvLSVMFilterObjectCaskade *filter, + CvPoint *points, int *levels, int kPoints, + CvScalar color, int thickness, + int line_type, int shift); +// INPUT +// image - initial image +// filters - a set of part filters +// n - number of part filters +// partsDisplacement - a set of points +// levels - levels of feature pyramid +// kPoints - number of foot filter positions +// color - line color for each box +// thickness - line thickness +// line_type - line type +// shift - shift +// OUTPUT +// window contained initial image and filter boxes +// RESULT +// Error status +*/ +int showPartFilterBoxes(IplImage *image, + const CvLSVMFilterObjectCaskade **filters, + int n, CvPoint **partsDisplacement, + int *levels, int kPoints, + CvScalar color, int thickness, + int line_type, int shift) +{ + int i, j; + float step; + CvPoint oppositePoint; + + step = powf( 2.0f, 1.0f / ((float)LAMBDA)); + + for (i = 0; i < kPoints; i++) + { + for (j = 0; j < n; j++) + { + // Drawing rectangles for part filters + getOppositePoint(partsDisplacement[i][j], + filters[j + 1]->sizeX, filters[j + 1]->sizeY, + step, levels[i] - 2 * LAMBDA, &oppositePoint); + cvRectangle(image, partsDisplacement[i][j], oppositePoint, + color, thickness, line_type, shift); + } + } +#ifdef HAVE_OPENCV_HIGHGUI + cvShowImage("Initial image", image); +#endif + return LATENT_SVM_OK; +} + +/* +// Drawing boxes +// +// API +// int showBoxes(const IplImage *img, + const CvPoint *points, const CvPoint *oppositePoints, int kPoints, + CvScalar color, int thickness, int line_type, int shift); +// INPUT +// img - initial image +// points - top left corner coordinates +// oppositePoints - right bottom corner coordinates +// kPoints - points number +// color - line color for each box +// thickness - line thickness +// line_type - line type +// shift - shift +// OUTPUT +// RESULT +// Error status +*/ +int showBoxes(IplImage *img, + const CvPoint *points, const CvPoint *oppositePoints, int kPoints, + CvScalar color, int thickness, int line_type, int shift) +{ + int i; + for (i = 0; i < kPoints; i++) + { + cvRectangle(img, points[i], oppositePoints[i], + color, thickness, line_type, shift); + } +#ifdef HAVE_OPENCV_HIGHGUI + cvShowImage("Initial image", img); +#endif + return LATENT_SVM_OK; +} + +///* +//// Computation maximum filter size for each dimension +//// +//// API +//// int getMaxFilterDims(const CvLSVMFilterObjectCaskade **filters, int kComponents, +// const int *kPartFilters, +// unsigned int *maxXBorder, unsigned int *maxYBorder); +//// INPUT +//// filters - a set of filters (at first root filter, then part filters +// and etc. for all components) +//// kComponents - number of components +//// kPartFilters - number of part filters for each component +//// OUTPUT +//// maxXBorder - maximum of filter size at the horizontal dimension +//// maxYBorder - maximum of filter size at the vertical dimension +//// RESULT +//// Error status +//*/ +//int getMaxFilterDims(const CvLSVMFilterObjectCaskade **filters, int kComponents, +// const int *kPartFilters, +// unsigned int *maxXBorder, unsigned int *maxYBorder) +//{ +// int i, componentIndex; +// *maxXBorder = filters[0]->sizeX; +// *maxYBorder = filters[0]->sizeY; +// componentIndex = kPartFilters[0] + 1; +// for (i = 1; i < kComponents; i++) +// { +// if ((unsigned)filters[componentIndex]->sizeX > *maxXBorder) +// { +// *maxXBorder = filters[componentIndex]->sizeX; +// } +// if ((unsigned)filters[componentIndex]->sizeY > *maxYBorder) +// { +// *maxYBorder = filters[componentIndex]->sizeY; +// } +// componentIndex += (kPartFilters[i] + 1); +// } +// return LATENT_SVM_OK; +//} + + +#ifdef HAVE_TBB + +class PathOfModel :public ParallelLoopBody{ + int *componentIndex; + const CvLSVMFeaturePyramidCaskade *H; + const CvLSVMFeaturePyramidCaskade *H_PCA; + const CvLSVMFilterObjectCaskade **filters; + const int *kPartFilters; + const float *b; + unsigned int maxXBorder, maxYBorder; + CvPoint **pointsArr, **oppPointsArr, ***partsDisplacementArr; + float **scoreArr; + int *kPointsArr, **levelsArr; + float scoreThreshold; + CvPoint **oppPoints; +public: + PathOfModel( + int *_componentIndex, + const CvLSVMFeaturePyramidCaskade *_H, + const CvLSVMFeaturePyramidCaskade *_H_PCA, + const CvLSVMFilterObjectCaskade **_filters, + const int *_kPartFilters, + const float *_b, + unsigned int _maxXBorder, unsigned int _maxYBorder, + CvPoint **_pointsArr, CvPoint **_oppPointsArr, CvPoint ***_partsDisplacementArr, + float **_scoreArr, + int *_kPointsArr, int **_levelsArr, + float _scoreThreshold, + CvPoint **_oppPoints + ): + componentIndex(_componentIndex), + H(_H), + H_PCA(_H_PCA), + filters(_filters), + kPartFilters(_kPartFilters), + b(_b), + maxXBorder(_maxXBorder), + maxYBorder(_maxYBorder), + pointsArr(_pointsArr), + oppPointsArr(_oppPointsArr), + partsDisplacementArr(_partsDisplacementArr), + scoreArr(_scoreArr), + kPointsArr(_kPointsArr), + levelsArr(_levelsArr), + scoreThreshold(_scoreThreshold), + oppPoints(_oppPoints) + {} + + + void operator() (const Range& range) const + { + + for( int i=range.start; i!=range.end; ++i ) + { + searchObjectThreshold(H, H_PCA, &(filters[componentIndex[i]]), kPartFilters[i], + b[i], maxXBorder, maxYBorder, scoreThreshold, + &(pointsArr[i]), &(levelsArr[i]), &(kPointsArr[i]), + &(scoreArr[i]), &(partsDisplacementArr[i])); + estimateBoxes(pointsArr[i], levelsArr[i], kPointsArr[i], + filters[componentIndex[i]]->sizeX, filters[componentIndex[i]]->sizeY, &(oppPointsArr[i])); + } + } +}; + +#endif +/* +// Computation root filters displacement and values of score function +// +// API +// int searchObjectThresholdSomeComponents(const featurePyramid *H, + const CvLSVMFilterObjectCaskade **filters, + int kComponents, const int *kPartFilters, + const float *b, float scoreThreshold, + CvPoint **points, CvPoint **oppPoints, + float **score, int *kPoints); +// INPUT +// H - feature pyramid +// filters - filters (root filter then it's part filters, etc.) +// kComponents - root filters number +// kPartFilters - array of part filters number for each component +// b - array of linear terms +// scoreThreshold - score threshold +// OUTPUT +// points - root filters displacement (top left corners) +// oppPoints - root filters displacement (bottom right corners) +// score - array of score values +// kPoints - number of boxes +// RESULT +// Error status +*/ +int searchObjectThresholdSomeComponents(const CvLSVMFeaturePyramidCaskade *H, + const CvLSVMFeaturePyramidCaskade *H_PCA, + const CvLSVMFilterObjectCaskade **filters, + int kComponents, const int *kPartFilters, + const float *b, float scoreThreshold, + CvPoint **points, CvPoint **oppPoints, + float **score, int *kPoints) +{ + int i, j, s, f, *componentIndex; + unsigned int maxXBorder, maxYBorder; + CvPoint **pointsArr, **oppPointsArr, ***partsDisplacementArr; + float **scoreArr; + int *kPointsArr, **levelsArr; + int sum; + + // Allocation memory + pointsArr = (CvPoint **)malloc(sizeof(CvPoint *) * kComponents); + oppPointsArr = (CvPoint **)malloc(sizeof(CvPoint *) * kComponents); + scoreArr = (float **)malloc(sizeof(float *) * kComponents); + kPointsArr = (int *)malloc(sizeof(int) * kComponents); + levelsArr = (int **)malloc(sizeof(int *) * kComponents); + partsDisplacementArr = (CvPoint ***)malloc(sizeof(CvPoint **) * kComponents); + componentIndex = (int *)malloc(sizeof(int) * kComponents); + + // Getting maximum filter dimensions + getMaxFilterDims(filters, kComponents, kPartFilters, &maxXBorder, &maxYBorder); + *kPoints = 0; + sum = 0; + componentIndex[0] = 0; + for (i = 1; i < kComponents; i++) + { + componentIndex[i] = componentIndex[i - 1] + (kPartFilters[i - 1] + 1); + } + // For each component perform searching +//#pragma omp parallel for schedule(dynamic) reduction(+ : sum) +#ifdef HAVE_TBB + PathOfModel POM( + componentIndex, + H, + H_PCA, + filters, + kPartFilters, + b, + maxXBorder, + maxYBorder, + pointsArr, + oppPointsArr, + partsDisplacementArr, + scoreArr, + kPointsArr, + levelsArr, + scoreThreshold, + oppPoints); + cv::parallel_for_( Range( 0, kComponents ), POM); +#else + for (i = 0; i < kComponents; i++) + { + searchObjectThreshold(H, H_PCA, &(filters[componentIndex[i]]), kPartFilters[i], + b[i], maxXBorder, maxYBorder, scoreThreshold, + &(pointsArr[i]), &(levelsArr[i]), &(kPointsArr[i]), + &(scoreArr[i]), &(partsDisplacementArr[i])); + estimateBoxes(pointsArr[i], levelsArr[i], kPointsArr[i], + filters[componentIndex[i]]->sizeX, filters[componentIndex[i]]->sizeY, &(oppPointsArr[i])); + } +#endif + for (i = 0; i < kComponents; i++) + { + //*kPoints += kPointsArr[i]; + sum += kPointsArr[i]; + } + *kPoints = sum; + *points = (CvPoint *)malloc(sizeof(CvPoint) * (*kPoints)); + *oppPoints = (CvPoint *)malloc(sizeof(CvPoint) * (*kPoints)); + *score = (float *)malloc(sizeof(float) * (*kPoints)); + + //file = fopen("point.txt", "w"); + s = 0; + for (i = 0; i < kComponents; i++) + { + f = s + kPointsArr[i]; + for (j = s; j < f; j++) + { + (*points)[j].x = pointsArr[i][j - s].x; + (*points)[j].y = pointsArr[i][j - s].y; + (*oppPoints)[j].x = oppPointsArr[i][j - s].x; + (*oppPoints)[j].y = oppPointsArr[i][j - s].y; + (*score)[j] = scoreArr[i][j - s]; + // fprintf(file, "%d %d %d %d %f\n", (*points)[j].x, (*points)[j].y, + // (*oppPoints)[j].x, (*oppPoints)[j].y, (*score)[j]); + } + s = f; + } + //fclose(file); + + // Release allocated memory + for (i = 0; i < kComponents; i++) + { + free(pointsArr[i]); + free(oppPointsArr[i]); + free(scoreArr[i]); + free(levelsArr[i]); + for (j = 0; j < kPointsArr[i]; j++) + { + free(partsDisplacementArr[i][j]); + } + free(partsDisplacementArr[i]); + } + free(pointsArr); + free(oppPointsArr); + free(scoreArr); + free(kPointsArr); + free(levelsArr); + free(partsDisplacementArr); + free(componentIndex); + return LATENT_SVM_OK; +} +} +} diff --git a/modules/latentsvm/src/lsvmc_latentsvmdetector.cpp b/modules/latentsvm/src/lsvmc_latentsvmdetector.cpp new file mode 100644 index 00000000000..e24495fb830 --- /dev/null +++ b/modules/latentsvm/src/lsvmc_latentsvmdetector.cpp @@ -0,0 +1,331 @@ +/*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) 2010-2013, University of Nizhny Novgorod, 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 "_lsvmc_parser.h" +#include "_lsvmc_matching.h" +namespace cv +{ +namespace lsvm +{ + +std::string extractModelName( const std::string& filename ); + +const int pca_size = 31; + +CvLatentSvmDetectorCaskade* cvLoadLatentSvmDetectorCaskade(const char* filename); +void cvReleaseLatentSvmDetectorCaskade(CvLatentSvmDetectorCaskade** detector); +CvSeq* cvLatentSvmDetectObjectsCaskade(IplImage* image, + CvLatentSvmDetectorCaskade* detector, + CvMemStorage* storage, + float overlap_threshold); + +/* +// load trained detector from a file +// +// API +// CvLatentSvmDetectorCaskade* cvLoadLatentSvmDetector(const char* filename); +// INPUT +// filename - path to the file containing the parameters of +// - trained Latent SVM detector +// OUTPUT +// trained Latent SVM detector in internal representation +*/ +CvLatentSvmDetectorCaskade* cvLoadLatentSvmDetectorCaskade(const char* filename) +{ + CvLatentSvmDetectorCaskade* detector = 0; + CvLSVMFilterObjectCaskade** filters = 0; + int kFilters = 0; + int kComponents = 0; + int* kPartFilters = 0; + float* b = 0; + float scoreThreshold = 0.f; + int err_code = 0; + float* PCAcoeff = 0; + + err_code = loadModel(filename, &filters, &kFilters, &kComponents, &kPartFilters, &b, &scoreThreshold, &PCAcoeff); + if (err_code != LATENT_SVM_OK) return 0; + + detector = (CvLatentSvmDetectorCaskade*)malloc(sizeof(CvLatentSvmDetectorCaskade)); + detector->filters = filters; + detector->b = b; + detector->num_components = kComponents; + detector->num_filters = kFilters; + detector->num_part_filters = kPartFilters; + detector->score_threshold = scoreThreshold; + detector->pca = PCAcoeff; + detector->pca_size = pca_size; + + return detector; +} + +/* +// release memory allocated for CvLatentSvmDetectorCaskade structure +// +// API +// void cvReleaseLatentSvmDetector(CvLatentSvmDetectorCaskade** detector); +// INPUT +// detector - CvLatentSvmDetectorCaskade structure to be released +// OUTPUT +*/ +void cvReleaseLatentSvmDetectorCaskade(CvLatentSvmDetectorCaskade** detector) +{ + free((*detector)->b); + free((*detector)->num_part_filters); + for (int i = 0; i < (*detector)->num_filters; i++) + { + free((*detector)->filters[i]->H); + free((*detector)->filters[i]); + } + free((*detector)->filters); + free((*detector)->pca); + free((*detector)); + *detector = 0; +} + +/* +// find rectangular regions in the given image that are likely +// to contain objects and corresponding confidence levels +// +// API +// CvSeq* cvLatentSvmDetectObjects(const IplImage* image, +// CvLatentSvmDetectorCaskade* detector, +// CvMemStorage* storage, +// float overlap_threshold = 0.5f); +// INPUT +// image - image to detect objects in +// detector - Latent SVM detector in internal representation +// storage - memory storage to store the resultant sequence +// of the object candidate rectangles +// overlap_threshold - threshold for the non-maximum suppression algorithm [here will be the reference to original paper] +// OUTPUT +// sequence of detected objects (bounding boxes and confidence levels stored in CvObjectDetection structures) +*/ +CvSeq* cvLatentSvmDetectObjectsCaskade(IplImage* image, + CvLatentSvmDetectorCaskade* detector, + CvMemStorage* storage, + float overlap_threshold) +{ + CvLSVMFeaturePyramidCaskade *H = 0; + CvLSVMFeaturePyramidCaskade *H_PCA = 0; + CvPoint *points = 0, *oppPoints = 0; + int kPoints = 0; + float *score = 0; + unsigned int maxXBorder = 0, maxYBorder = 0; + int numBoxesOut = 0; + CvPoint *pointsOut = 0; + CvPoint *oppPointsOut = 0; + float *scoreOut = 0; + CvSeq* result_seq = 0; + int error = 0; + + if(image->nChannels == 3) + cvCvtColor(image, image, CV_BGR2RGB); + + // Getting maximum filter dimensions + getMaxFilterDims((const CvLSVMFilterObjectCaskade**)(detector->filters), detector->num_components, + detector->num_part_filters, &maxXBorder, &maxYBorder); + // Create feature pyramid with nullable border + H = createFeaturePyramidWithBorder(image, maxXBorder, maxYBorder); + + // Create PSA feature pyramid + H_PCA = createPCA_FeaturePyramid(H, detector, maxXBorder, maxYBorder); + + FeaturePyramid32(H, maxXBorder, maxYBorder); + + // Search object + error = searchObjectThresholdSomeComponents(H, H_PCA,(const CvLSVMFilterObjectCaskade**)(detector->filters), + detector->num_components, detector->num_part_filters, detector->b, detector->score_threshold, + &points, &oppPoints, &score, &kPoints); + if (error != LATENT_SVM_OK) + { + return NULL; + } + // Clipping boxes + clippingBoxes(image->width, image->height, points, kPoints); + clippingBoxes(image->width, image->height, oppPoints, kPoints); + // NMS procedure + nonMaximumSuppression(kPoints, points, oppPoints, score, overlap_threshold, + &numBoxesOut, &pointsOut, &oppPointsOut, &scoreOut); + + result_seq = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvObjectDetection), storage ); + + for (int i = 0; i < numBoxesOut; i++) + { + CvObjectDetection detection; + detection.score = scoreOut[i]; + detection.rect.x = pointsOut[i].x; + detection.rect.y = pointsOut[i].y; + detection.rect.width = oppPointsOut[i].x - pointsOut[i].x; + detection.rect.height = oppPointsOut[i].y - pointsOut[i].y; + cvSeqPush(result_seq, &detection); + } + + if(image->nChannels == 3) + cvCvtColor(image, image, CV_RGB2BGR); + + freeFeaturePyramidObject(&H); + freeFeaturePyramidObject(&H_PCA); + free(points); + free(oppPoints); + free(score); + + return result_seq; +} + +class LSVMDetectorImpl : public LSVMDetector +{ +public: + + LSVMDetectorImpl( const std::vector& filenames, const std::vector& classNames=std::vector() ); + ~LSVMDetectorImpl(); + + bool isEmpty() const; + + void detect(cv::Mat const &image, CV_OUT std::vector& objects, float overlapThreshold=0.5f); + + const std::vector& getClassNames() const; + size_t getClassCount() const; + +private: + std::vector detectors; + std::vector classNames; +}; + +cv::Ptr LSVMDetector::create(std::vector const &filenames, + std::vector const &classNames) +{ + return cv::makePtr(filenames, classNames); +} + +LSVMDetectorImpl::ObjectDetection::ObjectDetection() : score(0.f), classID(-1) {} + +LSVMDetectorImpl::ObjectDetection::ObjectDetection( const Rect& _rect, float _score, int _classID ) : + rect(_rect), score(_score), classID(_classID) {} + + +LSVMDetectorImpl::LSVMDetectorImpl( const std::vector& filenames, const std::vector& _classNames ) +{ + for( size_t i = 0; i < filenames.size(); i++ ) + { + const std::string filename = filenames[i]; + if( filename.length() < 5 || filename.substr(filename.length()-4, 4) != ".xml" ) + continue; + + CvLatentSvmDetectorCaskade* detector = cvLoadLatentSvmDetectorCaskade( filename.c_str() ); + if( detector ) + { + detectors.push_back( detector ); + if( _classNames.empty() ) + { + classNames.push_back( extractModelName(filenames[i]) ); + } + else + classNames.push_back( _classNames[i] ); + } + } +} + +LSVMDetectorImpl::~LSVMDetectorImpl() +{ + for(size_t i = 0; i < detectors.size(); i++) + cv::lsvm::cvReleaseLatentSvmDetectorCaskade(&detectors[i]); +} + +bool LSVMDetectorImpl::isEmpty() const +{ + return detectors.empty(); +} + +const std::vector& LSVMDetectorImpl::getClassNames() const +{ + return classNames; +} + +size_t LSVMDetectorImpl::getClassCount() const +{ + return classNames.size(); +} + +std::string extractModelName( const std::string& filename ) +{ + size_t startPos = filename.rfind('/'); + if( startPos == std::string::npos ) + startPos = filename.rfind('\\'); + + if( startPos == std::string::npos ) + startPos = 0; + else + startPos++; + + const int extentionSize = 4; //.xml + + int substrLength = (int)(filename.size() - startPos - extentionSize); + + return filename.substr(startPos, substrLength); +} + +void LSVMDetectorImpl::detect( cv::Mat const &image, + std::vector &objectDetections, + float overlapThreshold) +{ + objectDetections.clear(); + + for( size_t classID = 0; classID < detectors.size(); classID++ ) + { + IplImage image_ipl = image; + CvMemStorage* storage = cvCreateMemStorage(0); + CvSeq* detections = cv::lsvm::cvLatentSvmDetectObjectsCaskade( &image_ipl, (CvLatentSvmDetectorCaskade*)(detectors[classID]), storage, overlapThreshold); + + // convert results + objectDetections.reserve( objectDetections.size() + detections->total ); + for( int detectionIdx = 0; detectionIdx < detections->total; detectionIdx++ ) + { + CvObjectDetection detection = *(CvObjectDetection*)cvGetSeqElem( detections, detectionIdx ); + objectDetections.push_back( ObjectDetection(Rect(detection.rect), detection.score, (int)classID) ); + } + + cvReleaseMemStorage( &storage ); + } +} + +} // namespace cv +} diff --git a/modules/latentsvm/src/lsvmc_matching.cpp b/modules/latentsvm/src/lsvmc_matching.cpp new file mode 100644 index 00000000000..3795d7e4a41 --- /dev/null +++ b/modules/latentsvm/src/lsvmc_matching.cpp @@ -0,0 +1,285 @@ +/*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) 2010-2013, University of Nizhny Novgorod, 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 "_lsvmc_matching.h" +#include + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif +namespace cv +{ +namespace lsvm +{ + +void sort(int n, const float* x, int* indices); + +/* +// Computation border size for feature map +// +// API +// int computeBorderSize(int maxXBorder, int maxYBorder, int *bx, int *by); +// INPUT +// maxXBorder - the largest root filter size (X-direction) +// maxYBorder - the largest root filter size (Y-direction) +// OUTPUT +// bx - border size (X-direction) +// by - border size (Y-direction) +// RESULT +// Error status +*/ +int computeBorderSize(int maxXBorder, int maxYBorder, int *bx, int *by) +{ + *bx = (int)ceilf(((float) maxXBorder) / 2.0f + 1.0f); + *by = (int)ceilf(((float) maxYBorder) / 2.0f + 1.0f); + return LATENT_SVM_OK; +} + +/* +// Addition nullable border to the feature map +// +// API +// int addNullableBorder(featureMap *map, int bx, int by); +// INPUT +// map - feature map +// bx - border size (X-direction) +// by - border size (Y-direction) +// OUTPUT +// RESULT +// Error status +*/ +int addNullableBorder(CvLSVMFeatureMapCaskade *map, int bx, int by) +{ + int sizeX, sizeY, i, j, k; + float *new_map; + sizeX = map->sizeX + 2 * bx; + sizeY = map->sizeY + 2 * by; + new_map = (float *)malloc(sizeof(float) * sizeX * sizeY * map->numFeatures); + for (i = 0; i < sizeX * sizeY * map->numFeatures; i++) + { + new_map[i] = 0.0; + } + for (i = by; i < map->sizeY + by; i++) + { + for (j = bx; j < map->sizeX + bx; j++) + { + for (k = 0; k < map->numFeatures; k++) + { + new_map[(i * sizeX + j) * map->numFeatures + k] = + map->map[((i - by) * map->sizeX + j - bx) * map->numFeatures + k]; + } + } + } + map->sizeX = sizeX; + map->sizeY = sizeY; + free(map->map); + map->map = new_map; + return LATENT_SVM_OK; +} + +/* +// Computation maximum filter size for each dimension +// +// API +// int getMaxFilterDims(const CvLSVMFilterObjectCaskade **filters, int kComponents, + const int *kPartFilters, + unsigned int *maxXBorder, unsigned int *maxYBorder); +// INPUT +// filters - a set of filters (at first root filter, then part filters + and etc. for all components) +// kComponents - number of components +// kPartFilters - number of part filters for each component +// OUTPUT +// maxXBorder - maximum of filter size at the horizontal dimension +// maxYBorder - maximum of filter size at the vertical dimension +// RESULT +// Error status +*/ +int getMaxFilterDims(const CvLSVMFilterObjectCaskade **filters, int kComponents, + const int *kPartFilters, + unsigned int *maxXBorder, unsigned int *maxYBorder) +{ + int i, componentIndex; + *maxXBorder = filters[0]->sizeX; + *maxYBorder = filters[0]->sizeY; + componentIndex = kPartFilters[0] + 1; + for (i = 1; i < kComponents; i++) + { + if (unsigned(filters[componentIndex]->sizeX) > *maxXBorder) + { + *maxXBorder = filters[componentIndex]->sizeX; + } + if (unsigned(filters[componentIndex]->sizeY) > *maxYBorder) + { + *maxYBorder = filters[componentIndex]->sizeY; + } + componentIndex += (kPartFilters[i] + 1); + } + return LATENT_SVM_OK; +} + +void sort(int n, const float* x, int* indices) +{ + int i, j; + for (i = 0; i < n; i++) + for (j = i + 1; j < n; j++) + { + if (x[indices[j]] > x[indices[i]]) + { + //float x_tmp = x[i]; + int index_tmp = indices[i]; + //x[i] = x[j]; + indices[i] = indices[j]; + //x[j] = x_tmp; + indices[j] = index_tmp; + } + } +} + +/* +// Perform non-maximum suppression algorithm (described in original paper) +// to remove "similar" bounding boxes +// +// API +// int nonMaximumSuppression(int numBoxes, const CvPoint *points, + const CvPoint *oppositePoints, const float *score, + float overlapThreshold, + int *numBoxesOut, CvPoint **pointsOut, + CvPoint **oppositePointsOut, float **scoreOut); +// INPUT +// numBoxes - number of bounding boxes +// points - array of left top corner coordinates +// oppositePoints - array of right bottom corner coordinates +// score - array of detection scores +// overlapThreshold - threshold: bounding box is removed if overlap part + is greater than passed value +// OUTPUT +// numBoxesOut - the number of bounding boxes algorithm returns +// pointsOut - array of left top corner coordinates +// oppositePointsOut - array of right bottom corner coordinates +// scoreOut - array of detection scores +// RESULT +// Error status +*/ +int nonMaximumSuppression(int numBoxes, const CvPoint *points, + const CvPoint *oppositePoints, const float *score, + float overlapThreshold, + int *numBoxesOut, CvPoint **pointsOut, + CvPoint **oppositePointsOut, float **scoreOut) +{ + int i, j, index; + float* box_area = (float*)malloc(numBoxes * sizeof(float)); + int* indices = (int*)malloc(numBoxes * sizeof(int)); + int* is_suppressed = (int*)malloc(numBoxes * sizeof(int)); + + for (i = 0; i < numBoxes; i++) + { + indices[i] = i; + is_suppressed[i] = 0; + box_area[i] = (float)( (oppositePoints[i].x - points[i].x + 1) * + (oppositePoints[i].y - points[i].y + 1)); + } + + sort(numBoxes, score, indices); + for (i = 0; i < numBoxes; i++) + { + if (!is_suppressed[indices[i]]) + { + for (j = i + 1; j < numBoxes; j++) + { + if (!is_suppressed[indices[j]]) + { + int x1max = max(points[indices[i]].x, points[indices[j]].x); + int x2min = min(oppositePoints[indices[i]].x, oppositePoints[indices[j]].x); + int y1max = max(points[indices[i]].y, points[indices[j]].y); + int y2min = min(oppositePoints[indices[i]].y, oppositePoints[indices[j]].y); + int overlapWidth = x2min - x1max + 1; + int overlapHeight = y2min - y1max + 1; + if (overlapWidth > 0 && overlapHeight > 0) + { + float overlapPart = (overlapWidth * overlapHeight) / box_area[indices[j]]; + if (overlapPart > overlapThreshold) + { + is_suppressed[indices[j]] = 1; + } + } + } + } + } + } + + *numBoxesOut = 0; + for (i = 0; i < numBoxes; i++) + { + if (!is_suppressed[i]) (*numBoxesOut)++; + } + + *pointsOut = (CvPoint *)malloc((*numBoxesOut) * sizeof(CvPoint)); + *oppositePointsOut = (CvPoint *)malloc((*numBoxesOut) * sizeof(CvPoint)); + *scoreOut = (float *)malloc((*numBoxesOut) * sizeof(float)); + index = 0; + for (i = 0; i < numBoxes; i++) + { + if (!is_suppressed[indices[i]]) + { + (*pointsOut)[index].x = points[indices[i]].x; + (*pointsOut)[index].y = points[indices[i]].y; + (*oppositePointsOut)[index].x = oppositePoints[indices[i]].x; + (*oppositePointsOut)[index].y = oppositePoints[indices[i]].y; + (*scoreOut)[index] = score[indices[i]]; + index++; + } + + } + + free(indices); + free(box_area); + free(is_suppressed); + + return LATENT_SVM_OK; +} +} +} diff --git a/modules/latentsvm/src/lsvmc_parser.cpp b/modules/latentsvm/src/lsvmc_parser.cpp new file mode 100644 index 00000000000..b606b4f3112 --- /dev/null +++ b/modules/latentsvm/src/lsvmc_parser.cpp @@ -0,0 +1,1113 @@ +/*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) 2010-2013, University of Nizhny Novgorod, 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 +#include "string.h" +#include "_lsvmc_parser.h" +#include "_lsvmc_error.h" + +namespace cv +{ +namespace lsvm +{ + +int isMODEL (char *str); +int isP (char *str); +int isSCORE (char *str); +int isCOMP (char *str); +int isRFILTER (char *str); +int isPFILTERs (char *str); +int isPFILTER (char *str); +int isSIZEX (char *str); +int isSIZEY (char *str); +int isWEIGHTS (char *str); +int isV (char *str); +int isVx (char *str); +int isVy (char *str); +int isD (char *str); +int isDx (char *str); +int isDy (char *str); +int isDxx (char *str); +int isDyy (char *str); +int isB (char *str); +int isWEIGHTS_PCA (char *str); +int isPCA (char *str); +int isPCAcoeff (char *str); +int isCASCADE_Th (char *str); +int isHYPOTHES_PCA (char *str); +int isDEFORM_PCA (char *str); +int isHYPOTHES (char *str); +int isDEFORM (char *str); +int getTeg (char *str); + +void addFilter(CvLSVMFilterObjectCaskade *** model, int *last, int *max); + +void parserCascadeThresholds (FILE * xmlf, CvLSVMFilterObjectCaskade * model); + +void parserRFilter (FILE * xmlf, int p, int pca, CvLSVMFilterObjectCaskade * model, float *b); + +void parserV (FILE * xmlf, int /*p*/, CvLSVMFilterObjectCaskade * model); + +void parserD (FILE * xmlf, int /*p*/, CvLSVMFilterObjectCaskade * model); + +void parserPFilter (FILE * xmlf, int p, int pca, int /*N_path*/, CvLSVMFilterObjectCaskade * model); + +void parserPFilterS (FILE * xmlf, int p, int pca, CvLSVMFilterObjectCaskade *** model, int *last, int *max); + +void parserComp (FILE * xmlf, int p, int pca, int *N_comp, CvLSVMFilterObjectCaskade *** model, float *b, int *last, int *max); + +void parserModel(FILE * xmlf, CvLSVMFilterObjectCaskade *** model, int *last, int *max, int **comp, float **b, int *count, float * score, float** PCAcoeff); + +void LSVMparser(const char * filename, + CvLSVMFilterObjectCaskade *** model, + int *last, + int *max, + int **comp, + float **b, + int *count, + float * score, + float** PCAcoeff); + +int isMODEL (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return MODEL; + if(strcmp(etag, str) == 0)return EMODEL; + return 0; +} +int isP (char *str){ + char stag [] = "

"; + char etag [] = "

"; + if(strcmp(stag, str) == 0)return P; + if(strcmp(etag, str) == 0)return EP; + return 0; +} +int isSCORE (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return SCORE; + if(strcmp(etag, str) == 0)return ESCORE; + return 0; +} +int isCOMP (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return COMP; + if(strcmp(etag, str) == 0)return ECOMP; + return 0; +} +int isRFILTER (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return RFILTER; + if(strcmp(etag, str) == 0)return ERFILTER; + return 0; +} +int isPFILTERs (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return PFILTERs; + if(strcmp(etag, str) == 0)return EPFILTERs; + return 0; +} +int isPFILTER (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return PFILTER; + if(strcmp(etag, str) == 0)return EPFILTER; + return 0; +} +int isSIZEX (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return SIZEX; + if(strcmp(etag, str) == 0)return ESIZEX; + return 0; +} +int isSIZEY (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return SIZEY; + if(strcmp(etag, str) == 0)return ESIZEY; + return 0; +} +int isWEIGHTS (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return WEIGHTS; + if(strcmp(etag, str) == 0)return EWEIGHTS; + return 0; +} +int isV (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return TAGV; + if(strcmp(etag, str) == 0)return ETAGV; + return 0; +} +int isVx (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return Vx; + if(strcmp(etag, str) == 0)return EVx; + return 0; +} +int isVy (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return Vy; + if(strcmp(etag, str) == 0)return EVy; + return 0; +} +int isD (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return TAGD; + if(strcmp(etag, str) == 0)return ETAGD; + return 0; +} +int isDx (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return Dx; + if(strcmp(etag, str) == 0)return EDx; + return 0; +} +int isDy (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return Dy; + if(strcmp(etag, str) == 0)return EDy; + return 0; +} +int isDxx (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return Dxx; + if(strcmp(etag, str) == 0)return EDxx; + return 0; +} +int isDyy (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return Dyy; + if(strcmp(etag, str) == 0)return EDyy; + return 0; +} +int isB (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return BTAG; + if(strcmp(etag, str) == 0)return EBTAG; + return 0; +} + +int isWEIGHTS_PCA (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return WEIGHTSPCA; + if(strcmp(etag, str) == 0)return EWEIGHTSPCA; + return 0; +} + +int isPCA (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return PCA; + if(strcmp(etag, str) == 0)return EPCA; + return 0; +} + +int isPCAcoeff (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return PCACOEFF; + if(strcmp(etag, str) == 0)return EPCACOEFF; + return 0; +} + +int isCASCADE_Th (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return CASCADE_Th; + if(strcmp(etag, str) == 0)return ECASCADE_Th; + return 0; +} + +int isHYPOTHES_PCA (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return HYPOTHES_PCA; + if(strcmp(etag, str) == 0)return EHYPOTHES_PCA; + return 0; +} +int isDEFORM_PCA (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return DEFORM_PCA; + if(strcmp(etag, str) == 0)return EDEFORM_PCA; + return 0; +} +int isHYPOTHES (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return HYPOTHES; + if(strcmp(etag, str) == 0)return EHYPOTHES; + return 0; +} +int isDEFORM (char *str){ + char stag [] = ""; + char etag [] = ""; + if(strcmp(stag, str) == 0)return DEFORM; + if(strcmp(etag, str) == 0)return EDEFORM; + return 0; +} + +int getTeg(char *str){ + int sum = 0; + sum = isMODEL (str)+ + isP (str)+ + isSCORE (str)+ + isCOMP (str)+ + isRFILTER (str)+ + isPFILTERs (str)+ + isPFILTER (str)+ + isSIZEX (str)+ + isSIZEY (str)+ + isWEIGHTS (str)+ + isV (str)+ + isVx (str)+ + isVy (str)+ + isD (str)+ + isDx (str)+ + isDy (str)+ + isDxx (str)+ + isDyy (str)+ + isB (str)+ + isPCA (str)+ + isCASCADE_Th (str)+ + isHYPOTHES_PCA(str)+ + isDEFORM_PCA (str)+ + isHYPOTHES (str)+ + isDEFORM (str)+ + isWEIGHTS_PCA (str)+ + isPCAcoeff (str) + ; + + return sum; +} + +void addFilter(CvLSVMFilterObjectCaskade *** model, int *last, int *max) +{ + CvLSVMFilterObjectCaskade ** nmodel; + int i; + (*last) ++; + if((*last) >= (*max)){ + (*max) += 10; + nmodel = (CvLSVMFilterObjectCaskade **)malloc(sizeof(CvLSVMFilterObjectCaskade *) * (*max)); + for(i = 0; i < *last; i++){ + nmodel[i] = (* model)[i]; + } + free(* model); + (*model) = nmodel; + } + (*model) [(*last)] = (CvLSVMFilterObjectCaskade *)malloc(sizeof(CvLSVMFilterObjectCaskade)); + (*model) [(*last)]->Hypothesis = 0.0f; + (*model) [(*last)]->Deformation = 0.0f; + (*model) [(*last)]->Hypothesis_PCA = 0.0f; + (*model) [(*last)]->Deformation_PCA = 0.0f; + +} + +//############################################## +void parserCascadeThresholds (FILE * xmlf, CvLSVMFilterObjectCaskade * model){ + int st = 0; + int tag; + int tagVal; + char ch; + int i,j; + char buf[1024]; + char tagBuf[1024]; + + i = 0; + j = 0; + st = 0; + tag = 0; + while(!feof(xmlf)){ + ch = (char) fgetc( xmlf ); + if(ch == '<'){ + tag = 1; + j = 1; + tagBuf[j - 1] = ch; + }else { + if(ch == '>'){ + tagBuf[j ] = ch; + tagBuf[j + 1] = '\0'; + + tagVal = getTeg(tagBuf); + + if(tagVal == ECASCADE_Th){ + return; + } + if(tagVal == HYPOTHES_PCA){ + st = 1; + i = 0; + } + if(tagVal == EHYPOTHES_PCA){ + st = 0; + buf[i] = '\0'; + model->Hypothesis_PCA =(float) atof(buf); + } + if(tagVal == DEFORM_PCA){ + st = 1; + i = 0; + } + if(tagVal == EDEFORM_PCA){ + st = 0; + buf[i] = '\0'; + model->Deformation_PCA =(float) atof(buf); + } + if(tagVal == HYPOTHES){ + st = 1; + i = 0; + } + if(tagVal == EHYPOTHES){ + st = 0; + buf[i] = '\0'; + model->Hypothesis = (float)atof(buf); + } + if(tagVal == DEFORM){ + st = 1; + i = 0; + } + if(tagVal == EDEFORM){ + st = 0; + buf[i] = '\0'; + model->Deformation = (float)atof(buf); + } + tag = 0; + i = 0; + }else{ + if((tag == 0)&& (st == 1)){ + buf[i] = ch; i++; + }else{ + tagBuf[j] = ch; j++; + } + } + } + } +} +//############################################## + +void parserRFilter (FILE * xmlf, int p, int pca, CvLSVMFilterObjectCaskade * model, float *b){ + int st = 0; + int sizeX = 0, sizeY = 0; + int tag; + int tagVal; + char ch; + int i,j,ii; + char buf[1024]; + char tagBuf[1024]; + double *data; + //printf("\n"); + + model->V.x = 0; + model->V.y = 0; + model->V.l = 0; + model->fineFunction[0] = 0.0; + model->fineFunction[1] = 0.0; + model->fineFunction[2] = 0.0; + model->fineFunction[3] = 0.0; + + i = 0; + j = 0; + st = 0; + tag = 0; + while(!feof(xmlf)){ + ch = (char)fgetc( xmlf ); + if(ch == '<'){ + tag = 1; + j = 1; + tagBuf[j - 1] = ch; + }else { + if(ch == '>'){ + tagBuf[j ] = ch; + tagBuf[j + 1] = '\0'; + + tagVal = getTeg(tagBuf); + + if(tagVal == ERFILTER){ + //printf("\n"); + return; + } + if(tagVal == SIZEX){ + st = 1; + i = 0; + } + if(tagVal == ESIZEX){ + st = 0; + buf[i] = '\0'; + sizeX = atoi(buf); + model->sizeX = sizeX; + //printf("%d\n", sizeX); + } + if(tagVal == SIZEY){ + st = 1; + i = 0; + } + if(tagVal == ESIZEY){ + st = 0; + buf[i] = '\0'; + sizeY = atoi(buf); + model->sizeY = sizeY; + //printf("%d\n", sizeY); + } + if(tagVal == WEIGHTS){ + data = (double *)malloc( sizeof(double) * p * sizeX * sizeY); + CV_Assert(fread(data, sizeof(double), p * sizeX * sizeY, xmlf)); + model->H = (float *)malloc(sizeof(float)* p * sizeX * sizeY); + for(ii = 0; ii < p * sizeX * sizeY; ii++){ + model->H[ii] = (float)data[ii]; + } + free(data); + } + if(tagVal == WEIGHTSPCA){ + data = (double *)malloc( sizeof(double) * pca * sizeX * sizeY); + CV_Assert(fread(data, sizeof(double), pca * sizeX * sizeY, xmlf)); + model->H_PCA = (float *)malloc(sizeof(float)* pca * sizeX * sizeY); + for(ii = 0; ii < pca * sizeX * sizeY; ii++){ + model->H_PCA[ii] = (float)data[ii]; + } + free(data); + } + + if(tagVal == CASCADE_Th){ + parserCascadeThresholds (xmlf, model); + } + + if(tagVal == BTAG){ + st = 1; + i = 0; + } + if(tagVal == EBTAG){ + st = 0; + buf[i] = '\0'; + *b =(float) atof(buf); + //printf("%f\n", *b); + } + + tag = 0; + i = 0; + }else{ + if((tag == 0)&& (st == 1)){ + buf[i] = ch; i++; + }else{ + tagBuf[j] = ch; j++; + } + } + } + } +} + +void parserV (FILE * xmlf, int /*p*/, CvLSVMFilterObjectCaskade * model){ + int st = 0; + int tag; + int tagVal; + char ch; + int i,j; + char buf[1024]; + char tagBuf[1024]; + //printf(" \n"); + + i = 0; + j = 0; + st = 0; + tag = 0; + while(!feof(xmlf)){ + ch = (char) fgetc( xmlf ); + if(ch == '<'){ + tag = 1; + j = 1; + tagBuf[j - 1] = ch; + }else { + if(ch == '>'){ + tagBuf[j ] = ch; + tagBuf[j + 1] = '\0'; + + tagVal = getTeg(tagBuf); + + if(tagVal == ETAGV){ + //printf(" \n"); + return; + } + if(tagVal == Vx){ + st = 1; + i = 0; + } + if(tagVal == EVx){ + st = 0; + buf[i] = '\0'; + model->V.x = atoi(buf); + //printf(" %d\n", model->V.x); + } + if(tagVal == Vy){ + st = 1; + i = 0; + } + if(tagVal == EVy){ + st = 0; + buf[i] = '\0'; + model->V.y = atoi(buf); + //printf(" %d\n", model->V.y); + } + tag = 0; + i = 0; + }else{ + if((tag == 0)&& (st == 1)){ + buf[i] = ch; i++; + }else{ + tagBuf[j] = ch; j++; + } + } + } + } +} +void parserD (FILE * xmlf, int /*p*/, CvLSVMFilterObjectCaskade * model){ + int st = 0; + int tag; + int tagVal; + char ch; + int i,j; + char buf[1024]; + char tagBuf[1024]; + //printf(" \n"); + + i = 0; + j = 0; + st = 0; + tag = 0; + while(!feof(xmlf)){ + ch = (char)fgetc( xmlf ); + if(ch == '<'){ + tag = 1; + j = 1; + tagBuf[j - 1] = ch; + }else { + if(ch == '>'){ + tagBuf[j ] = ch; + tagBuf[j + 1] = '\0'; + + tagVal = getTeg(tagBuf); + + if(tagVal == ETAGD){ + //printf(" \n"); + return; + } + if(tagVal == Dx){ + st = 1; + i = 0; + } + if(tagVal == EDx){ + st = 0; + buf[i] = '\0'; + + model->fineFunction[0] = (float)atof(buf); + //printf(" %f\n", model->fineFunction[0]); + } + if(tagVal == Dy){ + st = 1; + i = 0; + } + if(tagVal == EDy){ + st = 0; + buf[i] = '\0'; + + model->fineFunction[1] = (float)atof(buf); + //printf(" %f\n", model->fineFunction[1]); + } + if(tagVal == Dxx){ + st = 1; + i = 0; + } + if(tagVal == EDxx){ + st = 0; + buf[i] = '\0'; + + model->fineFunction[2] = (float)atof(buf); + //printf(" %f\n", model->fineFunction[2]); + } + if(tagVal == Dyy){ + st = 1; + i = 0; + } + if(tagVal == EDyy){ + st = 0; + buf[i] = '\0'; + + model->fineFunction[3] = (float)atof(buf); + //printf(" %f\n", model->fineFunction[3]); + } + + tag = 0; + i = 0; + }else{ + if((tag == 0)&& (st == 1)){ + buf[i] = ch; i++; + }else{ + tagBuf[j] = ch; j++; + } + } + } + } +} + +void parserPFilter (FILE * xmlf, int p, int pca, int /*N_path*/, CvLSVMFilterObjectCaskade * model){ + int st = 0; + int sizeX = 0, sizeY = 0; + int tag; + int tagVal; + char ch; + int i,j, ii; + char buf[1024]; + char tagBuf[1024]; + double *data; + //printf(" (%d)\n", N_path); + + model->V.x = 0; + model->V.y = 0; + model->V.l = 0; + model->fineFunction[0] = 0.0f; + model->fineFunction[1] = 0.0f; + model->fineFunction[2] = 0.0f; + model->fineFunction[3] = 0.0f; + + i = 0; + j = 0; + st = 0; + tag = 0; + while(!feof(xmlf)){ + ch = (char)fgetc( xmlf ); + if(ch == '<'){ + tag = 1; + j = 1; + tagBuf[j - 1] = ch; + }else { + if(ch == '>'){ + tagBuf[j ] = ch; + tagBuf[j + 1] = '\0'; + + tagVal = getTeg(tagBuf); + + if(tagVal == EPFILTER){ + //printf("\n"); + return; + } + + if(tagVal == TAGV){ + parserV(xmlf, p, model); + } + if(tagVal == TAGD){ + parserD(xmlf, p, model); + } + if(tagVal == SIZEX){ + st = 1; + i = 0; + } + if(tagVal == ESIZEX){ + st = 0; + buf[i] = '\0'; + sizeX = atoi(buf); + model->sizeX = sizeX; + //printf("%d\n", sizeX); + } + if(tagVal == SIZEY){ + st = 1; + i = 0; + } + if(tagVal == ESIZEY){ + st = 0; + buf[i] = '\0'; + sizeY = atoi(buf); + model->sizeY = sizeY; + //printf("%d\n", sizeY); + } + if(tagVal == WEIGHTS){ + data = (double *)malloc( sizeof(double) * p * sizeX * sizeY); + CV_Assert(fread(data, sizeof(double), p * sizeX * sizeY, xmlf)); + model->H = (float *)malloc(sizeof(float)* p * sizeX * sizeY); + for(ii = 0; ii < p * sizeX * sizeY; ii++){ + model->H[ii] = (float)data[ii]; + } + free(data); + } + if(tagVal == WEIGHTSPCA){ + data = (double *)malloc( sizeof(double) * pca * sizeX * sizeY); + CV_Assert(fread(data, sizeof(double), pca * sizeX * sizeY, xmlf)); + model->H_PCA = (float *)malloc(sizeof(float)* pca * sizeX * sizeY); + for(ii = 0; ii < pca * sizeX * sizeY; ii++){ + model->H_PCA[ii] = (float)data[ii]; + } + free(data); + } + if(tagVal == CASCADE_Th){ + parserCascadeThresholds (xmlf, model); + } + if(tagVal == EWEIGHTS){ + //printf("WEIGHTS OK\n"); + } + tag = 0; + i = 0; + }else{ + if((tag == 0)&& (st == 1)){ + buf[i] = ch; i++; + }else{ + tagBuf[j] = ch; j++; + } + } + } + } +} +void parserPFilterS (FILE * xmlf, int p, int pca, CvLSVMFilterObjectCaskade *** model, int *last, int *max){ + int st = 0; + int N_path = 0; + int tag; + int tagVal; + char ch; + int j; + char tagBuf[1024]; + //printf("\n"); + + j = 0; + st = 0; + tag = 0; + while(!feof(xmlf)){ + ch = (char)fgetc( xmlf ); + if(ch == '<'){ + tag = 1; + j = 1; + tagBuf[j - 1] = ch; + }else { + if(ch == '>'){ + tagBuf[j ] = ch; + tagBuf[j + 1] = '\0'; + + tagVal = getTeg(tagBuf); + + if(tagVal == EPFILTERs){ + //printf("\n"); + return; + } + if(tagVal == PFILTER){ + addFilter(model, last, max); + parserPFilter (xmlf, p, pca, N_path, (*model)[*last]); + N_path++; + } + tag = 0; + }else{ + if((tag != 0) || (st != 1)){ + tagBuf[j] = ch; j++; + } + } + } + } +} +void parserComp (FILE * xmlf, int p, int pca, int *N_comp, CvLSVMFilterObjectCaskade *** model, float *b, int *last, int *max){ + int st = 0; + int tag; + int tagVal; + char ch; + int j; + char tagBuf[1024]; + //printf(" %d\n", *N_comp); + + j = 0; + st = 0; + tag = 0; + while(!feof(xmlf)){ + ch = (char)fgetc( xmlf ); + if(ch == '<'){ + tag = 1; + j = 1; + tagBuf[j - 1] = ch; + }else { + if(ch == '>'){ + tagBuf[j ] = ch; + tagBuf[j + 1] = '\0'; + + tagVal = getTeg(tagBuf); + + if(tagVal == ECOMP){ + (*N_comp) ++; + return; + } + if(tagVal == RFILTER){ + addFilter(model, last, max); + parserRFilter (xmlf, p, pca, (*model)[*last],b); + } + if(tagVal == PFILTERs){ + parserPFilterS (xmlf, p, pca, model, last, max); + } + tag = 0; + }else{ + if((tag != 0) || (st != 1)){ + tagBuf[j] = ch; j++; + } + } + } + } +} +void parserModel(FILE * xmlf, CvLSVMFilterObjectCaskade *** model, int *last, int *max, int **comp, float **b, int *count, float * score, float** PCAcoeff){ + int p = 0, pca = 0; + int N_comp = 0; + int * cmp; + float *bb; + int st = 0; + int tag; + int tagVal; + char ch; + int i,j, ii = 0, jj; + char buf[1024]; + char tagBuf[1024]; + double *data; + //printf("\n"); + + i = 0; + j = 0; + st = 0; + tag = 0; + while(!feof(xmlf)){ + ch = (char)fgetc( xmlf ); + if(ch == '<'){ + tag = 1; + j = 1; + tagBuf[j - 1] = ch; + }else { + if(ch == '>'){ + tagBuf[j ] = ch; + tagBuf[j + 1] = '\0'; + + tagVal = getTeg(tagBuf); + + if(tagVal == EMODEL){ + //printf("\n"); + for(ii = 0; ii <= *last; ii++){ + (*model)[ii]->numFeatures = p; + } + * count = N_comp; + return; + } + if(tagVal == COMP){ + if(N_comp == 0){ + cmp = (int *)malloc(sizeof(int)); + bb = (float *)malloc(sizeof(float)); + * comp = cmp; + * b = bb; + * count = N_comp + 1; + } else { + cmp = (int *)malloc(sizeof(int) * (N_comp + 1)); + bb = (float *)malloc(sizeof(float) * (N_comp + 1)); + for(ii = 0; ii < N_comp; ii++){ + cmp[ii] = (* comp)[ii]; + bb [ii] = (* b )[ii]; + } + free(* comp); + free(* b ); + * comp = cmp; + * b = bb; + * count = N_comp + 1; + } + parserComp(xmlf, p, pca, &N_comp, model, &((*b)[N_comp]), last, max); + cmp[N_comp - 1] = *last; + } + if(tagVal == P){ + st = 1; + i = 0; + } + if(tagVal == EP){ + st = 0; + buf[i] = '\0'; + p = atoi(buf); + //printf("

%d

\n", p); + } + if(tagVal == PCA){ + st = 1; + i = 0; + } + if(tagVal == EPCA){ + st = 0; + buf[i] = '\0'; + pca = atoi(buf); + //printf("%d\n", p); + } + if(tagVal == SCORE){ + st = 1; + i = 0; + } + if(tagVal == PCACOEFF){ + st = 0; + i = 0; + p--; + data = (double *)malloc( sizeof(double) * p * p); + (*PCAcoeff) = (float *)malloc( sizeof(float) * p * p); + CV_Assert(fread(data, sizeof(double), p * p, xmlf)); + for(jj = 0; jj < p * p; jj++){ + (*PCAcoeff)[jj] = (float)data[jj]; + } + free(data); + p++; + } + if(tagVal == EPCACOEFF){ + st = 0; + //printf("%d\n", p); + } + if(tagVal == SCORE){ + st = 1; + i = 0; + } + if(tagVal == ESCORE){ + st = 0; + buf[i] = '\0'; + *score = (float)atof(buf); + //printf("%f\n", score); + } + tag = 0; + i = 0; + }else{ + if((tag == 0)&& (st == 1)){ + buf[i] = ch; i++; + }else{ + tagBuf[j] = ch; j++; + } + } + } + } +} + +void LSVMparser(const char * filename, + CvLSVMFilterObjectCaskade *** model, + int *last, + int *max, + int **comp, + float **b, + int *count, + float * score, + float** PCAcoeff) +{ + int tag; + char ch; + int j; + FILE *xmlf; + char tagBuf[1024]; + + (*max) = 10; + (*last) = -1; + (*model) = (CvLSVMFilterObjectCaskade ** )malloc((sizeof(CvLSVMFilterObjectCaskade * )) * (*max)); + + //printf("parse : %s\n", filename); + xmlf = fopen(filename, "rb"); + + j = 0; + tag = 0; + while(!feof(xmlf)){ + ch = (char) fgetc( xmlf ); + if(ch == '<'){ + tag = 1; + j = 1; + tagBuf[j - 1] = ch; + }else { + if(ch == '>'){ + tag = 0; + tagBuf[j ] = ch; + tagBuf[j + 1] = '\0'; + if(getTeg(tagBuf) == MODEL){ + parserModel(xmlf, model, last, max, comp, b, count, score, PCAcoeff); + } + }else{ + if(tag != 0) + { + tagBuf[j] = ch; j++; + } + } + } + } + fclose(xmlf); +} + +int loadModel( + const char *modelPath, + + CvLSVMFilterObjectCaskade ***filters, + int *kFilters, + int *kComponents, + int **kPartFilters, + float **b, + float *scoreThreshold, + float ** PCAcoeff){ + int last; + int max; + int *comp; + int count; + int i; + float score; + + LSVMparser(modelPath, filters, &last, &max, &comp, b, &count, &score, PCAcoeff); + (*kFilters) = last + 1; + (*kComponents) = count; + (*scoreThreshold) = (float) score; + + (*kPartFilters) = (int *)malloc(sizeof(int) * count); + + for(i = 1; i < count;i++){ + (*kPartFilters)[i] = (comp[i] - comp[i - 1]) - 1; + } + (*kPartFilters)[0] = comp[0]; + + + for(i = 0; i < (*kFilters);i++){ + (*(filters))[i]->deltaX = 5;// maxX; + (*(filters))[i]->deltaY = 5;// maxY; + } + + return 0; +} +} +} diff --git a/modules/latentsvm/src/lsvmc_resizeimg.cpp b/modules/latentsvm/src/lsvmc_resizeimg.cpp new file mode 100644 index 00000000000..0fcd503d747 --- /dev/null +++ b/modules/latentsvm/src/lsvmc_resizeimg.cpp @@ -0,0 +1,71 @@ +/*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) 2010-2013, University of Nizhny Novgorod, 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 "_lsvmc_resizeimg.h" +#include +#include +#include + +namespace cv +{ +namespace lsvm +{ + +IplImage* resize_opencv(IplImage* img, float scale) +{ + IplImage* imgTmp; + + int W, H, tW, tH; + + W = img->width; + H = img->height; + + tW = (int)(((float)W) * scale + 0.5); + tH = (int)(((float)H) * scale + 0.5); + + imgTmp = cvCreateImage(cvSize(tW , tH), img->depth, img->nChannels); + cvResize(img, imgTmp, CV_INTER_AREA); + + return imgTmp; +} +} +} diff --git a/modules/latentsvm/src/lsvmc_routine.cpp b/modules/latentsvm/src/lsvmc_routine.cpp new file mode 100644 index 00000000000..1c7152c9fb0 --- /dev/null +++ b/modules/latentsvm/src/lsvmc_routine.cpp @@ -0,0 +1,129 @@ +/*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) 2010-2013, University of Nizhny Novgorod, 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 "_lsvmc_routine.h" +namespace cv +{ +namespace lsvm +{ +int allocFilterObject(CvLSVMFilterObjectCaskade **obj, const int sizeX, + const int sizeY, const int numFeatures) +{ + int i; + (*obj) = (CvLSVMFilterObjectCaskade *)malloc(sizeof(CvLSVMFilterObjectCaskade)); + (*obj)->sizeX = sizeX; + (*obj)->sizeY = sizeY; + (*obj)->numFeatures = numFeatures; + (*obj)->fineFunction[0] = 0.0f; + (*obj)->fineFunction[1] = 0.0f; + (*obj)->fineFunction[2] = 0.0f; + (*obj)->fineFunction[3] = 0.0f; + (*obj)->V.x = 0; + (*obj)->V.y = 0; + (*obj)->V.l = 0; + (*obj)->H = (float *) malloc(sizeof (float) * + (sizeX * sizeY * numFeatures)); + for(i = 0; i < sizeX * sizeY * numFeatures; i++) + { + (*obj)->H[i] = 0.0f; + } + return LATENT_SVM_OK; +} +int freeFilterObject (CvLSVMFilterObjectCaskade **obj) +{ + if(*obj == NULL) return LATENT_SVM_MEM_NULL; + free((*obj)->H); + free(*obj); + (*obj) = NULL; + return LATENT_SVM_OK; +} + +int allocFeatureMapObject(CvLSVMFeatureMapCaskade **obj, const int sizeX, + const int sizeY, const int numFeatures) +{ + int i; + (*obj) = (CvLSVMFeatureMapCaskade *)malloc(sizeof(CvLSVMFeatureMapCaskade)); + (*obj)->sizeX = sizeX; + (*obj)->sizeY = sizeY; + (*obj)->numFeatures = numFeatures; + (*obj)->map = (float *) malloc(sizeof (float) * + (sizeX * sizeY * numFeatures)); + for(i = 0; i < sizeX * sizeY * numFeatures; i++) + { + (*obj)->map[i] = 0.0f; + } + return LATENT_SVM_OK; +} +int freeFeatureMapObject (CvLSVMFeatureMapCaskade **obj) +{ + if(*obj == NULL) return LATENT_SVM_MEM_NULL; + free((*obj)->map); + free(*obj); + (*obj) = NULL; + return LATENT_SVM_OK; +} + +int allocFeaturePyramidObject(CvLSVMFeaturePyramidCaskade **obj, + const int numLevels) +{ + (*obj) = (CvLSVMFeaturePyramidCaskade *)malloc(sizeof(CvLSVMFeaturePyramidCaskade)); + (*obj)->numLevels = numLevels; + (*obj)->pyramid = (CvLSVMFeatureMapCaskade **)malloc( + sizeof(CvLSVMFeatureMapCaskade *) * numLevels); + return LATENT_SVM_OK; +} + +int freeFeaturePyramidObject (CvLSVMFeaturePyramidCaskade **obj) +{ + int i; + if(*obj == NULL) return LATENT_SVM_MEM_NULL; + for(i = 0; i < (*obj)->numLevels; i++) + { + freeFeatureMapObject(&((*obj)->pyramid[i])); + } + free((*obj)->pyramid); + free(*obj); + (*obj) = NULL; + return LATENT_SVM_OK; +} +} +} diff --git a/modules/latentsvm/src/precomp.cpp b/modules/latentsvm/src/precomp.cpp new file mode 100644 index 00000000000..e65b780222b --- /dev/null +++ b/modules/latentsvm/src/precomp.cpp @@ -0,0 +1,44 @@ +/*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) 2010-2013, University of Nizhny Novgorod, 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" + +/* End of file. */ diff --git a/modules/latentsvm/src/precomp.hpp b/modules/latentsvm/src/precomp.hpp new file mode 100644 index 00000000000..53a5686f486 --- /dev/null +++ b/modules/latentsvm/src/precomp.hpp @@ -0,0 +1,67 @@ +/*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) 2010-2013, University of Nizhny Novgorod, 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*/ + +#ifndef __OPENCV_PRECOMP_H__ +#define __OPENCV_PRECOMP_H__ + +#ifdef HAVE_CVCONFIG_H +#include "cvconfig.h" +#endif + +#ifdef __cplusplus +#include +#include +#endif + +#include "opencv2/latentsvm.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/imgproc/imgproc_c.h" +#include "opencv2/core/core_c.h" + +#include "opencv2/opencv_modules.hpp" +#include "opencv2/highgui/highgui_c.h" + + +#ifdef HAVE_TEGRA_OPTIMIZATION +#include "opencv2/objdetect/objdetect_tegra.hpp" +#endif + +#endif diff --git a/modules/latentsvm/test/test_latentsvmdetector_cascade.cpp b/modules/latentsvm/test/test_latentsvmdetector_cascade.cpp new file mode 100644 index 00000000000..a819dd3d97f --- /dev/null +++ b/modules/latentsvm/test/test_latentsvmdetector_cascade.cpp @@ -0,0 +1,217 @@ +/*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 "test_precomp.hpp" + +#include + +#ifdef HAVE_CVCONFIG_H +#include "cvconfig.h" +#endif + +#ifdef HAVE_TBB +#include "tbb/task_scheduler_init.h" +#endif + +using namespace cv; + +const float score_thr = 0.05f; + +class LatentSVMDetectorCaskadeTest : public cvtest::BaseTest +{ +protected: + void run(int); +}; + +static void writeDetections( FileStorage& fs, const std::string& nodeName, const std::vector& detections ) +{ + fs << nodeName << "["; + for( size_t i = 0; i < detections.size(); i++ ) //FIXME operator << + { + lsvm::LSVMDetector::ObjectDetection const &d = detections[i]; + fs << d.rect.x << d.rect.y << d.rect.width << d.rect.height + << d.score << d.classID; + } + fs << "]"; +} + +static void readDetections( FileStorage fs, const std::string& nodeName, + std::vector& detections ) +{ + detections.clear(); + + FileNode fn = fs.root()[nodeName]; + FileNodeIterator fni = fn.begin(); + while( fni != fn.end() ) + { + lsvm::LSVMDetector::ObjectDetection d; + fni >> d.rect.x >> d.rect.y >> d.rect.width >> d.rect.height + >> d.score >> d.classID; + detections.push_back( d ); + } +} + +static inline bool isEqualCaskad( const lsvm::LSVMDetector::ObjectDetection& d1, + const lsvm::LSVMDetector::ObjectDetection& d2, int eps, float threshold) +{ + return ( + std::abs(d1.rect.x - d2.rect.x) <= eps + && std::abs(d1.rect.y - d2.rect.y) <= eps + && std::abs(d1.rect.width - d2.rect.width) <= eps + && std::abs(d1.rect.height - d2.rect.height) <= eps + && (d1.classID == d2.classID) + && std::abs(d1.score - d2.score) <= threshold + ); +} + + +bool compareResults( const std::vector& calc, + const std::vector& valid, int eps, float threshold) +{ + if( calc.size() != valid.size() ) + return false; + + for( size_t i = 0; i < calc.size(); i++ ) + { + lsvm::LSVMDetector::ObjectDetection const &c = calc[i]; + lsvm::LSVMDetector::ObjectDetection const &v = valid[i]; + + if( !isEqualCaskad(c, v, eps, threshold) ) + { + std::cerr << "Expected: " << v.rect << " class=" << v.classID << " score=" << v.score << std::endl; + std::cerr << "Actual: " << c.rect << " class=" << c.classID << " score=" << c.score << std::endl; + return false; + } + } + return true; +} + +void LatentSVMDetectorCaskadeTest::run( int /* start_from */) +{ + std::string img_path_cat = std::string(ts->get_data_path()) + "cat.png"; + std::string img_path_cars = std::string(ts->get_data_path()) + "cars.png"; + + std::string model_path_cat = std::string(ts->get_data_path()) + "models_VOC2007_cascade/cat.xml"; + std::string model_path_car = std::string(ts->get_data_path()) + "models_VOC2007_cascade/car.xml"; + + std::string true_res_path = std::string(ts->get_data_path()) + "results_cascade.xml"; + + +#ifdef HAVE_TBB + int numThreads = 2; +#endif + + Mat image_cat = imread( img_path_cat ); + Mat image_cars = imread( img_path_cars ); + if( image_cat.empty() || image_cars.empty() ) + { + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA ); + return; + } + + // We will test 2 cases: + // detector1 - to test case of one class 'cat' + // detector12 - to test case of two (several) classes 'cat' and car + + // Load detectors + cv::Ptr detector1 = lsvm::LSVMDetector::create(std::vector(1,model_path_cat)); + + std::vector models_pathes(2); + models_pathes[0] = model_path_cat; + models_pathes[1] = model_path_car; + cv::Ptr detector12 = lsvm::LSVMDetector::create(models_pathes); + + if( detector1->isEmpty() || detector12->isEmpty() || detector12->getClassCount() != 2 ) + { + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA ); + return; + } + + // 1. Test method detect + // Run detectors + std::vector detections1_cat, detections12_cat, detections12_cars; + detector1->detect( image_cat, detections1_cat, 0.5); + detector12->detect( image_cat, detections12_cat, 0.5); + detector12->detect( image_cars, detections12_cars, 0.5); + + // Load true results + FileStorage fs( true_res_path, FileStorage::READ ); + if( fs.isOpened() ) + { + std::vector true_detections1_cat, true_detections12_cat, true_detections12_cars; + readDetections( fs, "detections1_cat", true_detections1_cat ); + readDetections( fs, "detections12_cat", true_detections12_cat ); + readDetections( fs, "detections12_cars", true_detections12_cars ); + + if( !compareResults(detections1_cat, true_detections1_cat, 1, score_thr) ) + { + std::cerr << "Results of detector1 are invalid on image cat.png" << std::endl; + ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH ); + } + if( !compareResults(detections12_cat, true_detections12_cat, 1, score_thr) ) + { + std::cerr << "Results of detector12 are invalid on image cat.png" << std::endl; + ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH ); + } + if( !compareResults(detections12_cars, true_detections12_cars, 1, score_thr) ) + { + std::cerr << "Results of detector12 are invalid on image cars.png" << std::endl; + ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH ); + } + } + else + { + fs.open( true_res_path, FileStorage::WRITE ); + if( fs.isOpened() ) + { + writeDetections( fs, "detections1_cat", detections1_cat ); + writeDetections( fs, "detections12_cat", detections12_cat ); + writeDetections( fs, "detections12_cars", detections12_cars ); + } + else + std::cerr << "File " << true_res_path << " cann't be opened to save test results" << std::endl; + } + + ts->set_failed_test_info( cvtest::TS::OK); +} + +TEST(Objdetect_LatentSVMDetectorCaskade_cpp, regression) { LatentSVMDetectorCaskadeTest test; test.safe_run(); } diff --git a/modules/latentsvm/test/test_main.cpp b/modules/latentsvm/test/test_main.cpp new file mode 100644 index 00000000000..6d0975e242e --- /dev/null +++ b/modules/latentsvm/test/test_main.cpp @@ -0,0 +1,3 @@ +#include "test_precomp.hpp" + +CV_TEST_MAIN("latentsvm") diff --git a/modules/latentsvm/test/test_precomp.cpp b/modules/latentsvm/test/test_precomp.cpp new file mode 100644 index 00000000000..5956e13e3e9 --- /dev/null +++ b/modules/latentsvm/test/test_precomp.cpp @@ -0,0 +1 @@ +#include "test_precomp.hpp" diff --git a/modules/latentsvm/test/test_precomp.hpp b/modules/latentsvm/test/test_precomp.hpp new file mode 100644 index 00000000000..d32f480e179 --- /dev/null +++ b/modules/latentsvm/test/test_precomp.hpp @@ -0,0 +1,17 @@ +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wmissing-declarations" +# if defined __clang__ || defined __APPLE__ +# pragma GCC diagnostic ignored "-Wmissing-prototypes" +# pragma GCC diagnostic ignored "-Wextra" +# endif +#endif + +#ifndef __OPENCV_TEST_PRECOMP_HPP__ +#define __OPENCV_TEST_PRECOMP_HPP__ + +#include "opencv2/ts.hpp" +#include "opencv2/latentsvm.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" + +#endif diff --git a/modules/latentsvm/testdata/latentsvm/cars.png b/modules/latentsvm/testdata/latentsvm/cars.png new file mode 100644 index 00000000000..2d9bdf260bb Binary files /dev/null and b/modules/latentsvm/testdata/latentsvm/cars.png differ diff --git a/modules/latentsvm/testdata/latentsvm/cat.png b/modules/latentsvm/testdata/latentsvm/cat.png new file mode 100644 index 00000000000..31f4e2e581d Binary files /dev/null and b/modules/latentsvm/testdata/latentsvm/cat.png differ diff --git a/modules/latentsvm/testdata/latentsvm/mat2xml.m b/modules/latentsvm/testdata/latentsvm/mat2xml.m new file mode 100644 index 00000000000..61bc9bf96f0 --- /dev/null +++ b/modules/latentsvm/testdata/latentsvm/mat2xml.m @@ -0,0 +1,99 @@ +function [] = mat2xml(fname_in, fname_out) +load(fname_in); +num_feat = 31; +rootfilters = []; +for i = 1:length(model.rootfilters) + rootfilters{i} = model.rootfilters{i}.w; +end +partfilters = []; +for i = 1:length(model.partfilters) + partfilters{i} = model.partfilters{i}.w; +end +for c = 1:model.numcomponents + ridx{c} = model.components{c}.rootindex; + oidx{c} = model.components{c}.offsetindex; + root{c} = model.rootfilters{ridx{c}}.w; + rsize{c} = [size(root{c},1) size(root{c},2)]; + numparts{c} = length(model.components{c}.parts); + for j = 1:numparts{c} + pidx{c,j} = model.components{c}.parts{j}.partindex; + didx{c,j} = model.components{c}.parts{j}.defindex; + part{c,j} = model.partfilters{pidx{c,j}}.w; + psize{c,j} = [size(part{c,j},1) size(part{c,j},2)]; + % reverse map from partfilter index to (component, part#) + % rpidx{pidx{c,j}} = [c j]; + end +end + +f = fopen(fname_out, 'wb'); +fprintf(f, '\n'); +fprintf(f, '\t\n'); +fprintf(f, '\t%d\n', model.numcomponents); +fprintf(f, '\t\n'); +fprintf(f, '\t

%d

\n', num_feat); +fprintf(f, '\t\n'); +fprintf(f, '\t%.16f\n', model.thresh); +for c = 1:model.numcomponents + fprintf(f, '\t\n'); + fprintf(f, '\t\t\n'); + fprintf(f, '\t\t\n'); + fprintf(f, '\t\t\t\n'); + rootfilter = root{c}; + fprintf(f, '\t\t\t%d\n', rsize{c}(2)); + fprintf(f, '\t\t\t%d\n', rsize{c}(1)); + fprintf(f, '\t\t\t\n'); + fprintf(f, '\t\t\t'); + for jj = 1:rsize{c}(1) + for ii = 1:rsize{c}(2) + for kk = 1:num_feat + fwrite(f, rootfilter(jj, ii, kk), 'double'); + end + end + end + fprintf(f, '\t\t\t\n'); + fprintf(f, '\t\t\t\n'); + fprintf(f, '\t\t\t%.16f\n', model.offsets{1,c}.w); + fprintf(f, '\t\t\n\n'); + fprintf(f, '\t\t\n'); + fprintf(f, '\t\t\n'); + fprintf(f, '\t\t\t%d\n', numparts{c}); + + for j=1:numparts{c} + fprintf(f, '\t\t\t\n', j); + fprintf(f, '\t\t\t\n'); + partfilter = part{c,j}; + anchor = model.defs{didx{c,j}}.anchor; + def = model.defs{didx{c,j}}.w; + + fprintf(f, '\t\t\t\t\n'); + fprintf(f, '\t\t\t\t%d\n', psize{c,j}(2)); + fprintf(f, '\t\t\t\t%d\n', psize{c,j}(1)); + fprintf(f, '\t\t\t\t\n'); + fprintf(f, '\t\t\t\t'); + for jj = 1:psize{c,j}(1) + for ii = 1:psize{c,j}(2) + for kk = 1:num_feat + fwrite(f, partfilter(jj, ii, kk), 'double'); + end + end + end + fprintf(f, '\t\t\t\t\n'); + fprintf(f, '\t\t\t\t\n'); + fprintf(f, '\t\t\t\t\n'); + fprintf(f, '\t\t\t\t\t%d\n', anchor(1)); + fprintf(f, '\t\t\t\t\t%d\n', anchor(2)); + fprintf(f, '\t\t\t\t\n'); + fprintf(f, '\t\t\t\t\n'); + fprintf(f, '\t\t\t\t\n'); + fprintf(f, '\t\t\t\t\t%.16f\n', def(2)); + fprintf(f, '\t\t\t\t\t%.16f\n', def(4)); + fprintf(f, '\t\t\t\t\t%.16f\n', def(1)); + fprintf(f, '\t\t\t\t\t%.16f\n', def(3)); + fprintf(f, '\t\t\t\t\n'); + fprintf(f, '\t\t\t\n'); + end + fprintf(f, '\t\t\n'); + fprintf(f, '\t\n'); +end +fprintf(f, '
'); +fclose(f); diff --git a/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/aeroplane.xml b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/aeroplane.xml new file mode 100644 index 00000000000..4d37fe24874 Binary files /dev/null and b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/aeroplane.xml differ diff --git a/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/bicycle.xml b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/bicycle.xml new file mode 100644 index 00000000000..7ec2e3cfce0 Binary files /dev/null and b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/bicycle.xml differ diff --git a/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/bird.xml b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/bird.xml new file mode 100644 index 00000000000..3d18a7624d5 Binary files /dev/null and b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/bird.xml differ diff --git a/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/boat.xml b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/boat.xml new file mode 100644 index 00000000000..18977d1cc89 Binary files /dev/null and b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/boat.xml differ diff --git a/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/bottle.xml b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/bottle.xml new file mode 100644 index 00000000000..3e756d81859 Binary files /dev/null and b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/bottle.xml differ diff --git a/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/bus.xml b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/bus.xml new file mode 100644 index 00000000000..9ac5697d1b0 Binary files /dev/null and b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/bus.xml differ diff --git a/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/car.xml b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/car.xml new file mode 100644 index 00000000000..30fa895d57b Binary files /dev/null and b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/car.xml differ diff --git a/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/cat.xml b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/cat.xml new file mode 100644 index 00000000000..1ccdef8b4d5 Binary files /dev/null and b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/cat.xml differ diff --git a/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/chair.xml b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/chair.xml new file mode 100644 index 00000000000..4b37f0d753c Binary files /dev/null and b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/chair.xml differ diff --git a/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/cow.xml b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/cow.xml new file mode 100644 index 00000000000..d714029ab8f Binary files /dev/null and b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/cow.xml differ diff --git a/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/diningtable.xml b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/diningtable.xml new file mode 100644 index 00000000000..e9d55387fe0 Binary files /dev/null and b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/diningtable.xml differ diff --git a/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/dog.xml b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/dog.xml new file mode 100644 index 00000000000..6a4f958b558 Binary files /dev/null and b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/dog.xml differ diff --git a/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/horse.xml b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/horse.xml new file mode 100644 index 00000000000..e0e7ededc26 Binary files /dev/null and b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/horse.xml differ diff --git a/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/motorbike.xml b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/motorbike.xml new file mode 100644 index 00000000000..7fff6a4b37f Binary files /dev/null and b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/motorbike.xml differ diff --git a/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/person.xml b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/person.xml new file mode 100644 index 00000000000..6da86a47504 Binary files /dev/null and b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/person.xml differ diff --git a/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/pottedplant.xml b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/pottedplant.xml new file mode 100644 index 00000000000..578b5621582 Binary files /dev/null and b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/pottedplant.xml differ diff --git a/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/sheep.xml b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/sheep.xml new file mode 100644 index 00000000000..41a1f764c6f Binary files /dev/null and b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/sheep.xml differ diff --git a/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/sofa.xml b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/sofa.xml new file mode 100644 index 00000000000..ee264585803 Binary files /dev/null and b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/sofa.xml differ diff --git a/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/train.xml b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/train.xml new file mode 100644 index 00000000000..008aefba0a1 Binary files /dev/null and b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/train.xml differ diff --git a/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/tvmonitor.xml b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/tvmonitor.xml new file mode 100644 index 00000000000..19a829cc9b2 Binary files /dev/null and b/modules/latentsvm/testdata/latentsvm/models_VOC2007_cascade/tvmonitor.xml differ diff --git a/modules/latentsvm/testdata/latentsvm/pcacoeff.bin b/modules/latentsvm/testdata/latentsvm/pcacoeff.bin new file mode 100644 index 00000000000..7ca9cf38df6 Binary files /dev/null and b/modules/latentsvm/testdata/latentsvm/pcacoeff.bin differ diff --git a/modules/latentsvm/testdata/latentsvm/results_cascade.xml b/modules/latentsvm/testdata/latentsvm/results_cascade.xml new file mode 100644 index 00000000000..a0e4686b788 --- /dev/null +++ b/modules/latentsvm/testdata/latentsvm/results_cascade.xml @@ -0,0 +1,12 @@ + + + + 0 0 340 485 -0.837739 0 + + 0 0 340 485 -0.837739 0 129 0 181 155 -0.795819 1 + +218 24 218 121 2.36436 1 0 285 233 129 1.93423 1 0 21 190 105 1.7496 1 202 183 202 +73 1.57262 1 0 171 171 68 1.49932 1 238 312 165 91 0.504801 1 0 181 226 90 0.404986 +1 0 0 240 171 0.158534 1 207 155 233 129 -0.1988589 1 195 278 250 139 -0.50933 1 + 89 0 328 119 -0.570692 1 0 295 422 154 -0.922104 1 + diff --git a/modules/line_descriptor/include/opencv2/line_descriptor/descriptor.hpp b/modules/line_descriptor/include/opencv2/line_descriptor/descriptor.hpp index 45a5747a934..28a900c8871 100644 --- a/modules/line_descriptor/include/opencv2/line_descriptor/descriptor.hpp +++ b/modules/line_descriptor/include/opencv2/line_descriptor/descriptor.hpp @@ -50,7 +50,7 @@ #include #include "opencv2/core/utility.hpp" -#include "opencv2/core/private.hpp" +//#include "opencv2/core/private.hpp" #include #include #include