feat: 切换后端至PaddleOCR-NCNN,切换工程为CMake
1.项目后端整体迁移至PaddleOCR-NCNN算法,已通过基本的兼容性测试 2.工程改为使用CMake组织,后续为了更好地兼容第三方库,不再提供QMake工程 3.重整权利声明文件,重整代码工程,确保最小化侵权风险 Log: 切换后端至PaddleOCR-NCNN,切换工程为CMake Change-Id: I4d5d2c5d37505a4a24b389b1a4c5d12f17bfa38c
This commit is contained in:
8
3rdparty/opencv-4.5.4/modules/objdetect/CMakeLists.txt
vendored
Normal file
8
3rdparty/opencv-4.5.4/modules/objdetect/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
set(the_description "Object Detection")
|
||||
ocv_define_module(objdetect opencv_core opencv_imgproc opencv_calib3d opencv_dnn WRAP java objc python js)
|
||||
|
||||
if(HAVE_QUIRC)
|
||||
get_property(QUIRC_INCLUDE GLOBAL PROPERTY QUIRC_INCLUDE_DIR)
|
||||
ocv_include_directories(${QUIRC_INCLUDE})
|
||||
ocv_target_link_libraries(${the_module} quirc)
|
||||
endif()
|
BIN
3rdparty/opencv-4.5.4/modules/objdetect/doc/pics/haarfeatures.png
vendored
Normal file
BIN
3rdparty/opencv-4.5.4/modules/objdetect/doc/pics/haarfeatures.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
773
3rdparty/opencv-4.5.4/modules/objdetect/include/opencv2/objdetect.hpp
vendored
Normal file
773
3rdparty/opencv-4.5.4/modules/objdetect/include/opencv2/objdetect.hpp
vendored
Normal file
@ -0,0 +1,773 @@
|
||||
/*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.
|
||||
// Copyright (C) 2013, OpenCV Foundation, 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_OBJDETECT_HPP
|
||||
#define OPENCV_OBJDETECT_HPP
|
||||
|
||||
#include "opencv2/core.hpp"
|
||||
|
||||
/**
|
||||
@defgroup objdetect Object Detection
|
||||
|
||||
Haar Feature-based Cascade Classifier for Object Detection
|
||||
----------------------------------------------------------
|
||||
|
||||
The object detector described below has been initially proposed by Paul Viola @cite Viola01 and
|
||||
improved by Rainer Lienhart @cite Lienhart02 .
|
||||
|
||||
First, a classifier (namely a *cascade of boosted classifiers working with haar-like features*) is
|
||||
trained with a few hundred sample views of a particular object (i.e., a face or a car), called
|
||||
positive examples, that are scaled to the same size (say, 20x20), and negative examples - arbitrary
|
||||
images of the same size.
|
||||
|
||||
After a classifier is trained, it can be applied to a region of interest (of the same size as used
|
||||
during the training) in an input image. The classifier outputs a "1" if the region is likely to show
|
||||
the object (i.e., face/car), and "0" otherwise. To search for the object in the whole image one can
|
||||
move the search window across the image and check every location using the classifier. The
|
||||
classifier is designed so that it can be easily "resized" in order to be able to find the objects of
|
||||
interest at different sizes, which is more efficient than resizing the image itself. So, to find an
|
||||
object of an unknown size in the image the scan procedure should be done several times at different
|
||||
scales.
|
||||
|
||||
The word "cascade" in the classifier name means that the resultant classifier consists of several
|
||||
simpler classifiers (*stages*) that are applied subsequently to a region of interest until at some
|
||||
stage the candidate is rejected or all the stages are passed. The word "boosted" means that the
|
||||
classifiers at every stage of the cascade are complex themselves and they are built out of basic
|
||||
classifiers using one of four different boosting techniques (weighted voting). Currently Discrete
|
||||
Adaboost, Real Adaboost, Gentle Adaboost and Logitboost are supported. The basic classifiers are
|
||||
decision-tree classifiers with at least 2 leaves. Haar-like features are the input to the basic
|
||||
classifiers, and are calculated as described below. The current algorithm uses the following
|
||||
Haar-like features:
|
||||
|
||||

|
||||
|
||||
The feature used in a particular classifier is specified by its shape (1a, 2b etc.), position within
|
||||
the region of interest and the scale (this scale is not the same as the scale used at the detection
|
||||
stage, though these two scales are multiplied). For example, in the case of the third line feature
|
||||
(2c) the response is calculated as the difference between the sum of image pixels under the
|
||||
rectangle covering the whole feature (including the two white stripes and the black stripe in the
|
||||
middle) and the sum of the image pixels under the black stripe multiplied by 3 in order to
|
||||
compensate for the differences in the size of areas. The sums of pixel values over a rectangular
|
||||
regions are calculated rapidly using integral images (see below and the integral description).
|
||||
|
||||
To see the object detector at work, have a look at the facedetect demo:
|
||||
<https://github.com/opencv/opencv/tree/master/samples/cpp/dbt_face_detection.cpp>
|
||||
|
||||
The following reference is for the detection part only. There is a separate application called
|
||||
opencv_traincascade that can train a cascade of boosted classifiers from a set of samples.
|
||||
|
||||
@note In the new C++ interface it is also possible to use LBP (local binary pattern) features in
|
||||
addition to Haar-like features. .. [Viola01] Paul Viola and Michael J. Jones. Rapid Object Detection
|
||||
using a Boosted Cascade of Simple Features. IEEE CVPR, 2001. The paper is available online at
|
||||
<http://research.microsoft.com/en-us/um/people/viola/Pubs/Detect/violaJones_CVPR2001.pdf>
|
||||
|
||||
@{
|
||||
@defgroup objdetect_c C API
|
||||
@}
|
||||
*/
|
||||
|
||||
typedef struct CvHaarClassifierCascade CvHaarClassifierCascade;
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
//! @addtogroup objdetect
|
||||
//! @{
|
||||
|
||||
///////////////////////////// Object Detection ////////////////////////////
|
||||
|
||||
//! class for grouping object candidates, detected by Cascade Classifier, HOG etc.
|
||||
//! instance of the class is to be passed to cv::partition (see cxoperations.hpp)
|
||||
class CV_EXPORTS SimilarRects
|
||||
{
|
||||
public:
|
||||
SimilarRects(double _eps) : eps(_eps) {}
|
||||
inline bool operator()(const Rect& r1, const Rect& r2) const
|
||||
{
|
||||
double delta = eps * ((std::min)(r1.width, r2.width) + (std::min)(r1.height, r2.height)) * 0.5;
|
||||
return std::abs(r1.x - r2.x) <= delta &&
|
||||
std::abs(r1.y - r2.y) <= delta &&
|
||||
std::abs(r1.x + r1.width - r2.x - r2.width) <= delta &&
|
||||
std::abs(r1.y + r1.height - r2.y - r2.height) <= delta;
|
||||
}
|
||||
double eps;
|
||||
};
|
||||
|
||||
/** @brief Groups the object candidate rectangles.
|
||||
|
||||
@param rectList Input/output vector of rectangles. Output vector includes retained and grouped
|
||||
rectangles. (The Python list is not modified in place.)
|
||||
@param groupThreshold Minimum possible number of rectangles minus 1. The threshold is used in a
|
||||
group of rectangles to retain it.
|
||||
@param eps Relative difference between sides of the rectangles to merge them into a group.
|
||||
|
||||
The function is a wrapper for the generic function partition . It clusters all the input rectangles
|
||||
using the rectangle equivalence criteria that combines rectangles with similar sizes and similar
|
||||
locations. The similarity is defined by eps. When eps=0 , no clustering is done at all. If
|
||||
\f$\texttt{eps}\rightarrow +\inf\f$ , all the rectangles are put in one cluster. Then, the small
|
||||
clusters containing less than or equal to groupThreshold rectangles are rejected. In each other
|
||||
cluster, the average rectangle is computed and put into the output rectangle list.
|
||||
*/
|
||||
CV_EXPORTS void groupRectangles(std::vector<Rect>& rectList, int groupThreshold, double eps = 0.2);
|
||||
/** @overload */
|
||||
CV_EXPORTS_W void groupRectangles(CV_IN_OUT std::vector<Rect>& rectList, CV_OUT std::vector<int>& weights,
|
||||
int groupThreshold, double eps = 0.2);
|
||||
/** @overload */
|
||||
CV_EXPORTS void groupRectangles(std::vector<Rect>& rectList, int groupThreshold,
|
||||
double eps, std::vector<int>* weights, std::vector<double>* levelWeights );
|
||||
/** @overload */
|
||||
CV_EXPORTS void groupRectangles(std::vector<Rect>& rectList, std::vector<int>& rejectLevels,
|
||||
std::vector<double>& levelWeights, int groupThreshold, double eps = 0.2);
|
||||
/** @overload */
|
||||
CV_EXPORTS void groupRectangles_meanshift(std::vector<Rect>& rectList, std::vector<double>& foundWeights,
|
||||
std::vector<double>& foundScales,
|
||||
double detectThreshold = 0.0, Size winDetSize = Size(64, 128));
|
||||
|
||||
template<> struct DefaultDeleter<CvHaarClassifierCascade>{ CV_EXPORTS void operator ()(CvHaarClassifierCascade* obj) const; };
|
||||
|
||||
enum { CASCADE_DO_CANNY_PRUNING = 1,
|
||||
CASCADE_SCALE_IMAGE = 2,
|
||||
CASCADE_FIND_BIGGEST_OBJECT = 4,
|
||||
CASCADE_DO_ROUGH_SEARCH = 8
|
||||
};
|
||||
|
||||
class CV_EXPORTS_W BaseCascadeClassifier : public Algorithm
|
||||
{
|
||||
public:
|
||||
virtual ~BaseCascadeClassifier();
|
||||
virtual bool empty() const CV_OVERRIDE = 0;
|
||||
virtual bool load( const String& filename ) = 0;
|
||||
virtual void detectMultiScale( InputArray image,
|
||||
CV_OUT std::vector<Rect>& objects,
|
||||
double scaleFactor,
|
||||
int minNeighbors, int flags,
|
||||
Size minSize, Size maxSize ) = 0;
|
||||
|
||||
virtual void detectMultiScale( InputArray image,
|
||||
CV_OUT std::vector<Rect>& objects,
|
||||
CV_OUT std::vector<int>& numDetections,
|
||||
double scaleFactor,
|
||||
int minNeighbors, int flags,
|
||||
Size minSize, Size maxSize ) = 0;
|
||||
|
||||
virtual void detectMultiScale( InputArray image,
|
||||
CV_OUT std::vector<Rect>& objects,
|
||||
CV_OUT std::vector<int>& rejectLevels,
|
||||
CV_OUT std::vector<double>& levelWeights,
|
||||
double scaleFactor,
|
||||
int minNeighbors, int flags,
|
||||
Size minSize, Size maxSize,
|
||||
bool outputRejectLevels ) = 0;
|
||||
|
||||
virtual bool isOldFormatCascade() const = 0;
|
||||
virtual Size getOriginalWindowSize() const = 0;
|
||||
virtual int getFeatureType() const = 0;
|
||||
virtual void* getOldCascade() = 0;
|
||||
|
||||
class CV_EXPORTS MaskGenerator
|
||||
{
|
||||
public:
|
||||
virtual ~MaskGenerator() {}
|
||||
virtual Mat generateMask(const Mat& src)=0;
|
||||
virtual void initializeMask(const Mat& /*src*/) { }
|
||||
};
|
||||
virtual void setMaskGenerator(const Ptr<MaskGenerator>& maskGenerator) = 0;
|
||||
virtual Ptr<MaskGenerator> getMaskGenerator() = 0;
|
||||
};
|
||||
|
||||
/** @example samples/cpp/facedetect.cpp
|
||||
This program demonstrates usage of the Cascade classifier class
|
||||
\image html Cascade_Classifier_Tutorial_Result_Haar.jpg "Sample screenshot" width=321 height=254
|
||||
*/
|
||||
/** @brief Cascade classifier class for object detection.
|
||||
*/
|
||||
class CV_EXPORTS_W CascadeClassifier
|
||||
{
|
||||
public:
|
||||
CV_WRAP CascadeClassifier();
|
||||
/** @brief Loads a classifier from a file.
|
||||
|
||||
@param filename Name of the file from which the classifier is loaded.
|
||||
*/
|
||||
CV_WRAP CascadeClassifier(const String& filename);
|
||||
~CascadeClassifier();
|
||||
/** @brief Checks whether the classifier has been loaded.
|
||||
*/
|
||||
CV_WRAP bool empty() const;
|
||||
/** @brief Loads a classifier from a file.
|
||||
|
||||
@param filename Name of the file from which the classifier is loaded. The file may contain an old
|
||||
HAAR classifier trained by the haartraining application or a new cascade classifier trained by the
|
||||
traincascade application.
|
||||
*/
|
||||
CV_WRAP bool load( const String& filename );
|
||||
/** @brief Reads a classifier from a FileStorage node.
|
||||
|
||||
@note The file may contain a new cascade classifier (trained traincascade application) only.
|
||||
*/
|
||||
CV_WRAP bool read( const FileNode& node );
|
||||
|
||||
/** @brief Detects objects of different sizes in the input image. The detected objects are returned as a list
|
||||
of rectangles.
|
||||
|
||||
@param image Matrix of the type CV_8U containing an image where objects are detected.
|
||||
@param objects Vector of rectangles where each rectangle contains the detected object, the
|
||||
rectangles may be partially outside the original image.
|
||||
@param scaleFactor Parameter specifying how much the image size is reduced at each image scale.
|
||||
@param minNeighbors Parameter specifying how many neighbors each candidate rectangle should have
|
||||
to retain it.
|
||||
@param flags Parameter with the same meaning for an old cascade as in the function
|
||||
cvHaarDetectObjects. It is not used for a new cascade.
|
||||
@param minSize Minimum possible object size. Objects smaller than that are ignored.
|
||||
@param maxSize Maximum possible object size. Objects larger than that are ignored. If `maxSize == minSize` model is evaluated on single scale.
|
||||
|
||||
The function is parallelized with the TBB library.
|
||||
|
||||
@note
|
||||
- (Python) A face detection example using cascade classifiers can be found at
|
||||
opencv_source_code/samples/python/facedetect.py
|
||||
*/
|
||||
CV_WRAP void detectMultiScale( InputArray image,
|
||||
CV_OUT std::vector<Rect>& objects,
|
||||
double scaleFactor = 1.1,
|
||||
int minNeighbors = 3, int flags = 0,
|
||||
Size minSize = Size(),
|
||||
Size maxSize = Size() );
|
||||
|
||||
/** @overload
|
||||
@param image Matrix of the type CV_8U containing an image where objects are detected.
|
||||
@param objects Vector of rectangles where each rectangle contains the detected object, the
|
||||
rectangles may be partially outside the original image.
|
||||
@param numDetections Vector of detection numbers for the corresponding objects. An object's number
|
||||
of detections is the number of neighboring positively classified rectangles that were joined
|
||||
together to form the object.
|
||||
@param scaleFactor Parameter specifying how much the image size is reduced at each image scale.
|
||||
@param minNeighbors Parameter specifying how many neighbors each candidate rectangle should have
|
||||
to retain it.
|
||||
@param flags Parameter with the same meaning for an old cascade as in the function
|
||||
cvHaarDetectObjects. It is not used for a new cascade.
|
||||
@param minSize Minimum possible object size. Objects smaller than that are ignored.
|
||||
@param maxSize Maximum possible object size. Objects larger than that are ignored. If `maxSize == minSize` model is evaluated on single scale.
|
||||
*/
|
||||
CV_WRAP_AS(detectMultiScale2) void detectMultiScale( InputArray image,
|
||||
CV_OUT std::vector<Rect>& objects,
|
||||
CV_OUT std::vector<int>& numDetections,
|
||||
double scaleFactor=1.1,
|
||||
int minNeighbors=3, int flags=0,
|
||||
Size minSize=Size(),
|
||||
Size maxSize=Size() );
|
||||
|
||||
/** @overload
|
||||
This function allows you to retrieve the final stage decision certainty of classification.
|
||||
For this, one needs to set `outputRejectLevels` on true and provide the `rejectLevels` and `levelWeights` parameter.
|
||||
For each resulting detection, `levelWeights` will then contain the certainty of classification at the final stage.
|
||||
This value can then be used to separate strong from weaker classifications.
|
||||
|
||||
A code sample on how to use it efficiently can be found below:
|
||||
@code
|
||||
Mat img;
|
||||
vector<double> weights;
|
||||
vector<int> levels;
|
||||
vector<Rect> detections;
|
||||
CascadeClassifier model("/path/to/your/model.xml");
|
||||
model.detectMultiScale(img, detections, levels, weights, 1.1, 3, 0, Size(), Size(), true);
|
||||
cerr << "Detection " << detections[0] << " with weight " << weights[0] << endl;
|
||||
@endcode
|
||||
*/
|
||||
CV_WRAP_AS(detectMultiScale3) void detectMultiScale( InputArray image,
|
||||
CV_OUT std::vector<Rect>& objects,
|
||||
CV_OUT std::vector<int>& rejectLevels,
|
||||
CV_OUT std::vector<double>& levelWeights,
|
||||
double scaleFactor = 1.1,
|
||||
int minNeighbors = 3, int flags = 0,
|
||||
Size minSize = Size(),
|
||||
Size maxSize = Size(),
|
||||
bool outputRejectLevels = false );
|
||||
|
||||
CV_WRAP bool isOldFormatCascade() const;
|
||||
CV_WRAP Size getOriginalWindowSize() const;
|
||||
CV_WRAP int getFeatureType() const;
|
||||
void* getOldCascade();
|
||||
|
||||
CV_WRAP static bool convert(const String& oldcascade, const String& newcascade);
|
||||
|
||||
void setMaskGenerator(const Ptr<BaseCascadeClassifier::MaskGenerator>& maskGenerator);
|
||||
Ptr<BaseCascadeClassifier::MaskGenerator> getMaskGenerator();
|
||||
|
||||
Ptr<BaseCascadeClassifier> cc;
|
||||
};
|
||||
|
||||
CV_EXPORTS Ptr<BaseCascadeClassifier::MaskGenerator> createFaceDetectionMaskGenerator();
|
||||
|
||||
//////////////// HOG (Histogram-of-Oriented-Gradients) Descriptor and Object Detector //////////////
|
||||
|
||||
//! struct for detection region of interest (ROI)
|
||||
struct DetectionROI
|
||||
{
|
||||
//! scale(size) of the bounding box
|
||||
double scale;
|
||||
//! set of requested locations to be evaluated
|
||||
std::vector<cv::Point> locations;
|
||||
//! vector that will contain confidence values for each location
|
||||
std::vector<double> confidences;
|
||||
};
|
||||
|
||||
/**@brief Implementation of HOG (Histogram of Oriented Gradients) descriptor and object detector.
|
||||
|
||||
the HOG descriptor algorithm introduced by Navneet Dalal and Bill Triggs @cite Dalal2005 .
|
||||
|
||||
useful links:
|
||||
|
||||
https://hal.inria.fr/inria-00548512/document/
|
||||
|
||||
https://en.wikipedia.org/wiki/Histogram_of_oriented_gradients
|
||||
|
||||
https://software.intel.com/en-us/ipp-dev-reference-histogram-of-oriented-gradients-hog-descriptor
|
||||
|
||||
http://www.learnopencv.com/histogram-of-oriented-gradients
|
||||
|
||||
http://www.learnopencv.com/handwritten-digits-classification-an-opencv-c-python-tutorial
|
||||
|
||||
*/
|
||||
struct CV_EXPORTS_W HOGDescriptor
|
||||
{
|
||||
public:
|
||||
enum HistogramNormType { L2Hys = 0 //!< Default histogramNormType
|
||||
};
|
||||
enum { DEFAULT_NLEVELS = 64 //!< Default nlevels value.
|
||||
};
|
||||
enum DescriptorStorageFormat { DESCR_FORMAT_COL_BY_COL, DESCR_FORMAT_ROW_BY_ROW };
|
||||
|
||||
/**@brief Creates the HOG descriptor and detector with default params.
|
||||
|
||||
aqual to HOGDescriptor(Size(64,128), Size(16,16), Size(8,8), Size(8,8), 9 )
|
||||
*/
|
||||
CV_WRAP HOGDescriptor() : winSize(64,128), blockSize(16,16), blockStride(8,8),
|
||||
cellSize(8,8), nbins(9), derivAperture(1), winSigma(-1),
|
||||
histogramNormType(HOGDescriptor::L2Hys), L2HysThreshold(0.2), gammaCorrection(true),
|
||||
free_coef(-1.f), nlevels(HOGDescriptor::DEFAULT_NLEVELS), signedGradient(false)
|
||||
{}
|
||||
|
||||
/** @overload
|
||||
@param _winSize sets winSize with given value.
|
||||
@param _blockSize sets blockSize with given value.
|
||||
@param _blockStride sets blockStride with given value.
|
||||
@param _cellSize sets cellSize with given value.
|
||||
@param _nbins sets nbins with given value.
|
||||
@param _derivAperture sets derivAperture with given value.
|
||||
@param _winSigma sets winSigma with given value.
|
||||
@param _histogramNormType sets histogramNormType with given value.
|
||||
@param _L2HysThreshold sets L2HysThreshold with given value.
|
||||
@param _gammaCorrection sets gammaCorrection with given value.
|
||||
@param _nlevels sets nlevels with given value.
|
||||
@param _signedGradient sets signedGradient with given value.
|
||||
*/
|
||||
CV_WRAP HOGDescriptor(Size _winSize, Size _blockSize, Size _blockStride,
|
||||
Size _cellSize, int _nbins, int _derivAperture=1, double _winSigma=-1,
|
||||
HOGDescriptor::HistogramNormType _histogramNormType=HOGDescriptor::L2Hys,
|
||||
double _L2HysThreshold=0.2, bool _gammaCorrection=false,
|
||||
int _nlevels=HOGDescriptor::DEFAULT_NLEVELS, bool _signedGradient=false)
|
||||
: winSize(_winSize), blockSize(_blockSize), blockStride(_blockStride), cellSize(_cellSize),
|
||||
nbins(_nbins), derivAperture(_derivAperture), winSigma(_winSigma),
|
||||
histogramNormType(_histogramNormType), L2HysThreshold(_L2HysThreshold),
|
||||
gammaCorrection(_gammaCorrection), free_coef(-1.f), nlevels(_nlevels), signedGradient(_signedGradient)
|
||||
{}
|
||||
|
||||
/** @overload
|
||||
@param filename The file name containing HOGDescriptor properties and coefficients for the linear SVM classifier.
|
||||
*/
|
||||
CV_WRAP HOGDescriptor(const String& filename)
|
||||
{
|
||||
load(filename);
|
||||
}
|
||||
|
||||
/** @overload
|
||||
@param d the HOGDescriptor which cloned to create a new one.
|
||||
*/
|
||||
HOGDescriptor(const HOGDescriptor& d)
|
||||
{
|
||||
d.copyTo(*this);
|
||||
}
|
||||
|
||||
/**@brief Default destructor.
|
||||
*/
|
||||
virtual ~HOGDescriptor() {}
|
||||
|
||||
/**@brief Returns the number of coefficients required for the classification.
|
||||
*/
|
||||
CV_WRAP size_t getDescriptorSize() const;
|
||||
|
||||
/** @brief Checks if detector size equal to descriptor size.
|
||||
*/
|
||||
CV_WRAP bool checkDetectorSize() const;
|
||||
|
||||
/** @brief Returns winSigma value
|
||||
*/
|
||||
CV_WRAP double getWinSigma() const;
|
||||
|
||||
/**@example samples/cpp/peopledetect.cpp
|
||||
*/
|
||||
/**@brief Sets coefficients for the linear SVM classifier.
|
||||
@param svmdetector coefficients for the linear SVM classifier.
|
||||
*/
|
||||
CV_WRAP virtual void setSVMDetector(InputArray svmdetector);
|
||||
|
||||
/** @brief Reads HOGDescriptor parameters from a cv::FileNode.
|
||||
@param fn File node
|
||||
*/
|
||||
virtual bool read(FileNode& fn);
|
||||
|
||||
/** @brief Stores HOGDescriptor parameters in a cv::FileStorage.
|
||||
@param fs File storage
|
||||
@param objname Object name
|
||||
*/
|
||||
virtual void write(FileStorage& fs, const String& objname) const;
|
||||
|
||||
/** @brief loads HOGDescriptor parameters and coefficients for the linear SVM classifier from a file.
|
||||
@param filename Path of the file to read.
|
||||
@param objname The optional name of the node to read (if empty, the first top-level node will be used).
|
||||
*/
|
||||
CV_WRAP virtual bool load(const String& filename, const String& objname = String());
|
||||
|
||||
/** @brief saves HOGDescriptor parameters and coefficients for the linear SVM classifier to a file
|
||||
@param filename File name
|
||||
@param objname Object name
|
||||
*/
|
||||
CV_WRAP virtual void save(const String& filename, const String& objname = String()) const;
|
||||
|
||||
/** @brief clones the HOGDescriptor
|
||||
@param c cloned HOGDescriptor
|
||||
*/
|
||||
virtual void copyTo(HOGDescriptor& c) const;
|
||||
|
||||
/**@example samples/cpp/train_HOG.cpp
|
||||
*/
|
||||
/** @brief Computes HOG descriptors of given image.
|
||||
@param img Matrix of the type CV_8U containing an image where HOG features will be calculated.
|
||||
@param descriptors Matrix of the type CV_32F
|
||||
@param winStride Window stride. It must be a multiple of block stride.
|
||||
@param padding Padding
|
||||
@param locations Vector of Point
|
||||
*/
|
||||
CV_WRAP virtual void compute(InputArray img,
|
||||
CV_OUT std::vector<float>& descriptors,
|
||||
Size winStride = Size(), Size padding = Size(),
|
||||
const std::vector<Point>& locations = std::vector<Point>()) const;
|
||||
|
||||
/** @brief Performs object detection without a multi-scale window.
|
||||
@param img Matrix of the type CV_8U or CV_8UC3 containing an image where objects are detected.
|
||||
@param foundLocations Vector of point where each point contains left-top corner point of detected object boundaries.
|
||||
@param weights Vector that will contain confidence values for each detected object.
|
||||
@param hitThreshold Threshold for the distance between features and SVM classifying plane.
|
||||
Usually it is 0 and should be specified in the detector coefficients (as the last free coefficient).
|
||||
But if the free coefficient is omitted (which is allowed), you can specify it manually here.
|
||||
@param winStride Window stride. It must be a multiple of block stride.
|
||||
@param padding Padding
|
||||
@param searchLocations Vector of Point includes set of requested locations to be evaluated.
|
||||
*/
|
||||
CV_WRAP virtual void detect(InputArray img, CV_OUT std::vector<Point>& foundLocations,
|
||||
CV_OUT std::vector<double>& weights,
|
||||
double hitThreshold = 0, Size winStride = Size(),
|
||||
Size padding = Size(),
|
||||
const std::vector<Point>& searchLocations = std::vector<Point>()) const;
|
||||
|
||||
/** @brief Performs object detection without a multi-scale window.
|
||||
@param img Matrix of the type CV_8U or CV_8UC3 containing an image where objects are detected.
|
||||
@param foundLocations Vector of point where each point contains left-top corner point of detected object boundaries.
|
||||
@param hitThreshold Threshold for the distance between features and SVM classifying plane.
|
||||
Usually it is 0 and should be specified in the detector coefficients (as the last free coefficient).
|
||||
But if the free coefficient is omitted (which is allowed), you can specify it manually here.
|
||||
@param winStride Window stride. It must be a multiple of block stride.
|
||||
@param padding Padding
|
||||
@param searchLocations Vector of Point includes locations to search.
|
||||
*/
|
||||
virtual void detect(InputArray img, CV_OUT std::vector<Point>& foundLocations,
|
||||
double hitThreshold = 0, Size winStride = Size(),
|
||||
Size padding = Size(),
|
||||
const std::vector<Point>& searchLocations=std::vector<Point>()) const;
|
||||
|
||||
/** @brief Detects objects of different sizes in the input image. The detected objects are returned as a list
|
||||
of rectangles.
|
||||
@param img Matrix of the type CV_8U or CV_8UC3 containing an image where objects are detected.
|
||||
@param foundLocations Vector of rectangles where each rectangle contains the detected object.
|
||||
@param foundWeights Vector that will contain confidence values for each detected object.
|
||||
@param hitThreshold Threshold for the distance between features and SVM classifying plane.
|
||||
Usually it is 0 and should be specified in the detector coefficients (as the last free coefficient).
|
||||
But if the free coefficient is omitted (which is allowed), you can specify it manually here.
|
||||
@param winStride Window stride. It must be a multiple of block stride.
|
||||
@param padding Padding
|
||||
@param scale Coefficient of the detection window increase.
|
||||
@param finalThreshold Final threshold
|
||||
@param useMeanshiftGrouping indicates grouping algorithm
|
||||
*/
|
||||
CV_WRAP virtual void detectMultiScale(InputArray img, CV_OUT std::vector<Rect>& foundLocations,
|
||||
CV_OUT std::vector<double>& foundWeights, double hitThreshold = 0,
|
||||
Size winStride = Size(), Size padding = Size(), double scale = 1.05,
|
||||
double finalThreshold = 2.0,bool useMeanshiftGrouping = false) const;
|
||||
|
||||
/** @brief Detects objects of different sizes in the input image. The detected objects are returned as a list
|
||||
of rectangles.
|
||||
@param img Matrix of the type CV_8U or CV_8UC3 containing an image where objects are detected.
|
||||
@param foundLocations Vector of rectangles where each rectangle contains the detected object.
|
||||
@param hitThreshold Threshold for the distance between features and SVM classifying plane.
|
||||
Usually it is 0 and should be specified in the detector coefficients (as the last free coefficient).
|
||||
But if the free coefficient is omitted (which is allowed), you can specify it manually here.
|
||||
@param winStride Window stride. It must be a multiple of block stride.
|
||||
@param padding Padding
|
||||
@param scale Coefficient of the detection window increase.
|
||||
@param finalThreshold Final threshold
|
||||
@param useMeanshiftGrouping indicates grouping algorithm
|
||||
*/
|
||||
virtual void detectMultiScale(InputArray img, CV_OUT std::vector<Rect>& foundLocations,
|
||||
double hitThreshold = 0, Size winStride = Size(),
|
||||
Size padding = Size(), double scale = 1.05,
|
||||
double finalThreshold = 2.0, bool useMeanshiftGrouping = false) const;
|
||||
|
||||
/** @brief Computes gradients and quantized gradient orientations.
|
||||
@param img Matrix contains the image to be computed
|
||||
@param grad Matrix of type CV_32FC2 contains computed gradients
|
||||
@param angleOfs Matrix of type CV_8UC2 contains quantized gradient orientations
|
||||
@param paddingTL Padding from top-left
|
||||
@param paddingBR Padding from bottom-right
|
||||
*/
|
||||
CV_WRAP virtual void computeGradient(InputArray img, InputOutputArray grad, InputOutputArray angleOfs,
|
||||
Size paddingTL = Size(), Size paddingBR = Size()) const;
|
||||
|
||||
/** @brief Returns coefficients of the classifier trained for people detection (for 64x128 windows).
|
||||
*/
|
||||
CV_WRAP static std::vector<float> getDefaultPeopleDetector();
|
||||
|
||||
/**@example samples/tapi/hog.cpp
|
||||
*/
|
||||
/** @brief Returns coefficients of the classifier trained for people detection (for 48x96 windows).
|
||||
*/
|
||||
CV_WRAP static std::vector<float> getDaimlerPeopleDetector();
|
||||
|
||||
//! Detection window size. Align to block size and block stride. Default value is Size(64,128).
|
||||
CV_PROP Size winSize;
|
||||
|
||||
//! Block size in pixels. Align to cell size. Default value is Size(16,16).
|
||||
CV_PROP Size blockSize;
|
||||
|
||||
//! Block stride. It must be a multiple of cell size. Default value is Size(8,8).
|
||||
CV_PROP Size blockStride;
|
||||
|
||||
//! Cell size. Default value is Size(8,8).
|
||||
CV_PROP Size cellSize;
|
||||
|
||||
//! Number of bins used in the calculation of histogram of gradients. Default value is 9.
|
||||
CV_PROP int nbins;
|
||||
|
||||
//! not documented
|
||||
CV_PROP int derivAperture;
|
||||
|
||||
//! Gaussian smoothing window parameter.
|
||||
CV_PROP double winSigma;
|
||||
|
||||
//! histogramNormType
|
||||
CV_PROP HOGDescriptor::HistogramNormType histogramNormType;
|
||||
|
||||
//! L2-Hys normalization method shrinkage.
|
||||
CV_PROP double L2HysThreshold;
|
||||
|
||||
//! Flag to specify whether the gamma correction preprocessing is required or not.
|
||||
CV_PROP bool gammaCorrection;
|
||||
|
||||
//! coefficients for the linear SVM classifier.
|
||||
CV_PROP std::vector<float> svmDetector;
|
||||
|
||||
//! coefficients for the linear SVM classifier used when OpenCL is enabled
|
||||
UMat oclSvmDetector;
|
||||
|
||||
//! not documented
|
||||
float free_coef;
|
||||
|
||||
//! Maximum number of detection window increases. Default value is 64
|
||||
CV_PROP int nlevels;
|
||||
|
||||
//! Indicates signed gradient will be used or not
|
||||
CV_PROP bool signedGradient;
|
||||
|
||||
/** @brief evaluate specified ROI and return confidence value for each location
|
||||
@param img Matrix of the type CV_8U or CV_8UC3 containing an image where objects are detected.
|
||||
@param locations Vector of Point
|
||||
@param foundLocations Vector of Point where each Point is detected object's top-left point.
|
||||
@param confidences confidences
|
||||
@param hitThreshold Threshold for the distance between features and SVM classifying plane. Usually
|
||||
it is 0 and should be specified in the detector coefficients (as the last free coefficient). But if
|
||||
the free coefficient is omitted (which is allowed), you can specify it manually here
|
||||
@param winStride winStride
|
||||
@param padding padding
|
||||
*/
|
||||
virtual void detectROI(InputArray img, const std::vector<cv::Point> &locations,
|
||||
CV_OUT std::vector<cv::Point>& foundLocations, CV_OUT std::vector<double>& confidences,
|
||||
double hitThreshold = 0, cv::Size winStride = Size(),
|
||||
cv::Size padding = Size()) const;
|
||||
|
||||
/** @brief evaluate specified ROI and return confidence value for each location in multiple scales
|
||||
@param img Matrix of the type CV_8U or CV_8UC3 containing an image where objects are detected.
|
||||
@param foundLocations Vector of rectangles where each rectangle contains the detected object.
|
||||
@param locations Vector of DetectionROI
|
||||
@param hitThreshold Threshold for the distance between features and SVM classifying plane. Usually it is 0 and should be specified
|
||||
in the detector coefficients (as the last free coefficient). But if the free coefficient is omitted (which is allowed), you can specify it manually here.
|
||||
@param groupThreshold Minimum possible number of rectangles minus 1. The threshold is used in a group of rectangles to retain it.
|
||||
*/
|
||||
virtual void detectMultiScaleROI(InputArray img,
|
||||
CV_OUT std::vector<cv::Rect>& foundLocations,
|
||||
std::vector<DetectionROI>& locations,
|
||||
double hitThreshold = 0,
|
||||
int groupThreshold = 0) const;
|
||||
|
||||
/** @brief Groups the object candidate rectangles.
|
||||
@param rectList Input/output vector of rectangles. Output vector includes retained and grouped rectangles. (The Python list is not modified in place.)
|
||||
@param weights Input/output vector of weights of rectangles. Output vector includes weights of retained and grouped rectangles. (The Python list is not modified in place.)
|
||||
@param groupThreshold Minimum possible number of rectangles minus 1. The threshold is used in a group of rectangles to retain it.
|
||||
@param eps Relative difference between sides of the rectangles to merge them into a group.
|
||||
*/
|
||||
void groupRectangles(std::vector<cv::Rect>& rectList, std::vector<double>& weights, int groupThreshold, double eps) const;
|
||||
};
|
||||
|
||||
class CV_EXPORTS_W QRCodeDetector
|
||||
{
|
||||
public:
|
||||
CV_WRAP QRCodeDetector();
|
||||
~QRCodeDetector();
|
||||
|
||||
/** @brief sets the epsilon used during the horizontal scan of QR code stop marker detection.
|
||||
@param epsX Epsilon neighborhood, which allows you to determine the horizontal pattern
|
||||
of the scheme 1:1:3:1:1 according to QR code standard.
|
||||
*/
|
||||
CV_WRAP void setEpsX(double epsX);
|
||||
/** @brief sets the epsilon used during the vertical scan of QR code stop marker detection.
|
||||
@param epsY Epsilon neighborhood, which allows you to determine the vertical pattern
|
||||
of the scheme 1:1:3:1:1 according to QR code standard.
|
||||
*/
|
||||
CV_WRAP void setEpsY(double epsY);
|
||||
|
||||
/** @brief Detects QR code in image and returns the quadrangle containing the code.
|
||||
@param img grayscale or color (BGR) image containing (or not) QR code.
|
||||
@param points Output vector of vertices of the minimum-area quadrangle containing the code.
|
||||
*/
|
||||
CV_WRAP bool detect(InputArray img, OutputArray points) const;
|
||||
|
||||
/** @brief Decodes QR code in image once it's found by the detect() method.
|
||||
|
||||
Returns UTF8-encoded output string or empty string if the code cannot be decoded.
|
||||
@param img grayscale or color (BGR) image containing QR code.
|
||||
@param points Quadrangle vertices found by detect() method (or some other algorithm).
|
||||
@param straight_qrcode The optional output image containing rectified and binarized QR code
|
||||
*/
|
||||
CV_WRAP std::string decode(InputArray img, InputArray points, OutputArray straight_qrcode = noArray());
|
||||
|
||||
/** @brief Decodes QR code on a curved surface in image once it's found by the detect() method.
|
||||
|
||||
Returns UTF8-encoded output string or empty string if the code cannot be decoded.
|
||||
@param img grayscale or color (BGR) image containing QR code.
|
||||
@param points Quadrangle vertices found by detect() method (or some other algorithm).
|
||||
@param straight_qrcode The optional output image containing rectified and binarized QR code
|
||||
*/
|
||||
CV_WRAP cv::String decodeCurved(InputArray img, InputArray points, OutputArray straight_qrcode = noArray());
|
||||
|
||||
/** @brief Both detects and decodes QR code
|
||||
|
||||
@param img grayscale or color (BGR) image containing QR code.
|
||||
@param points optional output array of vertices of the found QR code quadrangle. Will be empty if not found.
|
||||
@param straight_qrcode The optional output image containing rectified and binarized QR code
|
||||
*/
|
||||
CV_WRAP std::string detectAndDecode(InputArray img, OutputArray points=noArray(),
|
||||
OutputArray straight_qrcode = noArray());
|
||||
|
||||
/** @brief Both detects and decodes QR code on a curved surface
|
||||
|
||||
@param img grayscale or color (BGR) image containing QR code.
|
||||
@param points optional output array of vertices of the found QR code quadrangle. Will be empty if not found.
|
||||
@param straight_qrcode The optional output image containing rectified and binarized QR code
|
||||
*/
|
||||
CV_WRAP std::string detectAndDecodeCurved(InputArray img, OutputArray points=noArray(),
|
||||
OutputArray straight_qrcode = noArray());
|
||||
|
||||
/** @brief Detects QR codes in image and returns the vector of the quadrangles containing the codes.
|
||||
@param img grayscale or color (BGR) image containing (or not) QR codes.
|
||||
@param points Output vector of vector of vertices of the minimum-area quadrangle containing the codes.
|
||||
*/
|
||||
CV_WRAP
|
||||
bool detectMulti(InputArray img, OutputArray points) const;
|
||||
|
||||
/** @brief Decodes QR codes in image once it's found by the detect() method.
|
||||
@param img grayscale or color (BGR) image containing QR codes.
|
||||
@param decoded_info UTF8-encoded output vector of string or empty vector of string if the codes cannot be decoded.
|
||||
@param points vector of Quadrangle vertices found by detect() method (or some other algorithm).
|
||||
@param straight_qrcode The optional output vector of images containing rectified and binarized QR codes
|
||||
*/
|
||||
CV_WRAP
|
||||
bool decodeMulti(
|
||||
InputArray img, InputArray points,
|
||||
CV_OUT std::vector<std::string>& decoded_info,
|
||||
OutputArrayOfArrays straight_qrcode = noArray()
|
||||
) const;
|
||||
|
||||
/** @brief Both detects and decodes QR codes
|
||||
@param img grayscale or color (BGR) image containing QR codes.
|
||||
@param decoded_info UTF8-encoded output vector of string or empty vector of string if the codes cannot be decoded.
|
||||
@param points optional output vector of vertices of the found QR code quadrangles. Will be empty if not found.
|
||||
@param straight_qrcode The optional output vector of images containing rectified and binarized QR codes
|
||||
*/
|
||||
CV_WRAP
|
||||
bool detectAndDecodeMulti(
|
||||
InputArray img, CV_OUT std::vector<std::string>& decoded_info,
|
||||
OutputArray points = noArray(),
|
||||
OutputArrayOfArrays straight_qrcode = noArray()
|
||||
) const;
|
||||
|
||||
protected:
|
||||
struct Impl;
|
||||
Ptr<Impl> p;
|
||||
};
|
||||
|
||||
//! @} objdetect
|
||||
}
|
||||
|
||||
#include "opencv2/objdetect/detection_based_tracker.hpp"
|
||||
#include "opencv2/objdetect/face.hpp"
|
||||
|
||||
#endif
|
222
3rdparty/opencv-4.5.4/modules/objdetect/include/opencv2/objdetect/detection_based_tracker.hpp
vendored
Normal file
222
3rdparty/opencv-4.5.4/modules/objdetect/include/opencv2/objdetect/detection_based_tracker.hpp
vendored
Normal file
@ -0,0 +1,222 @@
|
||||
/*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.
|
||||
// Copyright (C) 2013, OpenCV Foundation, 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_OBJDETECT_DBT_HPP
|
||||
#define OPENCV_OBJDETECT_DBT_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
//! @addtogroup objdetect
|
||||
//! @{
|
||||
|
||||
class CV_EXPORTS DetectionBasedTracker
|
||||
{
|
||||
public:
|
||||
struct CV_EXPORTS Parameters
|
||||
{
|
||||
int maxTrackLifetime;
|
||||
int minDetectionPeriod; //the minimal time between run of the big object detector (on the whole frame) in ms (1000 mean 1 sec), default=0
|
||||
|
||||
Parameters();
|
||||
};
|
||||
|
||||
class IDetector
|
||||
{
|
||||
public:
|
||||
IDetector():
|
||||
minObjSize(96, 96),
|
||||
maxObjSize(INT_MAX, INT_MAX),
|
||||
minNeighbours(2),
|
||||
scaleFactor(1.1f)
|
||||
{}
|
||||
|
||||
virtual void detect(const cv::Mat& image, std::vector<cv::Rect>& objects) = 0;
|
||||
|
||||
void setMinObjectSize(const cv::Size& min)
|
||||
{
|
||||
minObjSize = min;
|
||||
}
|
||||
void setMaxObjectSize(const cv::Size& max)
|
||||
{
|
||||
maxObjSize = max;
|
||||
}
|
||||
cv::Size getMinObjectSize() const
|
||||
{
|
||||
return minObjSize;
|
||||
}
|
||||
cv::Size getMaxObjectSize() const
|
||||
{
|
||||
return maxObjSize;
|
||||
}
|
||||
float getScaleFactor()
|
||||
{
|
||||
return scaleFactor;
|
||||
}
|
||||
void setScaleFactor(float value)
|
||||
{
|
||||
scaleFactor = value;
|
||||
}
|
||||
int getMinNeighbours()
|
||||
{
|
||||
return minNeighbours;
|
||||
}
|
||||
void setMinNeighbours(int value)
|
||||
{
|
||||
minNeighbours = value;
|
||||
}
|
||||
virtual ~IDetector() {}
|
||||
|
||||
protected:
|
||||
cv::Size minObjSize;
|
||||
cv::Size maxObjSize;
|
||||
int minNeighbours;
|
||||
float scaleFactor;
|
||||
};
|
||||
|
||||
DetectionBasedTracker(cv::Ptr<IDetector> mainDetector, cv::Ptr<IDetector> trackingDetector, const Parameters& params);
|
||||
virtual ~DetectionBasedTracker();
|
||||
|
||||
virtual bool run();
|
||||
virtual void stop();
|
||||
virtual void resetTracking();
|
||||
|
||||
virtual void process(const cv::Mat& imageGray);
|
||||
|
||||
bool setParameters(const Parameters& params);
|
||||
const Parameters& getParameters() const;
|
||||
|
||||
|
||||
typedef std::pair<cv::Rect, int> Object;
|
||||
virtual void getObjects(std::vector<cv::Rect>& result) const;
|
||||
virtual void getObjects(std::vector<Object>& result) const;
|
||||
|
||||
enum ObjectStatus
|
||||
{
|
||||
DETECTED_NOT_SHOWN_YET,
|
||||
DETECTED,
|
||||
DETECTED_TEMPORARY_LOST,
|
||||
WRONG_OBJECT
|
||||
};
|
||||
struct ExtObject
|
||||
{
|
||||
int id;
|
||||
cv::Rect location;
|
||||
ObjectStatus status;
|
||||
ExtObject(int _id, cv::Rect _location, ObjectStatus _status)
|
||||
:id(_id), location(_location), status(_status)
|
||||
{
|
||||
}
|
||||
};
|
||||
virtual void getObjects(std::vector<ExtObject>& result) const;
|
||||
|
||||
|
||||
virtual int addObject(const cv::Rect& location); //returns id of the new object
|
||||
|
||||
protected:
|
||||
class SeparateDetectionWork;
|
||||
cv::Ptr<SeparateDetectionWork> separateDetectionWork;
|
||||
friend void* workcycleObjectDetectorFunction(void* p);
|
||||
|
||||
struct InnerParameters
|
||||
{
|
||||
int numLastPositionsToTrack;
|
||||
int numStepsToWaitBeforeFirstShow;
|
||||
int numStepsToTrackWithoutDetectingIfObjectHasNotBeenShown;
|
||||
int numStepsToShowWithoutDetecting;
|
||||
|
||||
float coeffTrackingWindowSize;
|
||||
float coeffObjectSizeToTrack;
|
||||
float coeffObjectSpeedUsingInPrediction;
|
||||
|
||||
InnerParameters();
|
||||
};
|
||||
Parameters parameters;
|
||||
InnerParameters innerParameters;
|
||||
|
||||
struct TrackedObject
|
||||
{
|
||||
typedef std::vector<cv::Rect> PositionsVector;
|
||||
|
||||
PositionsVector lastPositions;
|
||||
|
||||
int numDetectedFrames;
|
||||
int numFramesNotDetected;
|
||||
int id;
|
||||
|
||||
TrackedObject(const cv::Rect& rect):numDetectedFrames(1), numFramesNotDetected(0)
|
||||
{
|
||||
lastPositions.push_back(rect);
|
||||
id=getNextId();
|
||||
};
|
||||
|
||||
static int getNextId()
|
||||
{
|
||||
static int _id=0;
|
||||
return _id++;
|
||||
}
|
||||
};
|
||||
|
||||
int numTrackedSteps;
|
||||
std::vector<TrackedObject> trackedObjects;
|
||||
|
||||
std::vector<float> weightsPositionsSmoothing;
|
||||
std::vector<float> weightsSizesSmoothing;
|
||||
|
||||
cv::Ptr<IDetector> cascadeForTracking;
|
||||
|
||||
void updateTrackedObjects(const std::vector<cv::Rect>& detectedObjects);
|
||||
cv::Rect calcTrackedObjectPositionToShow(int i) const;
|
||||
cv::Rect calcTrackedObjectPositionToShow(int i, ObjectStatus& status) const;
|
||||
void detectInRegion(const cv::Mat& img, const cv::Rect& r, std::vector<cv::Rect>& detectedObjectsInRegions);
|
||||
};
|
||||
|
||||
//! @} objdetect
|
||||
|
||||
} //end of cv namespace
|
||||
|
||||
#endif
|
125
3rdparty/opencv-4.5.4/modules/objdetect/include/opencv2/objdetect/face.hpp
vendored
Normal file
125
3rdparty/opencv-4.5.4/modules/objdetect/include/opencv2/objdetect/face.hpp
vendored
Normal file
@ -0,0 +1,125 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#ifndef OPENCV_OBJDETECT_FACE_HPP
|
||||
#define OPENCV_OBJDETECT_FACE_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
/** @defgroup dnn_face DNN-based face detection and recognition
|
||||
*/
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
/** @brief DNN-based face detector, model download link: https://github.com/ShiqiYu/libfacedetection.train/tree/master/tasks/task1/onnx.
|
||||
*/
|
||||
class CV_EXPORTS_W FaceDetectorYN
|
||||
{
|
||||
public:
|
||||
virtual ~FaceDetectorYN() {};
|
||||
|
||||
/** @brief Set the size for the network input, which overwrites the input size of creating model. Call this method when the size of input image does not match the input size when creating model
|
||||
*
|
||||
* @param input_size the size of the input image
|
||||
*/
|
||||
CV_WRAP virtual void setInputSize(const Size& input_size) = 0;
|
||||
|
||||
CV_WRAP virtual Size getInputSize() = 0;
|
||||
|
||||
/** @brief Set the score threshold to filter out bounding boxes of score less than the given value
|
||||
*
|
||||
* @param score_threshold threshold for filtering out bounding boxes
|
||||
*/
|
||||
CV_WRAP virtual void setScoreThreshold(float score_threshold) = 0;
|
||||
|
||||
CV_WRAP virtual float getScoreThreshold() = 0;
|
||||
|
||||
/** @brief Set the Non-maximum-suppression threshold to suppress bounding boxes that have IoU greater than the given value
|
||||
*
|
||||
* @param nms_threshold threshold for NMS operation
|
||||
*/
|
||||
CV_WRAP virtual void setNMSThreshold(float nms_threshold) = 0;
|
||||
|
||||
CV_WRAP virtual float getNMSThreshold() = 0;
|
||||
|
||||
/** @brief Set the number of bounding boxes preserved before NMS
|
||||
*
|
||||
* @param top_k the number of bounding boxes to preserve from top rank based on score
|
||||
*/
|
||||
CV_WRAP virtual void setTopK(int top_k) = 0;
|
||||
|
||||
CV_WRAP virtual int getTopK() = 0;
|
||||
|
||||
/** @brief A simple interface to detect face from given image
|
||||
*
|
||||
* @param image an image to detect
|
||||
* @param faces detection results stored in a cv::Mat
|
||||
*/
|
||||
CV_WRAP virtual int detect(InputArray image, OutputArray faces) = 0;
|
||||
|
||||
/** @brief Creates an instance of this class with given parameters
|
||||
*
|
||||
* @param model the path to the requested model
|
||||
* @param config the path to the config file for compability, which is not requested for ONNX models
|
||||
* @param input_size the size of the input image
|
||||
* @param score_threshold the threshold to filter out bounding boxes of score smaller than the given value
|
||||
* @param nms_threshold the threshold to suppress bounding boxes of IoU bigger than the given value
|
||||
* @param top_k keep top K bboxes before NMS
|
||||
* @param backend_id the id of backend
|
||||
* @param target_id the id of target device
|
||||
*/
|
||||
CV_WRAP static Ptr<FaceDetectorYN> create(const String& model,
|
||||
const String& config,
|
||||
const Size& input_size,
|
||||
float score_threshold = 0.9f,
|
||||
float nms_threshold = 0.3f,
|
||||
int top_k = 5000,
|
||||
int backend_id = 0,
|
||||
int target_id = 0);
|
||||
};
|
||||
|
||||
/** @brief DNN-based face recognizer, model download link: https://drive.google.com/file/d/1ClK9WiB492c5OZFKveF3XiHCejoOxINW/view.
|
||||
*/
|
||||
class CV_EXPORTS_W FaceRecognizerSF
|
||||
{
|
||||
public:
|
||||
virtual ~FaceRecognizerSF() {};
|
||||
|
||||
/** @brief Definition of distance used for calculating the distance between two face features
|
||||
*/
|
||||
enum DisType { FR_COSINE=0, FR_NORM_L2=1 };
|
||||
|
||||
/** @brief Aligning image to put face on the standard position
|
||||
* @param src_img input image
|
||||
* @param face_box the detection result used for indicate face in input image
|
||||
* @param aligned_img output aligned image
|
||||
*/
|
||||
CV_WRAP virtual void alignCrop(InputArray src_img, InputArray face_box, OutputArray aligned_img) const = 0;
|
||||
|
||||
/** @brief Extracting face feature from aligned image
|
||||
* @param aligned_img input aligned image
|
||||
* @param face_feature output face feature
|
||||
*/
|
||||
CV_WRAP virtual void feature(InputArray aligned_img, OutputArray face_feature) = 0;
|
||||
|
||||
/** @brief Calculating the distance between two face features
|
||||
* @param _face_feature1 the first input feature
|
||||
* @param _face_feature2 the second input feature of the same size and the same type as _face_feature1
|
||||
* @param dis_type defining the similarity with optional values "FR_OSINE" or "FR_NORM_L2"
|
||||
*/
|
||||
CV_WRAP virtual double match(InputArray _face_feature1, InputArray _face_feature2, int dis_type = FaceRecognizerSF::FR_COSINE) const = 0;
|
||||
|
||||
/** @brief Creates an instance of this class with given parameters
|
||||
* @param model the path of the onnx model used for face recognition
|
||||
* @param config the path to the config file for compability, which is not requested for ONNX models
|
||||
* @param backend_id the id of backend
|
||||
* @param target_id the id of target device
|
||||
*/
|
||||
CV_WRAP static Ptr<FaceRecognizerSF> create(const String& model, const String& config, int backend_id = 0, int target_id = 0);
|
||||
};
|
||||
|
||||
} // namespace cv
|
||||
|
||||
#endif
|
48
3rdparty/opencv-4.5.4/modules/objdetect/include/opencv2/objdetect/objdetect.hpp
vendored
Normal file
48
3rdparty/opencv-4.5.4/modules/objdetect/include/opencv2/objdetect/objdetect.hpp
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
/*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.
|
||||
// Copyright (C) 2013, OpenCV Foundation, 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*/
|
||||
|
||||
#ifdef __OPENCV_BUILD
|
||||
#error this is a compatibility header which should not be used inside the OpenCV library
|
||||
#endif
|
||||
|
||||
#include "opencv2/objdetect.hpp"
|
104
3rdparty/opencv-4.5.4/modules/objdetect/misc/java/test/CascadeClassifierTest.java
vendored
Normal file
104
3rdparty/opencv-4.5.4/modules/objdetect/misc/java/test/CascadeClassifierTest.java
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
package org.opencv.test.objdetect;
|
||||
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.core.MatOfRect;
|
||||
import org.opencv.core.Size;
|
||||
import org.opencv.imgproc.Imgproc;
|
||||
import org.opencv.objdetect.CascadeClassifier;
|
||||
import org.opencv.objdetect.Objdetect;
|
||||
import org.opencv.test.OpenCVTestCase;
|
||||
import org.opencv.test.OpenCVTestRunner;
|
||||
|
||||
public class CascadeClassifierTest extends OpenCVTestCase {
|
||||
|
||||
private CascadeClassifier cc;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
cc = null;
|
||||
}
|
||||
|
||||
public void testCascadeClassifier() {
|
||||
cc = new CascadeClassifier();
|
||||
assertNotNull(cc);
|
||||
}
|
||||
|
||||
public void testCascadeClassifierString() {
|
||||
cc = new CascadeClassifier(OpenCVTestRunner.LBPCASCADE_FRONTALFACE_PATH);
|
||||
assertNotNull(cc);
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRect() {
|
||||
CascadeClassifier cc = new CascadeClassifier(OpenCVTestRunner.LBPCASCADE_FRONTALFACE_PATH);
|
||||
MatOfRect faces = new MatOfRect();
|
||||
|
||||
Mat greyLena = new Mat();
|
||||
Imgproc.cvtColor(rgbLena, greyLena, Imgproc.COLOR_RGB2GRAY);
|
||||
Imgproc.equalizeHist(greyLena, greyLena);
|
||||
|
||||
cc.detectMultiScale(greyLena, faces, 1.1, 3, Objdetect.CASCADE_SCALE_IMAGE, new Size(30, 30), new Size());
|
||||
assertEquals(1, faces.total());
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectDouble() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectDoubleInt() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectDoubleIntInt() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectDoubleIntIntSize() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectDoubleIntIntSizeSize() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectListOfIntegerListOfDouble() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectListOfIntegerListOfDoubleDouble() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectListOfIntegerListOfDoubleDoubleInt() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectListOfIntegerListOfDoubleDoubleIntInt() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectListOfIntegerListOfDoubleDoubleIntIntSize() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectListOfIntegerListOfDoubleDoubleIntIntSizeSize() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectListOfIntegerListOfDoubleDoubleIntIntSizeSizeBoolean() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testEmpty() {
|
||||
cc = new CascadeClassifier();
|
||||
assertTrue(cc.empty());
|
||||
}
|
||||
|
||||
public void testLoad() {
|
||||
cc = new CascadeClassifier();
|
||||
cc.load(OpenCVTestRunner.LBPCASCADE_FRONTALFACE_PATH);
|
||||
assertFalse(cc.empty());
|
||||
}
|
||||
|
||||
}
|
259
3rdparty/opencv-4.5.4/modules/objdetect/misc/java/test/HOGDescriptorTest.java
vendored
Normal file
259
3rdparty/opencv-4.5.4/modules/objdetect/misc/java/test/HOGDescriptorTest.java
vendored
Normal file
@ -0,0 +1,259 @@
|
||||
package org.opencv.test.objdetect;
|
||||
|
||||
import org.opencv.objdetect.HOGDescriptor;
|
||||
import org.opencv.test.OpenCVTestCase;
|
||||
|
||||
public class HOGDescriptorTest extends OpenCVTestCase {
|
||||
|
||||
public void testCheckDetectorSize() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testComputeGradientMatMatMat() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testComputeGradientMatMatMatSize() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testComputeGradientMatMatMatSizeSize() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testComputeMatListOfFloat() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testComputeMatListOfFloatSize() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testComputeMatListOfFloatSizeSize() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testComputeMatListOfFloatSizeSizeListOfPoint() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMatListOfPoint() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMatListOfPointDouble() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMatListOfPointDoubleSize() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMatListOfPointDoubleSizeSize() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMatListOfPointDoubleSizeSizeListOfPoint() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMatListOfPointListOfDouble() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMatListOfPointListOfDoubleDouble() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMatListOfPointListOfDoubleDoubleSize() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMatListOfPointListOfDoubleDoubleSizeSize() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMatListOfPointListOfDoubleDoubleSizeSizeListOfPoint() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRect() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectDouble() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectDoubleSize() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectDoubleSizeSize() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectDoubleSizeSizeDouble() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectDoubleSizeSizeDoubleDouble() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectDoubleSizeSizeDoubleDoubleBoolean() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectListOfDouble() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectListOfDoubleDouble() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectListOfDoubleDoubleSize() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectListOfDoubleDoubleSizeSize() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectListOfDoubleDoubleSizeSizeDouble() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectListOfDoubleDoubleSizeSizeDoubleDouble() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDetectMultiScaleMatListOfRectListOfDoubleDoubleSizeSizeDoubleDoubleBoolean() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testGet_blockSize() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testGet_blockStride() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testGet_cellSize() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testGet_derivAperture() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testGet_gammaCorrection() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testGet_histogramNormType() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testGet_L2HysThreshold() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testGet_nbins() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testGet_nlevels() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testGet_svmDetector() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testGet_winSigma() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testGet_winSize() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testGetDaimlerPeopleDetector() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testGetDefaultPeopleDetector() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testGetDescriptorSize() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testGetWinSigma() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testHOGDescriptor() {
|
||||
HOGDescriptor hog = new HOGDescriptor();
|
||||
|
||||
assertNotNull(hog);
|
||||
assertEquals(HOGDescriptor.DEFAULT_NLEVELS, hog.get_nlevels());
|
||||
}
|
||||
|
||||
public void testHOGDescriptorSizeSizeSizeSizeInt() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testHOGDescriptorSizeSizeSizeSizeIntInt() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testHOGDescriptorSizeSizeSizeSizeIntIntDouble() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testHOGDescriptorSizeSizeSizeSizeIntIntDoubleInt() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testHOGDescriptorSizeSizeSizeSizeIntIntDoubleIntDouble() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testHOGDescriptorSizeSizeSizeSizeIntIntDoubleIntDoubleBoolean() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testHOGDescriptorSizeSizeSizeSizeIntIntDoubleIntDoubleBooleanInt() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testHOGDescriptorString() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testLoadString() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testLoadStringString() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testSaveString() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testSaveStringString() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testSetSVMDetector() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
}
|
42
3rdparty/opencv-4.5.4/modules/objdetect/misc/java/test/ObjdetectTest.java
vendored
Normal file
42
3rdparty/opencv-4.5.4/modules/objdetect/misc/java/test/ObjdetectTest.java
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
package org.opencv.test.objdetect;
|
||||
|
||||
import org.opencv.test.OpenCVTestCase;
|
||||
|
||||
public class ObjdetectTest extends OpenCVTestCase {
|
||||
|
||||
public void testGroupRectanglesListOfRectListOfIntegerInt() {
|
||||
fail("Not yet implemented");
|
||||
/*
|
||||
final int NUM = 10;
|
||||
MatOfRect rects = new MatOfRect();
|
||||
rects.alloc(NUM);
|
||||
|
||||
for (int i = 0; i < NUM; i++)
|
||||
rects.put(i, 0, 10, 10, 20, 20);
|
||||
|
||||
int groupThreshold = 1;
|
||||
Objdetect.groupRectangles(rects, null, groupThreshold);//TODO: second parameter should not be null
|
||||
assertEquals(1, rects.total());
|
||||
*/
|
||||
}
|
||||
|
||||
public void testGroupRectanglesListOfRectListOfIntegerIntDouble() {
|
||||
fail("Not yet implemented");
|
||||
/*
|
||||
final int NUM = 10;
|
||||
MatOfRect rects = new MatOfRect();
|
||||
rects.alloc(NUM);
|
||||
|
||||
for (int i = 0; i < NUM; i++)
|
||||
rects.put(i, 0, 10, 10, 20, 20);
|
||||
|
||||
for (int i = 0; i < NUM; i++)
|
||||
rects.put(i, 0, 10, 10, 25, 25);
|
||||
|
||||
int groupThreshold = 1;
|
||||
double eps = 0.2;
|
||||
Objdetect.groupRectangles(rects, null, groupThreshold, eps);//TODO: second parameter should not be null
|
||||
assertEquals(2, rects.size());
|
||||
*/
|
||||
}
|
||||
}
|
48
3rdparty/opencv-4.5.4/modules/objdetect/misc/java/test/QRCodeDetectorTest.java
vendored
Normal file
48
3rdparty/opencv-4.5.4/modules/objdetect/misc/java/test/QRCodeDetectorTest.java
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
package org.opencv.test.objdetect;
|
||||
|
||||
import java.util.List;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.objdetect.QRCodeDetector;
|
||||
import org.opencv.imgcodecs.Imgcodecs;
|
||||
import org.opencv.test.OpenCVTestCase;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
public class QRCodeDetectorTest extends OpenCVTestCase {
|
||||
|
||||
private final static String ENV_OPENCV_TEST_DATA_PATH = "OPENCV_TEST_DATA_PATH";
|
||||
private String testDataPath;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
testDataPath = System.getenv(ENV_OPENCV_TEST_DATA_PATH);
|
||||
if (testDataPath == null)
|
||||
throw new Exception(ENV_OPENCV_TEST_DATA_PATH + " has to be defined!");
|
||||
}
|
||||
|
||||
public void testDetectAndDecode() {
|
||||
Mat img = Imgcodecs.imread(testDataPath + "/cv/qrcode/link_ocv.jpg");
|
||||
assertFalse(img.empty());
|
||||
QRCodeDetector detector = new QRCodeDetector();
|
||||
assertNotNull(detector);
|
||||
String output = detector.detectAndDecode(img);
|
||||
assertEquals(output, "https://opencv.org/");
|
||||
}
|
||||
|
||||
public void testDetectAndDecodeMulti() {
|
||||
Mat img = Imgcodecs.imread(testDataPath + "/cv/qrcode/multiple/6_qrcodes.png");
|
||||
assertFalse(img.empty());
|
||||
QRCodeDetector detector = new QRCodeDetector();
|
||||
assertNotNull(detector);
|
||||
List < String > output = new ArrayList< String >();
|
||||
boolean result = detector.detectAndDecodeMulti(img, output);
|
||||
assertTrue(result);
|
||||
assertEquals(output.size(), 6);
|
||||
List < String > expectedResults = Arrays.asList("SKIP", "EXTRA", "TWO STEPS FORWARD", "STEP BACK", "QUESTION", "STEP FORWARD");
|
||||
assertEquals(new HashSet<String>(output), new HashSet<String>(expectedResults));
|
||||
}
|
||||
}
|
8
3rdparty/opencv-4.5.4/modules/objdetect/misc/python/pyopencv_objdetect.hpp
vendored
Normal file
8
3rdparty/opencv-4.5.4/modules/objdetect/misc/python/pyopencv_objdetect.hpp
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
#ifdef HAVE_OPENCV_OBJDETECT
|
||||
|
||||
#include "opencv2/objdetect.hpp"
|
||||
|
||||
typedef HOGDescriptor::HistogramNormType HOGDescriptor_HistogramNormType;
|
||||
typedef HOGDescriptor::DescriptorStorageFormat HOGDescriptor_DescriptorStorageFormat;
|
||||
|
||||
#endif
|
92
3rdparty/opencv-4.5.4/modules/objdetect/misc/python/test/test_facedetect.py
vendored
Normal file
92
3rdparty/opencv-4.5.4/modules/objdetect/misc/python/test/test_facedetect.py
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
face detection using haar cascades
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
|
||||
def detect(img, cascade):
|
||||
rects = cascade.detectMultiScale(img, scaleFactor=1.275, minNeighbors=4, minSize=(30, 30),
|
||||
flags=cv.CASCADE_SCALE_IMAGE)
|
||||
if len(rects) == 0:
|
||||
return []
|
||||
rects[:,2:] += rects[:,:2]
|
||||
return rects
|
||||
|
||||
from tests_common import NewOpenCVTests, intersectionRate
|
||||
|
||||
class facedetect_test(NewOpenCVTests):
|
||||
|
||||
def test_facedetect(self):
|
||||
cascade_fn = self.repoPath + '/data/haarcascades/haarcascade_frontalface_alt.xml'
|
||||
nested_fn = self.repoPath + '/data/haarcascades/haarcascade_eye.xml'
|
||||
|
||||
cascade = cv.CascadeClassifier(cascade_fn)
|
||||
nested = cv.CascadeClassifier(nested_fn)
|
||||
|
||||
samples = ['samples/data/lena.jpg', 'cv/cascadeandhog/images/mona-lisa.png']
|
||||
|
||||
faces = []
|
||||
eyes = []
|
||||
|
||||
testFaces = [
|
||||
#lena
|
||||
[[218, 200, 389, 371],
|
||||
[ 244, 240, 294, 290],
|
||||
[ 309, 246, 352, 289]],
|
||||
|
||||
#lisa
|
||||
[[167, 119, 307, 259],
|
||||
[188, 153, 229, 194],
|
||||
[236, 153, 277, 194]]
|
||||
]
|
||||
|
||||
for sample in samples:
|
||||
|
||||
img = self.get_sample( sample)
|
||||
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
|
||||
gray = cv.GaussianBlur(gray, (5, 5), 0)
|
||||
|
||||
rects = detect(gray, cascade)
|
||||
faces.append(rects)
|
||||
|
||||
if not nested.empty():
|
||||
for x1, y1, x2, y2 in rects:
|
||||
roi = gray[y1:y2, x1:x2]
|
||||
subrects = detect(roi.copy(), nested)
|
||||
|
||||
for rect in subrects:
|
||||
rect[0] += x1
|
||||
rect[2] += x1
|
||||
rect[1] += y1
|
||||
rect[3] += y1
|
||||
|
||||
eyes.append(subrects)
|
||||
|
||||
faces_matches = 0
|
||||
eyes_matches = 0
|
||||
|
||||
eps = 0.8
|
||||
|
||||
for i in range(len(faces)):
|
||||
for j in range(len(testFaces)):
|
||||
if intersectionRate(faces[i][0], testFaces[j][0]) > eps:
|
||||
faces_matches += 1
|
||||
#check eyes
|
||||
if len(eyes[i]) == 2:
|
||||
if intersectionRate(eyes[i][0], testFaces[j][1]) > eps and intersectionRate(eyes[i][1] , testFaces[j][2]) > eps:
|
||||
eyes_matches += 1
|
||||
elif intersectionRate(eyes[i][1], testFaces[j][1]) > eps and intersectionRate(eyes[i][0], testFaces[j][2]) > eps:
|
||||
eyes_matches += 1
|
||||
|
||||
self.assertEqual(faces_matches, 2)
|
||||
self.assertEqual(eyes_matches, 2)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
NewOpenCVTests.bootstrap()
|
65
3rdparty/opencv-4.5.4/modules/objdetect/misc/python/test/test_peopledetect.py
vendored
Normal file
65
3rdparty/opencv-4.5.4/modules/objdetect/misc/python/test/test_peopledetect.py
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
example to detect upright people in images using HOG features
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
|
||||
|
||||
def inside(r, q):
|
||||
rx, ry, rw, rh = r
|
||||
qx, qy, qw, qh = q
|
||||
return rx > qx and ry > qy and rx + rw < qx + qw and ry + rh < qy + qh
|
||||
|
||||
from tests_common import NewOpenCVTests, intersectionRate
|
||||
|
||||
class peopledetect_test(NewOpenCVTests):
|
||||
def test_peopledetect(self):
|
||||
|
||||
hog = cv.HOGDescriptor()
|
||||
hog.setSVMDetector( cv.HOGDescriptor_getDefaultPeopleDetector() )
|
||||
|
||||
dirPath = 'samples/data/'
|
||||
samples = ['basketball1.png', 'basketball2.png']
|
||||
|
||||
testPeople = [
|
||||
[[23, 76, 164, 477], [440, 22, 637, 478]],
|
||||
[[23, 76, 164, 477], [440, 22, 637, 478]]
|
||||
]
|
||||
|
||||
eps = 0.5
|
||||
|
||||
for sample in samples:
|
||||
|
||||
img = self.get_sample(dirPath + sample, 0)
|
||||
|
||||
found, _w = hog.detectMultiScale(img, winStride=(8,8), padding=(32,32), scale=1.05)
|
||||
found_filtered = []
|
||||
for ri, r in enumerate(found):
|
||||
for qi, q in enumerate(found):
|
||||
if ri != qi and inside(r, q):
|
||||
break
|
||||
else:
|
||||
found_filtered.append(r)
|
||||
|
||||
matches = 0
|
||||
|
||||
for i in range(len(found_filtered)):
|
||||
for j in range(len(testPeople)):
|
||||
|
||||
found_rect = (found_filtered[i][0], found_filtered[i][1],
|
||||
found_filtered[i][0] + found_filtered[i][2],
|
||||
found_filtered[i][1] + found_filtered[i][3])
|
||||
|
||||
if intersectionRate(found_rect, testPeople[j][0]) > eps or intersectionRate(found_rect, testPeople[j][1]) > eps:
|
||||
matches += 1
|
||||
|
||||
self.assertGreater(matches, 0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
NewOpenCVTests.bootstrap()
|
52
3rdparty/opencv-4.5.4/modules/objdetect/misc/python/test/test_qrcode_detect.py
vendored
Normal file
52
3rdparty/opencv-4.5.4/modules/objdetect/misc/python/test/test_qrcode_detect.py
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python
|
||||
'''
|
||||
===============================================================================
|
||||
QR code detect and decode pipeline.
|
||||
===============================================================================
|
||||
'''
|
||||
import os
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
class qrcode_detector_test(NewOpenCVTests):
|
||||
|
||||
def test_detect(self):
|
||||
img = cv.imread(os.path.join(self.extraTestDataPath, 'cv/qrcode/link_ocv.jpg'))
|
||||
self.assertFalse(img is None)
|
||||
detector = cv.QRCodeDetector()
|
||||
retval, points = detector.detect(img)
|
||||
self.assertTrue(retval)
|
||||
self.assertEqual(points.shape, (1, 4, 2))
|
||||
|
||||
def test_detect_and_decode(self):
|
||||
img = cv.imread(os.path.join(self.extraTestDataPath, 'cv/qrcode/link_ocv.jpg'))
|
||||
self.assertFalse(img is None)
|
||||
detector = cv.QRCodeDetector()
|
||||
retval, points, straight_qrcode = detector.detectAndDecode(img)
|
||||
self.assertEqual(retval, "https://opencv.org/")
|
||||
self.assertEqual(points.shape, (1, 4, 2))
|
||||
|
||||
def test_detect_multi(self):
|
||||
img = cv.imread(os.path.join(self.extraTestDataPath, 'cv/qrcode/multiple/6_qrcodes.png'))
|
||||
self.assertFalse(img is None)
|
||||
detector = cv.QRCodeDetector()
|
||||
retval, points = detector.detectMulti(img)
|
||||
self.assertTrue(retval)
|
||||
self.assertEqual(points.shape, (6, 4, 2))
|
||||
|
||||
def test_detect_and_decode_multi(self):
|
||||
img = cv.imread(os.path.join(self.extraTestDataPath, 'cv/qrcode/multiple/6_qrcodes.png'))
|
||||
self.assertFalse(img is None)
|
||||
detector = cv.QRCodeDetector()
|
||||
retval, decoded_data, points, straight_qrcode = detector.detectAndDecodeMulti(img)
|
||||
self.assertTrue(retval)
|
||||
self.assertEqual(len(decoded_data), 6)
|
||||
self.assertEqual(decoded_data[0], "TWO STEPS FORWARD")
|
||||
self.assertEqual(decoded_data[1], "EXTRA")
|
||||
self.assertEqual(decoded_data[2], "SKIP")
|
||||
self.assertEqual(decoded_data[3], "STEP FORWARD")
|
||||
self.assertEqual(decoded_data[4], "STEP BACK")
|
||||
self.assertEqual(decoded_data[5], "QUESTION")
|
||||
self.assertEqual(points.shape, (6, 4, 2))
|
61
3rdparty/opencv-4.5.4/modules/objdetect/perf/opencl/perf_cascades.cpp
vendored
Normal file
61
3rdparty/opencv-4.5.4/modules/objdetect/perf/opencl/perf_cascades.cpp
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
#include "../perf_precomp.hpp"
|
||||
#include <opencv2/imgproc.hpp>
|
||||
|
||||
#include "opencv2/ts/ocl_perf.hpp"
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
using namespace perf;
|
||||
|
||||
typedef tuple<std::string, std::string, int> Cascade_Image_MinSize_t;
|
||||
typedef perf::TestBaseWithParam<Cascade_Image_MinSize_t> Cascade_Image_MinSize;
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
OCL_PERF_TEST_P(Cascade_Image_MinSize, CascadeClassifier,
|
||||
testing::Combine(
|
||||
testing::Values( string("cv/cascadeandhog/cascades/haarcascade_frontalface_alt.xml"),
|
||||
string("cv/cascadeandhog/cascades/haarcascade_frontalface_alt2.xml"),
|
||||
string("cv/cascadeandhog/cascades/lbpcascade_frontalface.xml") ),
|
||||
testing::Values( string("cv/shared/lena.png"),
|
||||
string("cv/cascadeandhog/images/bttf301.png"),
|
||||
string("cv/cascadeandhog/images/class57.png") ),
|
||||
testing::Values(30, 64, 90) ) )
|
||||
{
|
||||
const string cascadePath = get<0>(GetParam());
|
||||
const string imagePath = get<1>(GetParam());
|
||||
int min_size = get<2>(GetParam());
|
||||
Size minSize(min_size, min_size);
|
||||
|
||||
CascadeClassifier cc( getDataPath(cascadePath) );
|
||||
if (cc.empty())
|
||||
FAIL() << "Can't load cascade file: " << getDataPath(cascadePath);
|
||||
|
||||
Mat img = imread(getDataPath(imagePath), IMREAD_GRAYSCALE);
|
||||
if (img.empty())
|
||||
FAIL() << "Can't load source image: " << getDataPath(imagePath);
|
||||
|
||||
vector<Rect> faces;
|
||||
|
||||
equalizeHist(img, img);
|
||||
declare.in(img).time(60);
|
||||
|
||||
UMat uimg = img.getUMat(ACCESS_READ);
|
||||
|
||||
while(next())
|
||||
{
|
||||
faces.clear();
|
||||
cvtest::ocl::perf::safeFinish();
|
||||
|
||||
startTimer();
|
||||
cc.detectMultiScale(uimg, faces, 1.1, 3, 0, minSize);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
sort(faces.begin(), faces.end(), comparators::RectLess());
|
||||
SANITY_CHECK(faces, min_size/5);
|
||||
}
|
||||
|
||||
#endif //HAVE_OPENCL
|
||||
|
||||
} // namespace
|
93
3rdparty/opencv-4.5.4/modules/objdetect/perf/opencl/perf_hogdetect.cpp
vendored
Normal file
93
3rdparty/opencv-4.5.4/modules/objdetect/perf/opencl/perf_hogdetect.cpp
vendored
Normal file
@ -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-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Fangfang Bai, fangfang@multicorewareinc.com
|
||||
// Jin Ma, jin@multicorewareinc.com
|
||||
//
|
||||
// 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 "../perf_precomp.hpp"
|
||||
#include "opencv2/ts/ocl_perf.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
///////////// HOG////////////////////////
|
||||
|
||||
struct RectLess
|
||||
{
|
||||
bool operator()(const cv::Rect& a,
|
||||
const cv::Rect& b) const
|
||||
{
|
||||
if (a.x != b.x)
|
||||
return a.x < b.x;
|
||||
else if (a.y != b.y)
|
||||
return a.y < b.y;
|
||||
else if (a.width != b.width)
|
||||
return a.width < b.width;
|
||||
else
|
||||
return a.height < b.height;
|
||||
}
|
||||
};
|
||||
|
||||
OCL_PERF_TEST(HOGFixture, HOG)
|
||||
{
|
||||
UMat src;
|
||||
imread(getDataPath("gpu/hog/road.png"), cv::IMREAD_GRAYSCALE).copyTo(src);
|
||||
ASSERT_FALSE(src.empty());
|
||||
|
||||
vector<cv::Rect> found_locations;
|
||||
declare.in(src);
|
||||
|
||||
HOGDescriptor hog;
|
||||
hog.setSVMDetector(hog.getDefaultPeopleDetector());
|
||||
|
||||
OCL_TEST_CYCLE() hog.detectMultiScale(src, found_locations);
|
||||
|
||||
std::sort(found_locations.begin(), found_locations.end(), RectLess());
|
||||
SANITY_CHECK(found_locations, 3);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
7
3rdparty/opencv-4.5.4/modules/objdetect/perf/perf_main.cpp
vendored
Normal file
7
3rdparty/opencv-4.5.4/modules/objdetect/perf/perf_main.cpp
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
#if defined(HAVE_HPX)
|
||||
#include <hpx/hpx_main.hpp>
|
||||
#endif
|
||||
|
||||
CV_PERF_TEST_MAIN(objdetect)
|
7
3rdparty/opencv-4.5.4/modules/objdetect/perf/perf_precomp.hpp
vendored
Normal file
7
3rdparty/opencv-4.5.4/modules/objdetect/perf/perf_precomp.hpp
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef __OPENCV_PERF_PRECOMP_HPP__
|
||||
#define __OPENCV_PERF_PRECOMP_HPP__
|
||||
|
||||
#include "opencv2/ts.hpp"
|
||||
#include "opencv2/objdetect.hpp"
|
||||
|
||||
#endif
|
193
3rdparty/opencv-4.5.4/modules/objdetect/perf/perf_qrcode_pipeline.cpp
vendored
Normal file
193
3rdparty/opencv-4.5.4/modules/objdetect/perf/perf_qrcode_pipeline.cpp
vendored
Normal file
@ -0,0 +1,193 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
namespace
|
||||
{
|
||||
|
||||
typedef ::perf::TestBaseWithParam< std::string > Perf_Objdetect_QRCode;
|
||||
|
||||
PERF_TEST_P_(Perf_Objdetect_QRCode, detect)
|
||||
{
|
||||
const std::string name_current_image = GetParam();
|
||||
const std::string root = "cv/qrcode/";
|
||||
|
||||
std::string image_path = findDataFile(root + name_current_image);
|
||||
Mat src = imread(image_path, IMREAD_GRAYSCALE), straight_barcode;
|
||||
ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path;
|
||||
|
||||
std::vector< Point > corners;
|
||||
QRCodeDetector qrcode;
|
||||
TEST_CYCLE() ASSERT_TRUE(qrcode.detect(src, corners));
|
||||
SANITY_CHECK(corners);
|
||||
}
|
||||
|
||||
#ifdef HAVE_QUIRC
|
||||
PERF_TEST_P_(Perf_Objdetect_QRCode, decode)
|
||||
{
|
||||
const std::string name_current_image = GetParam();
|
||||
const std::string root = "cv/qrcode/";
|
||||
|
||||
std::string image_path = findDataFile(root + name_current_image);
|
||||
Mat src = imread(image_path, IMREAD_GRAYSCALE), straight_barcode;
|
||||
ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path;
|
||||
|
||||
std::vector< Point > corners;
|
||||
std::string decoded_info;
|
||||
QRCodeDetector qrcode;
|
||||
ASSERT_TRUE(qrcode.detect(src, corners));
|
||||
TEST_CYCLE()
|
||||
{
|
||||
decoded_info = qrcode.decode(src, corners, straight_barcode);
|
||||
ASSERT_FALSE(decoded_info.empty());
|
||||
}
|
||||
|
||||
std::vector<uint8_t> decoded_info_uint8_t(decoded_info.begin(), decoded_info.end());
|
||||
SANITY_CHECK(decoded_info_uint8_t);
|
||||
SANITY_CHECK(straight_barcode);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef ::perf::TestBaseWithParam< std::string > Perf_Objdetect_QRCode_Multi;
|
||||
|
||||
PERF_TEST_P_(Perf_Objdetect_QRCode_Multi, detectMulti)
|
||||
{
|
||||
const std::string name_current_image = GetParam();
|
||||
const std::string root = "cv/qrcode/multiple/";
|
||||
|
||||
std::string image_path = findDataFile(root + name_current_image);
|
||||
Mat src = imread(image_path);
|
||||
ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path;
|
||||
std::vector<Point2f> corners;
|
||||
QRCodeDetector qrcode;
|
||||
TEST_CYCLE() ASSERT_TRUE(qrcode.detectMulti(src, corners));
|
||||
SANITY_CHECK(corners);
|
||||
}
|
||||
|
||||
#ifdef HAVE_QUIRC
|
||||
PERF_TEST_P_(Perf_Objdetect_QRCode_Multi, decodeMulti)
|
||||
{
|
||||
const std::string name_current_image = GetParam();
|
||||
const std::string root = "cv/qrcode/multiple/";
|
||||
|
||||
std::string image_path = findDataFile(root + name_current_image);
|
||||
Mat src = imread(image_path);
|
||||
ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path;
|
||||
QRCodeDetector qrcode;
|
||||
std::vector<Point2f> corners;
|
||||
ASSERT_TRUE(qrcode.detectMulti(src, corners));
|
||||
std::vector<Mat> straight_barcode;
|
||||
std::vector< cv::String > decoded_info;
|
||||
TEST_CYCLE()
|
||||
{
|
||||
ASSERT_TRUE(qrcode.decodeMulti(src, corners, decoded_info, straight_barcode));
|
||||
for(size_t i = 0; i < decoded_info.size(); i++)
|
||||
{
|
||||
ASSERT_FALSE(decoded_info[i].empty());
|
||||
}
|
||||
}
|
||||
std::vector < std::vector< uint8_t > > decoded_info_uint8_t;
|
||||
for(size_t i = 0; i < decoded_info.size(); i++)
|
||||
{
|
||||
std::vector< uint8_t > tmp(decoded_info[i].begin(), decoded_info[i].end());
|
||||
decoded_info_uint8_t.push_back(tmp);
|
||||
}
|
||||
SANITY_CHECK(decoded_info_uint8_t);
|
||||
SANITY_CHECK(straight_barcode);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/*nothing*/, Perf_Objdetect_QRCode,
|
||||
::testing::Values(
|
||||
"version_1_down.jpg", "version_1_left.jpg", "version_1_right.jpg", "version_1_up.jpg", "version_1_top.jpg",
|
||||
"version_5_down.jpg", "version_5_left.jpg", "version_5_right.jpg", "version_5_up.jpg", "version_5_top.jpg",
|
||||
"russian.jpg", "kanji.jpg", "link_github_ocv.jpg", "link_ocv.jpg", "link_wiki_cv.jpg"
|
||||
)
|
||||
);
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/*nothing*/, Perf_Objdetect_QRCode_Multi,
|
||||
::testing::Values(
|
||||
"2_qrcodes.png", "3_close_qrcodes.png", "3_qrcodes.png", "4_qrcodes.png",
|
||||
"5_qrcodes.png", "6_qrcodes.png", "7_qrcodes.png", "8_close_qrcodes.png"
|
||||
)
|
||||
);
|
||||
|
||||
typedef ::perf::TestBaseWithParam< tuple< std::string, Size > > Perf_Objdetect_Not_QRCode;
|
||||
|
||||
PERF_TEST_P_(Perf_Objdetect_Not_QRCode, detect)
|
||||
{
|
||||
std::vector<Point> corners;
|
||||
std::string type_gen = get<0>(GetParam());
|
||||
Size resolution = get<1>(GetParam());
|
||||
Mat not_qr_code(resolution, CV_8UC1, Scalar(0));
|
||||
if (type_gen == "random")
|
||||
{
|
||||
RNG rng;
|
||||
rng.fill(not_qr_code, RNG::UNIFORM, Scalar(0), Scalar(1));
|
||||
}
|
||||
if (type_gen == "chessboard")
|
||||
{
|
||||
uint8_t next_pixel = 0;
|
||||
for (int r = 0; r < not_qr_code.rows * not_qr_code.cols; r++)
|
||||
{
|
||||
int i = r / not_qr_code.cols;
|
||||
int j = r % not_qr_code.cols;
|
||||
not_qr_code.ptr<uchar>(i)[j] = next_pixel;
|
||||
next_pixel = 255 - next_pixel;
|
||||
}
|
||||
}
|
||||
|
||||
QRCodeDetector qrcode;
|
||||
TEST_CYCLE() ASSERT_FALSE(qrcode.detect(not_qr_code, corners));
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
#ifdef HAVE_QUIRC
|
||||
PERF_TEST_P_(Perf_Objdetect_Not_QRCode, decode)
|
||||
{
|
||||
Mat straight_barcode;
|
||||
std::vector< Point > corners;
|
||||
corners.push_back(Point( 0, 0)); corners.push_back(Point( 0, 5));
|
||||
corners.push_back(Point(10, 0)); corners.push_back(Point(15, 15));
|
||||
|
||||
std::string type_gen = get<0>(GetParam());
|
||||
Size resolution = get<1>(GetParam());
|
||||
Mat not_qr_code(resolution, CV_8UC1, Scalar(0));
|
||||
if (type_gen == "random")
|
||||
{
|
||||
RNG rng;
|
||||
rng.fill(not_qr_code, RNG::UNIFORM, Scalar(0), Scalar(1));
|
||||
}
|
||||
if (type_gen == "chessboard")
|
||||
{
|
||||
uint8_t next_pixel = 0;
|
||||
for (int r = 0; r < not_qr_code.rows * not_qr_code.cols; r++)
|
||||
{
|
||||
int i = r / not_qr_code.cols;
|
||||
int j = r % not_qr_code.cols;
|
||||
not_qr_code.ptr<uchar>(i)[j] = next_pixel;
|
||||
next_pixel = 255 - next_pixel;
|
||||
}
|
||||
}
|
||||
|
||||
QRCodeDetector qrcode;
|
||||
TEST_CYCLE() ASSERT_TRUE(qrcode.decode(not_qr_code, corners, straight_barcode).empty());
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
#endif
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/*nothing*/, Perf_Objdetect_Not_QRCode,
|
||||
::testing::Combine(
|
||||
::testing::Values("zero", "random", "chessboard"),
|
||||
::testing::Values(Size(640, 480), Size(1280, 720),
|
||||
Size(1920, 1080), Size(3840, 2160))
|
||||
));
|
||||
|
||||
}
|
||||
} // namespace
|
1763
3rdparty/opencv-4.5.4/modules/objdetect/src/cascadedetect.cpp
vendored
Normal file
1763
3rdparty/opencv-4.5.4/modules/objdetect/src/cascadedetect.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
656
3rdparty/opencv-4.5.4/modules/objdetect/src/cascadedetect.hpp
vendored
Normal file
656
3rdparty/opencv-4.5.4/modules/objdetect/src/cascadedetect.hpp
vendored
Normal file
@ -0,0 +1,656 @@
|
||||
#pragma once
|
||||
|
||||
#include "opencv2/core/ocl.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
void clipObjects(Size sz, std::vector<Rect>& objects,
|
||||
std::vector<int>* a, std::vector<double>* b);
|
||||
|
||||
class FeatureEvaluator
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
HAAR = 0,
|
||||
LBP = 1,
|
||||
HOG = 2
|
||||
};
|
||||
|
||||
struct ScaleData
|
||||
{
|
||||
ScaleData() { scale = 0.f; layer_ofs = ystep = 0; }
|
||||
Size getWorkingSize(Size winSize) const
|
||||
{
|
||||
return Size(std::max(szi.width - winSize.width, 0),
|
||||
std::max(szi.height - winSize.height, 0));
|
||||
}
|
||||
|
||||
float scale;
|
||||
Size szi;
|
||||
int layer_ofs, ystep;
|
||||
};
|
||||
|
||||
virtual ~FeatureEvaluator();
|
||||
|
||||
virtual bool read(const FileNode& node, Size origWinSize);
|
||||
virtual Ptr<FeatureEvaluator> clone() const;
|
||||
virtual int getFeatureType() const;
|
||||
int getNumChannels() const { return nchannels; }
|
||||
|
||||
virtual bool setImage(InputArray img, const std::vector<float>& scales);
|
||||
virtual bool setWindow(Point p, int scaleIdx);
|
||||
const ScaleData& getScaleData(int scaleIdx) const
|
||||
{
|
||||
CV_Assert( 0 <= scaleIdx && scaleIdx < (int)scaleData->size());
|
||||
return scaleData->at(scaleIdx);
|
||||
}
|
||||
virtual void getUMats(std::vector<UMat>& bufs);
|
||||
virtual void getMats();
|
||||
|
||||
Size getLocalSize() const { return localSize; }
|
||||
Size getLocalBufSize() const { return lbufSize; }
|
||||
|
||||
virtual float calcOrd(int featureIdx) const;
|
||||
virtual int calcCat(int featureIdx) const;
|
||||
|
||||
static Ptr<FeatureEvaluator> create(int type);
|
||||
|
||||
protected:
|
||||
enum { SBUF_VALID=1, USBUF_VALID=2 };
|
||||
int sbufFlag;
|
||||
|
||||
bool updateScaleData( Size imgsz, const std::vector<float>& _scales );
|
||||
virtual void computeChannels( int, InputArray ) {}
|
||||
virtual void computeOptFeatures() {}
|
||||
|
||||
Size origWinSize, sbufSize, localSize, lbufSize;
|
||||
int nchannels;
|
||||
Mat sbuf, rbuf;
|
||||
UMat urbuf, usbuf, ufbuf, uscaleData;
|
||||
|
||||
Ptr<std::vector<ScaleData> > scaleData;
|
||||
};
|
||||
|
||||
|
||||
class CascadeClassifierImpl CV_FINAL : public BaseCascadeClassifier
|
||||
{
|
||||
public:
|
||||
CascadeClassifierImpl();
|
||||
virtual ~CascadeClassifierImpl() CV_OVERRIDE;
|
||||
|
||||
bool empty() const CV_OVERRIDE;
|
||||
bool load( const String& filename ) CV_OVERRIDE;
|
||||
void read( const FileNode& node ) CV_OVERRIDE;
|
||||
bool read_( const FileNode& node );
|
||||
void detectMultiScale( InputArray image,
|
||||
CV_OUT std::vector<Rect>& objects,
|
||||
double scaleFactor = 1.1,
|
||||
int minNeighbors = 3, int flags = 0,
|
||||
Size minSize = Size(),
|
||||
Size maxSize = Size() ) CV_OVERRIDE;
|
||||
|
||||
void detectMultiScale( InputArray image,
|
||||
CV_OUT std::vector<Rect>& objects,
|
||||
CV_OUT std::vector<int>& numDetections,
|
||||
double scaleFactor=1.1,
|
||||
int minNeighbors=3, int flags=0,
|
||||
Size minSize=Size(),
|
||||
Size maxSize=Size() ) CV_OVERRIDE;
|
||||
|
||||
void detectMultiScale( InputArray image,
|
||||
CV_OUT std::vector<Rect>& objects,
|
||||
CV_OUT std::vector<int>& rejectLevels,
|
||||
CV_OUT std::vector<double>& levelWeights,
|
||||
double scaleFactor = 1.1,
|
||||
int minNeighbors = 3, int flags = 0,
|
||||
Size minSize = Size(),
|
||||
Size maxSize = Size(),
|
||||
bool outputRejectLevels = false ) CV_OVERRIDE;
|
||||
|
||||
|
||||
bool isOldFormatCascade() const CV_OVERRIDE;
|
||||
Size getOriginalWindowSize() const CV_OVERRIDE;
|
||||
int getFeatureType() const CV_OVERRIDE;
|
||||
void* getOldCascade() CV_OVERRIDE;
|
||||
|
||||
void setMaskGenerator(const Ptr<MaskGenerator>& maskGenerator) CV_OVERRIDE;
|
||||
Ptr<MaskGenerator> getMaskGenerator() CV_OVERRIDE;
|
||||
|
||||
protected:
|
||||
enum { SUM_ALIGN = 64 };
|
||||
|
||||
bool detectSingleScale( InputArray image, Size processingRectSize,
|
||||
int yStep, double factor, std::vector<Rect>& candidates,
|
||||
std::vector<int>& rejectLevels, std::vector<double>& levelWeights,
|
||||
Size sumSize0, bool outputRejectLevels = false );
|
||||
#ifdef HAVE_OPENCL
|
||||
bool ocl_detectMultiScaleNoGrouping( const std::vector<float>& scales,
|
||||
std::vector<Rect>& candidates );
|
||||
#endif
|
||||
void detectMultiScaleNoGrouping( InputArray image, std::vector<Rect>& candidates,
|
||||
std::vector<int>& rejectLevels, std::vector<double>& levelWeights,
|
||||
double scaleFactor, Size minObjectSize, Size maxObjectSize,
|
||||
bool outputRejectLevels = false );
|
||||
|
||||
enum { MAX_FACES = 10000 };
|
||||
enum { BOOST = 0 };
|
||||
enum { DO_CANNY_PRUNING = CASCADE_DO_CANNY_PRUNING,
|
||||
SCALE_IMAGE = CASCADE_SCALE_IMAGE,
|
||||
FIND_BIGGEST_OBJECT = CASCADE_FIND_BIGGEST_OBJECT,
|
||||
DO_ROUGH_SEARCH = CASCADE_DO_ROUGH_SEARCH
|
||||
};
|
||||
|
||||
friend class CascadeClassifierInvoker;
|
||||
friend class SparseCascadeClassifierInvoker;
|
||||
|
||||
template<class FEval>
|
||||
friend int predictOrdered( CascadeClassifierImpl& cascade, Ptr<FeatureEvaluator> &featureEvaluator, double& weight);
|
||||
|
||||
template<class FEval>
|
||||
friend int predictCategorical( CascadeClassifierImpl& cascade, Ptr<FeatureEvaluator> &featureEvaluator, double& weight);
|
||||
|
||||
template<class FEval>
|
||||
friend int predictOrderedStump( CascadeClassifierImpl& cascade, Ptr<FeatureEvaluator> &featureEvaluator, double& weight);
|
||||
|
||||
template<class FEval>
|
||||
friend int predictCategoricalStump( CascadeClassifierImpl& cascade, Ptr<FeatureEvaluator> &featureEvaluator, double& weight);
|
||||
|
||||
int runAt( Ptr<FeatureEvaluator>& feval, Point pt, int scaleIdx, double& weight );
|
||||
|
||||
class Data
|
||||
{
|
||||
public:
|
||||
struct DTreeNode
|
||||
{
|
||||
int featureIdx;
|
||||
float threshold; // for ordered features only
|
||||
int left;
|
||||
int right;
|
||||
};
|
||||
|
||||
struct DTree
|
||||
{
|
||||
int nodeCount;
|
||||
};
|
||||
|
||||
struct Stage
|
||||
{
|
||||
int first;
|
||||
int ntrees;
|
||||
float threshold;
|
||||
};
|
||||
|
||||
struct Stump
|
||||
{
|
||||
Stump() : featureIdx(0), threshold(0), left(0), right(0) { }
|
||||
Stump(int _featureIdx, float _threshold, float _left, float _right)
|
||||
: featureIdx(_featureIdx), threshold(_threshold), left(_left), right(_right) {}
|
||||
|
||||
int featureIdx;
|
||||
float threshold;
|
||||
float left;
|
||||
float right;
|
||||
};
|
||||
|
||||
Data();
|
||||
|
||||
bool read(const FileNode &node);
|
||||
|
||||
int stageType;
|
||||
int featureType;
|
||||
int ncategories;
|
||||
int minNodesPerTree, maxNodesPerTree;
|
||||
Size origWinSize;
|
||||
|
||||
std::vector<Stage> stages;
|
||||
std::vector<DTree> classifiers;
|
||||
std::vector<DTreeNode> nodes;
|
||||
std::vector<float> leaves;
|
||||
std::vector<int> subsets;
|
||||
std::vector<Stump> stumps;
|
||||
};
|
||||
|
||||
Data data;
|
||||
Ptr<FeatureEvaluator> featureEvaluator;
|
||||
Ptr<CvHaarClassifierCascade> oldCascade;
|
||||
|
||||
Ptr<MaskGenerator> maskGenerator;
|
||||
UMat ugrayImage;
|
||||
UMat ufacepos, ustages, unodes, uleaves, usubsets;
|
||||
#ifdef HAVE_OPENCL
|
||||
ocl::Kernel haarKernel, lbpKernel;
|
||||
bool tryOpenCL;
|
||||
#endif
|
||||
|
||||
Mutex mtx;
|
||||
};
|
||||
|
||||
#define CC_CASCADE_PARAMS "cascadeParams"
|
||||
#define CC_STAGE_TYPE "stageType"
|
||||
#define CC_FEATURE_TYPE "featureType"
|
||||
#define CC_HEIGHT "height"
|
||||
#define CC_WIDTH "width"
|
||||
|
||||
#define CC_STAGE_NUM "stageNum"
|
||||
#define CC_STAGES "stages"
|
||||
#define CC_STAGE_PARAMS "stageParams"
|
||||
|
||||
#define CC_BOOST "BOOST"
|
||||
#define CC_MAX_DEPTH "maxDepth"
|
||||
#define CC_WEAK_COUNT "maxWeakCount"
|
||||
#define CC_STAGE_THRESHOLD "stageThreshold"
|
||||
#define CC_WEAK_CLASSIFIERS "weakClassifiers"
|
||||
#define CC_INTERNAL_NODES "internalNodes"
|
||||
#define CC_LEAF_VALUES "leafValues"
|
||||
|
||||
#define CC_FEATURES "features"
|
||||
#define CC_FEATURE_PARAMS "featureParams"
|
||||
#define CC_MAX_CAT_COUNT "maxCatCount"
|
||||
|
||||
#define CC_HAAR "HAAR"
|
||||
#define CC_RECTS "rects"
|
||||
#define CC_TILTED "tilted"
|
||||
|
||||
#define CC_LBP "LBP"
|
||||
#define CC_RECT "rect"
|
||||
|
||||
#define CC_HOG "HOG"
|
||||
|
||||
#define CV_SUM_PTRS( p0, p1, p2, p3, sum, rect, step ) \
|
||||
/* (x, y) */ \
|
||||
(p0) = sum + (rect).x + (step) * (rect).y, \
|
||||
/* (x + w, y) */ \
|
||||
(p1) = sum + (rect).x + (rect).width + (step) * (rect).y, \
|
||||
/* (x, y + h) */ \
|
||||
(p2) = sum + (rect).x + (step) * ((rect).y + (rect).height), \
|
||||
/* (x + w, y + h) */ \
|
||||
(p3) = sum + (rect).x + (rect).width + (step) * ((rect).y + (rect).height)
|
||||
|
||||
#define CV_TILTED_PTRS( p0, p1, p2, p3, tilted, rect, step ) \
|
||||
/* (x, y) */ \
|
||||
(p0) = tilted + (rect).x + (step) * (rect).y, \
|
||||
/* (x - h, y + h) */ \
|
||||
(p1) = tilted + (rect).x - (rect).height + (step) * ((rect).y + (rect).height), \
|
||||
/* (x + w, y + w) */ \
|
||||
(p2) = tilted + (rect).x + (rect).width + (step) * ((rect).y + (rect).width), \
|
||||
/* (x + w - h, y + w + h) */ \
|
||||
(p3) = tilted + (rect).x + (rect).width - (rect).height \
|
||||
+ (step) * ((rect).y + (rect).width + (rect).height)
|
||||
|
||||
#define CALC_SUM_(p0, p1, p2, p3, offset) \
|
||||
((p0)[offset] - (p1)[offset] - (p2)[offset] + (p3)[offset])
|
||||
|
||||
#define CALC_SUM(rect,offset) CALC_SUM_((rect)[0], (rect)[1], (rect)[2], (rect)[3], offset)
|
||||
|
||||
#define CV_SUM_OFS( p0, p1, p2, p3, sum, rect, step ) \
|
||||
/* (x, y) */ \
|
||||
(p0) = sum + (rect).x + (step) * (rect).y, \
|
||||
/* (x + w, y) */ \
|
||||
(p1) = sum + (rect).x + (rect).width + (step) * (rect).y, \
|
||||
/* (x, y + h) */ \
|
||||
(p2) = sum + (rect).x + (step) * ((rect).y + (rect).height), \
|
||||
/* (x + w, y + h) */ \
|
||||
(p3) = sum + (rect).x + (rect).width + (step) * ((rect).y + (rect).height)
|
||||
|
||||
#define CV_TILTED_OFS( p0, p1, p2, p3, tilted, rect, step ) \
|
||||
/* (x, y) */ \
|
||||
(p0) = tilted + (rect).x + (step) * (rect).y, \
|
||||
/* (x - h, y + h) */ \
|
||||
(p1) = tilted + (rect).x - (rect).height + (step) * ((rect).y + (rect).height), \
|
||||
/* (x + w, y + w) */ \
|
||||
(p2) = tilted + (rect).x + (rect).width + (step) * ((rect).y + (rect).width), \
|
||||
/* (x + w - h, y + w + h) */ \
|
||||
(p3) = tilted + (rect).x + (rect).width - (rect).height \
|
||||
+ (step) * ((rect).y + (rect).width + (rect).height)
|
||||
|
||||
#define CALC_SUM_OFS_(p0, p1, p2, p3, ptr) \
|
||||
((ptr)[p0] - (ptr)[p1] - (ptr)[p2] + (ptr)[p3])
|
||||
|
||||
#define CALC_SUM_OFS(rect, ptr) CALC_SUM_OFS_((rect)[0], (rect)[1], (rect)[2], (rect)[3], ptr)
|
||||
|
||||
//---------------------------------------------- HaarEvaluator ---------------------------------------
|
||||
class HaarEvaluator CV_FINAL : public FeatureEvaluator
|
||||
{
|
||||
public:
|
||||
struct Feature
|
||||
{
|
||||
Feature();
|
||||
bool read(const FileNode& node, const Size& origWinSize);
|
||||
|
||||
bool tilted;
|
||||
|
||||
enum { RECT_NUM = 3 };
|
||||
struct RectWeigth
|
||||
{
|
||||
Rect r;
|
||||
float weight;
|
||||
} rect[RECT_NUM];
|
||||
};
|
||||
|
||||
struct OptFeature
|
||||
{
|
||||
OptFeature();
|
||||
|
||||
enum { RECT_NUM = Feature::RECT_NUM };
|
||||
float calc( const int* pwin ) const;
|
||||
void setOffsets( const Feature& _f, int step, int tofs );
|
||||
|
||||
int ofs[RECT_NUM][4];
|
||||
float weight[4];
|
||||
};
|
||||
|
||||
HaarEvaluator();
|
||||
virtual ~HaarEvaluator() CV_OVERRIDE;
|
||||
|
||||
virtual bool read( const FileNode& node, Size origWinSize) CV_OVERRIDE;
|
||||
virtual Ptr<FeatureEvaluator> clone() const CV_OVERRIDE;
|
||||
virtual int getFeatureType() const CV_OVERRIDE { return FeatureEvaluator::HAAR; }
|
||||
|
||||
virtual bool setWindow(Point p, int scaleIdx) CV_OVERRIDE;
|
||||
Rect getNormRect() const;
|
||||
int getSquaresOffset() const;
|
||||
|
||||
float operator()(int featureIdx) const
|
||||
{ return optfeaturesPtr[featureIdx].calc(pwin) * varianceNormFactor; }
|
||||
virtual float calcOrd(int featureIdx) const CV_OVERRIDE
|
||||
{ return (*this)(featureIdx); }
|
||||
|
||||
protected:
|
||||
virtual void computeChannels( int i, InputArray img ) CV_OVERRIDE;
|
||||
virtual void computeOptFeatures() CV_OVERRIDE;
|
||||
|
||||
Ptr<std::vector<Feature> > features;
|
||||
Ptr<std::vector<OptFeature> > optfeatures;
|
||||
Ptr<std::vector<OptFeature> > optfeatures_lbuf;
|
||||
bool hasTiltedFeatures;
|
||||
|
||||
int tofs, sqofs;
|
||||
Vec4i nofs;
|
||||
Rect normrect;
|
||||
const int* pwin;
|
||||
OptFeature* optfeaturesPtr; // optimization
|
||||
float varianceNormFactor;
|
||||
};
|
||||
|
||||
inline HaarEvaluator::Feature :: Feature()
|
||||
{
|
||||
tilted = false;
|
||||
rect[0].r = rect[1].r = rect[2].r = Rect();
|
||||
rect[0].weight = rect[1].weight = rect[2].weight = 0;
|
||||
}
|
||||
|
||||
inline HaarEvaluator::OptFeature :: OptFeature()
|
||||
{
|
||||
weight[0] = weight[1] = weight[2] = 0.f;
|
||||
|
||||
ofs[0][0] = ofs[0][1] = ofs[0][2] = ofs[0][3] =
|
||||
ofs[1][0] = ofs[1][1] = ofs[1][2] = ofs[1][3] =
|
||||
ofs[2][0] = ofs[2][1] = ofs[2][2] = ofs[2][3] = 0;
|
||||
}
|
||||
|
||||
inline float HaarEvaluator::OptFeature :: calc( const int* ptr ) const
|
||||
{
|
||||
float ret = weight[0] * CALC_SUM_OFS(ofs[0], ptr) +
|
||||
weight[1] * CALC_SUM_OFS(ofs[1], ptr);
|
||||
|
||||
if( weight[2] != 0.0f )
|
||||
ret += weight[2] * CALC_SUM_OFS(ofs[2], ptr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//---------------------------------------------- LBPEvaluator -------------------------------------
|
||||
|
||||
class LBPEvaluator CV_FINAL : public FeatureEvaluator
|
||||
{
|
||||
public:
|
||||
struct Feature
|
||||
{
|
||||
Feature();
|
||||
Feature( int x, int y, int _block_w, int _block_h ) :
|
||||
rect(x, y, _block_w, _block_h) {}
|
||||
|
||||
bool read(const FileNode& node, const Size& origWinSize);
|
||||
|
||||
Rect rect; // weight and height for block
|
||||
};
|
||||
|
||||
struct OptFeature
|
||||
{
|
||||
OptFeature();
|
||||
|
||||
int calc( const int* pwin ) const;
|
||||
void setOffsets( const Feature& _f, int step );
|
||||
int ofs[16];
|
||||
};
|
||||
|
||||
LBPEvaluator();
|
||||
virtual ~LBPEvaluator() CV_OVERRIDE;
|
||||
|
||||
virtual bool read( const FileNode& node, Size origWinSize ) CV_OVERRIDE;
|
||||
virtual Ptr<FeatureEvaluator> clone() const CV_OVERRIDE;
|
||||
virtual int getFeatureType() const CV_OVERRIDE { return FeatureEvaluator::LBP; }
|
||||
|
||||
virtual bool setWindow(Point p, int scaleIdx) CV_OVERRIDE;
|
||||
|
||||
int operator()(int featureIdx) const
|
||||
{ return optfeaturesPtr[featureIdx].calc(pwin); }
|
||||
virtual int calcCat(int featureIdx) const CV_OVERRIDE
|
||||
{ return (*this)(featureIdx); }
|
||||
protected:
|
||||
virtual void computeChannels( int i, InputArray img ) CV_OVERRIDE;
|
||||
virtual void computeOptFeatures() CV_OVERRIDE;
|
||||
|
||||
Ptr<std::vector<Feature> > features;
|
||||
Ptr<std::vector<OptFeature> > optfeatures;
|
||||
Ptr<std::vector<OptFeature> > optfeatures_lbuf;
|
||||
OptFeature* optfeaturesPtr; // optimization
|
||||
|
||||
const int* pwin;
|
||||
};
|
||||
|
||||
|
||||
inline LBPEvaluator::Feature :: Feature()
|
||||
{
|
||||
rect = Rect();
|
||||
}
|
||||
|
||||
inline LBPEvaluator::OptFeature :: OptFeature()
|
||||
{
|
||||
for( int i = 0; i < 16; i++ )
|
||||
ofs[i] = 0;
|
||||
}
|
||||
|
||||
inline int LBPEvaluator::OptFeature :: calc( const int* p ) const
|
||||
{
|
||||
int cval = CALC_SUM_OFS_( ofs[5], ofs[6], ofs[9], ofs[10], p );
|
||||
|
||||
return (CALC_SUM_OFS_( ofs[0], ofs[1], ofs[4], ofs[5], p ) >= cval ? 128 : 0) | // 0
|
||||
(CALC_SUM_OFS_( ofs[1], ofs[2], ofs[5], ofs[6], p ) >= cval ? 64 : 0) | // 1
|
||||
(CALC_SUM_OFS_( ofs[2], ofs[3], ofs[6], ofs[7], p ) >= cval ? 32 : 0) | // 2
|
||||
(CALC_SUM_OFS_( ofs[6], ofs[7], ofs[10], ofs[11], p ) >= cval ? 16 : 0) | // 5
|
||||
(CALC_SUM_OFS_( ofs[10], ofs[11], ofs[14], ofs[15], p ) >= cval ? 8 : 0)| // 8
|
||||
(CALC_SUM_OFS_( ofs[9], ofs[10], ofs[13], ofs[14], p ) >= cval ? 4 : 0)| // 7
|
||||
(CALC_SUM_OFS_( ofs[8], ofs[9], ofs[12], ofs[13], p ) >= cval ? 2 : 0)| // 6
|
||||
(CALC_SUM_OFS_( ofs[4], ofs[5], ofs[8], ofs[9], p ) >= cval ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------- predictor functions -------------------------------------
|
||||
|
||||
template<class FEval>
|
||||
inline int predictOrdered( CascadeClassifierImpl& cascade,
|
||||
Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
int nstages = (int)cascade.data.stages.size();
|
||||
int nodeOfs = 0, leafOfs = 0;
|
||||
FEval& featureEvaluator = (FEval&)*_featureEvaluator;
|
||||
float* cascadeLeaves = &cascade.data.leaves[0];
|
||||
CascadeClassifierImpl::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];
|
||||
CascadeClassifierImpl::Data::DTree* cascadeWeaks = &cascade.data.classifiers[0];
|
||||
CascadeClassifierImpl::Data::Stage* cascadeStages = &cascade.data.stages[0];
|
||||
|
||||
for( int si = 0; si < nstages; si++ )
|
||||
{
|
||||
CascadeClassifierImpl::Data::Stage& stage = cascadeStages[si];
|
||||
int wi, ntrees = stage.ntrees;
|
||||
sum = 0;
|
||||
|
||||
for( wi = 0; wi < ntrees; wi++ )
|
||||
{
|
||||
CascadeClassifierImpl::Data::DTree& weak = cascadeWeaks[stage.first + wi];
|
||||
int idx = 0, root = nodeOfs;
|
||||
|
||||
do
|
||||
{
|
||||
CascadeClassifierImpl::Data::DTreeNode& node = cascadeNodes[root + idx];
|
||||
double val = featureEvaluator(node.featureIdx);
|
||||
idx = val < node.threshold ? node.left : node.right;
|
||||
}
|
||||
while( idx > 0 );
|
||||
sum += cascadeLeaves[leafOfs - idx];
|
||||
nodeOfs += weak.nodeCount;
|
||||
leafOfs += weak.nodeCount + 1;
|
||||
}
|
||||
if( sum < stage.threshold )
|
||||
return -si;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<class FEval>
|
||||
inline int predictCategorical( CascadeClassifierImpl& cascade,
|
||||
Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
int nstages = (int)cascade.data.stages.size();
|
||||
int nodeOfs = 0, leafOfs = 0;
|
||||
FEval& featureEvaluator = (FEval&)*_featureEvaluator;
|
||||
size_t subsetSize = (cascade.data.ncategories + 31)/32;
|
||||
int* cascadeSubsets = &cascade.data.subsets[0];
|
||||
float* cascadeLeaves = &cascade.data.leaves[0];
|
||||
CascadeClassifierImpl::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];
|
||||
CascadeClassifierImpl::Data::DTree* cascadeWeaks = &cascade.data.classifiers[0];
|
||||
CascadeClassifierImpl::Data::Stage* cascadeStages = &cascade.data.stages[0];
|
||||
|
||||
for(int si = 0; si < nstages; si++ )
|
||||
{
|
||||
CascadeClassifierImpl::Data::Stage& stage = cascadeStages[si];
|
||||
int wi, ntrees = stage.ntrees;
|
||||
sum = 0;
|
||||
|
||||
for( wi = 0; wi < ntrees; wi++ )
|
||||
{
|
||||
CascadeClassifierImpl::Data::DTree& weak = cascadeWeaks[stage.first + wi];
|
||||
int idx = 0, root = nodeOfs;
|
||||
do
|
||||
{
|
||||
CascadeClassifierImpl::Data::DTreeNode& node = cascadeNodes[root + idx];
|
||||
int c = featureEvaluator(node.featureIdx);
|
||||
const int* subset = &cascadeSubsets[(root + idx)*subsetSize];
|
||||
idx = (subset[c>>5] & (1 << (c & 31))) ? node.left : node.right;
|
||||
}
|
||||
while( idx > 0 );
|
||||
sum += cascadeLeaves[leafOfs - idx];
|
||||
nodeOfs += weak.nodeCount;
|
||||
leafOfs += weak.nodeCount + 1;
|
||||
}
|
||||
if( sum < stage.threshold )
|
||||
return -si;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<class FEval>
|
||||
inline int predictOrderedStump( CascadeClassifierImpl& cascade,
|
||||
Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
CV_Assert(!cascade.data.stumps.empty());
|
||||
FEval& featureEvaluator = (FEval&)*_featureEvaluator;
|
||||
const CascadeClassifierImpl::Data::Stump* cascadeStumps = &cascade.data.stumps[0];
|
||||
const CascadeClassifierImpl::Data::Stage* cascadeStages = &cascade.data.stages[0];
|
||||
|
||||
int nstages = (int)cascade.data.stages.size();
|
||||
double tmp = 0;
|
||||
|
||||
for( int stageIdx = 0; stageIdx < nstages; stageIdx++ )
|
||||
{
|
||||
const CascadeClassifierImpl::Data::Stage& stage = cascadeStages[stageIdx];
|
||||
tmp = 0;
|
||||
|
||||
int ntrees = stage.ntrees;
|
||||
for( int i = 0; i < ntrees; i++ )
|
||||
{
|
||||
const CascadeClassifierImpl::Data::Stump& stump = cascadeStumps[i];
|
||||
double value = featureEvaluator(stump.featureIdx);
|
||||
tmp += value < stump.threshold ? stump.left : stump.right;
|
||||
}
|
||||
|
||||
if( tmp < stage.threshold )
|
||||
{
|
||||
sum = (double)tmp;
|
||||
return -stageIdx;
|
||||
}
|
||||
cascadeStumps += ntrees;
|
||||
}
|
||||
|
||||
sum = (double)tmp;
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<class FEval>
|
||||
inline int predictCategoricalStump( CascadeClassifierImpl& cascade,
|
||||
Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
CV_Assert(!cascade.data.stumps.empty());
|
||||
int nstages = (int)cascade.data.stages.size();
|
||||
FEval& featureEvaluator = (FEval&)*_featureEvaluator;
|
||||
size_t subsetSize = (cascade.data.ncategories + 31)/32;
|
||||
const int* cascadeSubsets = &cascade.data.subsets[0];
|
||||
const CascadeClassifierImpl::Data::Stump* cascadeStumps = &cascade.data.stumps[0];
|
||||
const CascadeClassifierImpl::Data::Stage* cascadeStages = &cascade.data.stages[0];
|
||||
|
||||
double tmp = 0;
|
||||
for( int si = 0; si < nstages; si++ )
|
||||
{
|
||||
const CascadeClassifierImpl::Data::Stage& stage = cascadeStages[si];
|
||||
int wi, ntrees = stage.ntrees;
|
||||
tmp = 0;
|
||||
|
||||
for( wi = 0; wi < ntrees; wi++ )
|
||||
{
|
||||
const CascadeClassifierImpl::Data::Stump& stump = cascadeStumps[wi];
|
||||
int c = featureEvaluator(stump.featureIdx);
|
||||
const int* subset = &cascadeSubsets[wi*subsetSize];
|
||||
tmp += (subset[c>>5] & (1 << (c & 31))) ? stump.left : stump.right;
|
||||
}
|
||||
|
||||
if( tmp < stage.threshold )
|
||||
{
|
||||
sum = tmp;
|
||||
return -si;
|
||||
}
|
||||
|
||||
cascadeStumps += ntrees;
|
||||
cascadeSubsets += ntrees*subsetSize;
|
||||
}
|
||||
|
||||
sum = (double)tmp;
|
||||
return 1;
|
||||
}
|
||||
|
||||
namespace haar_cvt
|
||||
{
|
||||
bool convert(const FileNode& oldcascade_root, FileStorage& newfs);
|
||||
}
|
||||
|
||||
}
|
275
3rdparty/opencv-4.5.4/modules/objdetect/src/cascadedetect_convert.cpp
vendored
Normal file
275
3rdparty/opencv-4.5.4/modules/objdetect/src/cascadedetect_convert.cpp
vendored
Normal file
@ -0,0 +1,275 @@
|
||||
/*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) 2013, Itseez 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 Intel Corporation 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*/
|
||||
|
||||
/* Haar features calculation */
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "cascadedetect.hpp"
|
||||
#include <stdio.h>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
/* field names */
|
||||
|
||||
#define ICV_HAAR_SIZE_NAME "size"
|
||||
#define ICV_HAAR_STAGES_NAME "stages"
|
||||
#define ICV_HAAR_TREES_NAME "trees"
|
||||
#define ICV_HAAR_FEATURE_NAME "feature"
|
||||
#define ICV_HAAR_RECTS_NAME "rects"
|
||||
#define ICV_HAAR_TILTED_NAME "tilted"
|
||||
#define ICV_HAAR_THRESHOLD_NAME "threshold"
|
||||
#define ICV_HAAR_LEFT_NODE_NAME "left_node"
|
||||
#define ICV_HAAR_LEFT_VAL_NAME "left_val"
|
||||
#define ICV_HAAR_RIGHT_NODE_NAME "right_node"
|
||||
#define ICV_HAAR_RIGHT_VAL_NAME "right_val"
|
||||
#define ICV_HAAR_STAGE_THRESHOLD_NAME "stage_threshold"
|
||||
#define ICV_HAAR_PARENT_NAME "parent"
|
||||
#define ICV_HAAR_NEXT_NAME "next"
|
||||
|
||||
namespace haar_cvt
|
||||
{
|
||||
|
||||
struct HaarFeature
|
||||
{
|
||||
enum { RECT_NUM = 3 };
|
||||
|
||||
HaarFeature()
|
||||
{
|
||||
tilted = false;
|
||||
for( int i = 0; i < RECT_NUM; i++ )
|
||||
{
|
||||
rect[i].r = Rect(0,0,0,0);
|
||||
rect[i].weight = 0.f;
|
||||
}
|
||||
}
|
||||
bool tilted;
|
||||
struct
|
||||
{
|
||||
Rect r;
|
||||
float weight;
|
||||
} rect[RECT_NUM];
|
||||
};
|
||||
|
||||
struct HaarClassifierNode
|
||||
{
|
||||
HaarClassifierNode()
|
||||
{
|
||||
f = left = right = 0;
|
||||
threshold = 0.f;
|
||||
}
|
||||
int f, left, right;
|
||||
float threshold;
|
||||
};
|
||||
|
||||
struct HaarClassifier
|
||||
{
|
||||
std::vector<HaarClassifierNode> nodes;
|
||||
std::vector<float> leaves;
|
||||
};
|
||||
|
||||
struct HaarStageClassifier
|
||||
{
|
||||
HaarStageClassifier() : threshold(0) {}
|
||||
|
||||
double threshold;
|
||||
std::vector<HaarClassifier> weaks;
|
||||
};
|
||||
|
||||
bool convert(const FileNode& oldroot, FileStorage& newfs)
|
||||
{
|
||||
FileNode sznode = oldroot[ICV_HAAR_SIZE_NAME];
|
||||
if( sznode.empty() )
|
||||
return false;
|
||||
Size cascadesize;
|
||||
cascadesize.width = (int)sznode[0];
|
||||
cascadesize.height = (int)sznode[1];
|
||||
std::vector<HaarFeature> features;
|
||||
|
||||
int i, j, k, n;
|
||||
|
||||
FileNode stages_seq = oldroot[ICV_HAAR_STAGES_NAME];
|
||||
int nstages = (int)stages_seq.size();
|
||||
std::vector<HaarStageClassifier> stages(nstages);
|
||||
|
||||
for( i = 0; i < nstages; i++ )
|
||||
{
|
||||
FileNode stagenode = stages_seq[i];
|
||||
HaarStageClassifier& stage = stages[i];
|
||||
stage.threshold = (double)stagenode[ICV_HAAR_STAGE_THRESHOLD_NAME];
|
||||
FileNode weaks_seq = stagenode[ICV_HAAR_TREES_NAME];
|
||||
int nweaks = (int)weaks_seq.size();
|
||||
stage.weaks.resize(nweaks);
|
||||
|
||||
for( j = 0; j < nweaks; j++ )
|
||||
{
|
||||
HaarClassifier& weak = stage.weaks[j];
|
||||
FileNode weaknode = weaks_seq[j];
|
||||
int nnodes = (int)weaknode.size();
|
||||
|
||||
for( n = 0; n < nnodes; n++ )
|
||||
{
|
||||
FileNode nnode = weaknode[n];
|
||||
FileNode fnode = nnode[ICV_HAAR_FEATURE_NAME];
|
||||
HaarFeature f;
|
||||
HaarClassifierNode node;
|
||||
node.f = (int)features.size();
|
||||
f.tilted = (int)fnode[ICV_HAAR_TILTED_NAME] != 0;
|
||||
FileNode rects_seq = fnode[ICV_HAAR_RECTS_NAME];
|
||||
int nrects = (int)rects_seq.size();
|
||||
|
||||
for( k = 0; k < nrects; k++ )
|
||||
{
|
||||
FileNode rnode = rects_seq[k];
|
||||
f.rect[k].r.x = (int)rnode[0];
|
||||
f.rect[k].r.y = (int)rnode[1];
|
||||
f.rect[k].r.width = (int)rnode[2];
|
||||
f.rect[k].r.height = (int)rnode[3];
|
||||
f.rect[k].weight = (float)rnode[4];
|
||||
}
|
||||
features.push_back(f);
|
||||
node.threshold = nnode[ICV_HAAR_THRESHOLD_NAME];
|
||||
FileNode leftValNode = nnode[ICV_HAAR_LEFT_VAL_NAME];
|
||||
if( !leftValNode.empty() )
|
||||
{
|
||||
node.left = -(int)weak.leaves.size();
|
||||
weak.leaves.push_back((float)leftValNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
node.left = (int)nnode[ICV_HAAR_LEFT_NODE_NAME];
|
||||
}
|
||||
FileNode rightValNode = nnode[ICV_HAAR_RIGHT_VAL_NAME];
|
||||
if( !rightValNode.empty() )
|
||||
{
|
||||
node.right = -(int)weak.leaves.size();
|
||||
weak.leaves.push_back((float)rightValNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
node.right = (int)nnode[ICV_HAAR_RIGHT_NODE_NAME];
|
||||
}
|
||||
weak.nodes.push_back(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int maxWeakCount = 0, nfeatures = (int)features.size();
|
||||
for( i = 0; i < nstages; i++ )
|
||||
maxWeakCount = std::max(maxWeakCount, (int)stages[i].weaks.size());
|
||||
|
||||
newfs << "cascade" << "{:opencv-cascade-classifier"
|
||||
<< "stageType" << "BOOST"
|
||||
<< "featureType" << "HAAR"
|
||||
<< "width" << cascadesize.width
|
||||
<< "height" << cascadesize.height
|
||||
<< "stageParams" << "{"
|
||||
<< "maxWeakCount" << (int)maxWeakCount
|
||||
<< "}"
|
||||
<< "featureParams" << "{"
|
||||
<< "maxCatCount" << 0
|
||||
<< "}"
|
||||
<< "stageNum" << (int)nstages
|
||||
<< "stages" << "[";
|
||||
|
||||
for( i = 0; i < nstages; i++ )
|
||||
{
|
||||
int nweaks = (int)stages[i].weaks.size();
|
||||
newfs << "{" << "maxWeakCount" << (int)nweaks
|
||||
<< "stageThreshold" << stages[i].threshold
|
||||
<< "weakClassifiers" << "[";
|
||||
for( j = 0; j < nweaks; j++ )
|
||||
{
|
||||
const HaarClassifier& c = stages[i].weaks[j];
|
||||
newfs << "{" << "internalNodes" << "[:";
|
||||
int nnodes = (int)c.nodes.size(), nleaves = (int)c.leaves.size();
|
||||
for( k = 0; k < nnodes; k++ )
|
||||
newfs << c.nodes[k].left << c.nodes[k].right
|
||||
<< c.nodes[k].f << c.nodes[k].threshold;
|
||||
newfs << "]" << "leafValues" << "[:";
|
||||
for( k = 0; k < nleaves; k++ )
|
||||
newfs << c.leaves[k];
|
||||
newfs << "]" << "}";
|
||||
}
|
||||
newfs << "]" << "}";
|
||||
}
|
||||
|
||||
newfs << "]"
|
||||
<< "features" << "[";
|
||||
|
||||
for( i = 0; i < nfeatures; i++ )
|
||||
{
|
||||
const HaarFeature& f = features[i];
|
||||
newfs << "{" << "rects" << "[";
|
||||
for( j = 0; j < HaarFeature::RECT_NUM; j++ )
|
||||
{
|
||||
if( j >= 2 && fabs(f.rect[j].weight) < FLT_EPSILON )
|
||||
break;
|
||||
newfs << "[:" << f.rect[j].r.x << f.rect[j].r.y <<
|
||||
f.rect[j].r.width << f.rect[j].r.height << f.rect[j].weight << "]";
|
||||
}
|
||||
newfs << "]";
|
||||
if( f.tilted )
|
||||
newfs << "tilted" << 1;
|
||||
newfs << "}";
|
||||
}
|
||||
|
||||
newfs << "]" << "}";
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool CascadeClassifier::convert(const String& oldcascade, const String& newcascade)
|
||||
{
|
||||
FileStorage oldfs(oldcascade, FileStorage::READ);
|
||||
FileStorage newfs(newcascade, FileStorage::WRITE);
|
||||
if( !oldfs.isOpened() || !newfs.isOpened() )
|
||||
return false;
|
||||
FileNode oldroot = oldfs.getFirstTopLevelNode();
|
||||
|
||||
bool ok = haar_cvt::convert(oldroot, newfs);
|
||||
if( !ok && newcascade.size() > 0 )
|
||||
remove(newcascade.c_str());
|
||||
return ok;
|
||||
}
|
||||
|
||||
}
|
885
3rdparty/opencv-4.5.4/modules/objdetect/src/detection_based_tracker.cpp
vendored
Normal file
885
3rdparty/opencv-4.5.4/modules/objdetect/src/detection_based_tracker.cpp
vendored
Normal file
@ -0,0 +1,885 @@
|
||||
/*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.
|
||||
// Copyright (C) 2013, OpenCV Foundation, 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 "opencv2/core/utility.hpp"
|
||||
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
#if defined(DEBUG) || defined(_DEBUG)
|
||||
#undef DEBUGLOGS
|
||||
#define DEBUGLOGS 1
|
||||
#endif
|
||||
|
||||
#ifndef DEBUGLOGS
|
||||
#define DEBUGLOGS 0
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <android/log.h>
|
||||
#define LOG_TAG "OBJECT_DETECTOR"
|
||||
#define LOGD0(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
|
||||
#define LOGI0(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
|
||||
#define LOGW0(...) ((void)__android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
|
||||
#define LOGE0(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
|
||||
#else
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define LOGD0(_str, ...) (printf(_str , ## __VA_ARGS__), printf("\n"), fflush(stdout))
|
||||
#define LOGI0(_str, ...) (printf(_str , ## __VA_ARGS__), printf("\n"), fflush(stdout))
|
||||
#define LOGW0(_str, ...) (printf(_str , ## __VA_ARGS__), printf("\n"), fflush(stdout))
|
||||
#define LOGE0(_str, ...) (printf(_str , ## __VA_ARGS__), printf("\n"), fflush(stdout))
|
||||
#endif //__ANDROID__
|
||||
|
||||
#if DEBUGLOGS
|
||||
#define LOGD(_str, ...) LOGD0(_str , ## __VA_ARGS__)
|
||||
#define LOGI(_str, ...) LOGI0(_str , ## __VA_ARGS__)
|
||||
#define LOGW(_str, ...) LOGW0(_str , ## __VA_ARGS__)
|
||||
#define LOGE(_str, ...) LOGE0(_str , ## __VA_ARGS__)
|
||||
#else
|
||||
#define LOGD(...)
|
||||
#define LOGI(...)
|
||||
#define LOGW(...)
|
||||
#define LOGE(...)
|
||||
#endif //DEBUGLOGS
|
||||
|
||||
|
||||
using namespace cv;
|
||||
|
||||
static inline cv::Point2f centerRect(const cv::Rect& r)
|
||||
{
|
||||
return cv::Point2f(r.x+((float)r.width)/2, r.y+((float)r.height)/2);
|
||||
}
|
||||
|
||||
static inline cv::Rect scale_rect(const cv::Rect& r, float scale)
|
||||
{
|
||||
cv::Point2f m=centerRect(r);
|
||||
float width = r.width * scale;
|
||||
float height = r.height * scale;
|
||||
int x=cvRound(m.x - width/2);
|
||||
int y=cvRound(m.y - height/2);
|
||||
|
||||
return cv::Rect(x, y, cvRound(width), cvRound(height));
|
||||
}
|
||||
|
||||
namespace cv
|
||||
{
|
||||
void* workcycleObjectDetectorFunction(void* p);
|
||||
}
|
||||
|
||||
class cv::DetectionBasedTracker::SeparateDetectionWork
|
||||
{
|
||||
public:
|
||||
SeparateDetectionWork(cv::DetectionBasedTracker& _detectionBasedTracker, cv::Ptr<DetectionBasedTracker::IDetector> _detector,
|
||||
const cv::DetectionBasedTracker::Parameters& params);
|
||||
virtual ~SeparateDetectionWork();
|
||||
bool communicateWithDetectingThread(const Mat& imageGray, std::vector<Rect>& rectsWhereRegions);
|
||||
bool run();
|
||||
void stop();
|
||||
void resetTracking();
|
||||
|
||||
inline bool isWorking()
|
||||
{
|
||||
return (stateThread==STATE_THREAD_WORKING_SLEEPING) || (stateThread==STATE_THREAD_WORKING_WITH_IMAGE);
|
||||
}
|
||||
void setParameters(const cv::DetectionBasedTracker::Parameters& params)
|
||||
{
|
||||
std::unique_lock<std::mutex> mtx_lock(mtx);
|
||||
parameters = params;
|
||||
}
|
||||
|
||||
inline void init()
|
||||
{
|
||||
std::unique_lock<std::mutex> mtx_lock(mtx);
|
||||
stateThread = STATE_THREAD_STOPPED;
|
||||
isObjectDetectingReady = false;
|
||||
shouldObjectDetectingResultsBeForgot = false;
|
||||
objectDetectorThreadStartStop.notify_one();
|
||||
}
|
||||
protected:
|
||||
|
||||
DetectionBasedTracker& detectionBasedTracker;
|
||||
cv::Ptr<DetectionBasedTracker::IDetector> cascadeInThread;
|
||||
std::thread second_workthread;
|
||||
std::mutex mtx;
|
||||
std::condition_variable objectDetectorRun;
|
||||
std::condition_variable objectDetectorThreadStartStop;
|
||||
std::vector<cv::Rect> resultDetect;
|
||||
volatile bool isObjectDetectingReady;
|
||||
volatile bool shouldObjectDetectingResultsBeForgot;
|
||||
|
||||
enum StateSeparatedThread {
|
||||
STATE_THREAD_STOPPED=0,
|
||||
STATE_THREAD_WORKING_SLEEPING,
|
||||
STATE_THREAD_WORKING_WITH_IMAGE,
|
||||
STATE_THREAD_WORKING,
|
||||
STATE_THREAD_STOPPING
|
||||
};
|
||||
volatile StateSeparatedThread stateThread;
|
||||
|
||||
cv::Mat imageSeparateDetecting;
|
||||
|
||||
void workcycleObjectDetector();
|
||||
friend void* workcycleObjectDetectorFunction(void* p);
|
||||
|
||||
long long timeWhenDetectingThreadStartedWork;
|
||||
cv::DetectionBasedTracker::Parameters parameters;
|
||||
};
|
||||
|
||||
cv::DetectionBasedTracker::SeparateDetectionWork::SeparateDetectionWork(DetectionBasedTracker& _detectionBasedTracker, cv::Ptr<DetectionBasedTracker::IDetector> _detector,
|
||||
const cv::DetectionBasedTracker::Parameters& params)
|
||||
:detectionBasedTracker(_detectionBasedTracker),
|
||||
cascadeInThread(),
|
||||
isObjectDetectingReady(false),
|
||||
shouldObjectDetectingResultsBeForgot(false),
|
||||
stateThread(STATE_THREAD_STOPPED),
|
||||
timeWhenDetectingThreadStartedWork(-1),
|
||||
parameters(params)
|
||||
{
|
||||
CV_Assert(_detector);
|
||||
|
||||
cascadeInThread = _detector;
|
||||
}
|
||||
|
||||
cv::DetectionBasedTracker::SeparateDetectionWork::~SeparateDetectionWork()
|
||||
{
|
||||
if(stateThread!=STATE_THREAD_STOPPED) {
|
||||
LOGE("\n\n\nATTENTION!!! dangerous algorithm error: destructor DetectionBasedTracker::DetectionBasedTracker::~SeparateDetectionWork is called before stopping the workthread");
|
||||
}
|
||||
second_workthread.join();
|
||||
}
|
||||
bool cv::DetectionBasedTracker::SeparateDetectionWork::run()
|
||||
{
|
||||
LOGD("DetectionBasedTracker::SeparateDetectionWork::run() --- start");
|
||||
std::unique_lock<std::mutex> mtx_lock(mtx);
|
||||
// unlocked when leaving scope
|
||||
if (stateThread != STATE_THREAD_STOPPED) {
|
||||
LOGE("DetectionBasedTracker::SeparateDetectionWork::run is called while the previous run is not stopped");
|
||||
return false;
|
||||
}
|
||||
stateThread=STATE_THREAD_WORKING_SLEEPING;
|
||||
second_workthread = std::thread(workcycleObjectDetectorFunction, (void*)this); //TODO: add attributes?
|
||||
objectDetectorThreadStartStop.wait(mtx_lock);
|
||||
LOGD("DetectionBasedTracker::SeparateDetectionWork::run --- end");
|
||||
return true;
|
||||
}
|
||||
|
||||
#define CATCH_ALL_AND_LOG(_block) \
|
||||
try { \
|
||||
_block; \
|
||||
} \
|
||||
catch(const cv::Exception& e) { \
|
||||
LOGE0("\n %s: ERROR: OpenCV Exception caught: \n'%s'\n\n", CV_Func, e.what()); \
|
||||
} catch(const std::exception& e) { \
|
||||
LOGE0("\n %s: ERROR: Exception caught: \n'%s'\n\n", CV_Func, e.what()); \
|
||||
} catch(...) { \
|
||||
LOGE0("\n %s: ERROR: UNKNOWN Exception caught\n\n", CV_Func); \
|
||||
}
|
||||
|
||||
void* cv::workcycleObjectDetectorFunction(void* p)
|
||||
{
|
||||
CATCH_ALL_AND_LOG({ ((cv::DetectionBasedTracker::SeparateDetectionWork*)p)->workcycleObjectDetector(); });
|
||||
try{
|
||||
((cv::DetectionBasedTracker::SeparateDetectionWork*)p)->init();
|
||||
} catch(...) {
|
||||
LOGE0("DetectionBasedTracker: workcycleObjectDetectorFunction: ERROR concerning pointer, received as the function parameter");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void cv::DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector()
|
||||
{
|
||||
static double freq = getTickFrequency();
|
||||
LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- start");
|
||||
std::vector<Rect> objects;
|
||||
|
||||
CV_Assert(stateThread==STATE_THREAD_WORKING_SLEEPING);
|
||||
std::unique_lock<std::mutex> mtx_lock(mtx);
|
||||
{
|
||||
objectDetectorThreadStartStop.notify_one();
|
||||
LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- before waiting");
|
||||
CV_Assert(stateThread==STATE_THREAD_WORKING_SLEEPING);
|
||||
objectDetectorRun.wait(mtx_lock);
|
||||
if (isWorking()) {
|
||||
stateThread=STATE_THREAD_WORKING_WITH_IMAGE;
|
||||
}
|
||||
LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- after waiting");
|
||||
}
|
||||
mtx_lock.unlock();
|
||||
|
||||
bool isFirstStep=true;
|
||||
|
||||
isObjectDetectingReady=false;
|
||||
|
||||
while(isWorking())
|
||||
{
|
||||
LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- next step");
|
||||
|
||||
if (! isFirstStep) {
|
||||
LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- before waiting");
|
||||
CV_Assert(stateThread==STATE_THREAD_WORKING_SLEEPING);
|
||||
mtx_lock.lock();
|
||||
if (!isWorking()) {//it is a rare case, but may cause a crash
|
||||
LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- go out from the workcycle from inner part of lock just before waiting");
|
||||
mtx_lock.unlock();
|
||||
break;
|
||||
}
|
||||
CV_Assert(stateThread==STATE_THREAD_WORKING_SLEEPING);
|
||||
objectDetectorRun.wait(mtx_lock);
|
||||
if (isWorking()) {
|
||||
stateThread=STATE_THREAD_WORKING_WITH_IMAGE;
|
||||
}
|
||||
mtx_lock.unlock();
|
||||
|
||||
LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- after waiting");
|
||||
} else {
|
||||
isFirstStep=false;
|
||||
}
|
||||
|
||||
if (!isWorking()) {
|
||||
LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- go out from the workcycle just after waiting");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (imageSeparateDetecting.empty()) {
|
||||
LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- imageSeparateDetecting is empty, continue");
|
||||
continue;
|
||||
}
|
||||
LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- start handling imageSeparateDetecting, img.size=%dx%d, img.data=0x%p",
|
||||
imageSeparateDetecting.size().width, imageSeparateDetecting.size().height, (void*)imageSeparateDetecting.data);
|
||||
|
||||
|
||||
int64 t1_detect=getTickCount();
|
||||
|
||||
cascadeInThread->detect(imageSeparateDetecting, objects);
|
||||
|
||||
/*cascadeInThread.detectMultiScale( imageSeparateDetecting, objects,
|
||||
detectionBasedTracker.parameters.scaleFactor, detectionBasedTracker.parameters.minNeighbors, 0
|
||||
|CV_HAAR_SCALE_IMAGE
|
||||
,
|
||||
min_objectSize,
|
||||
max_objectSize
|
||||
);
|
||||
*/
|
||||
|
||||
LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- end handling imageSeparateDetecting");
|
||||
|
||||
if (!isWorking()) {
|
||||
LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- go out from the workcycle just after detecting");
|
||||
break;
|
||||
}
|
||||
|
||||
int64 t2_detect = getTickCount();
|
||||
int64 dt_detect = t2_detect-t1_detect;
|
||||
double dt_detect_ms=((double)dt_detect)/freq * 1000.0;
|
||||
(void)(dt_detect_ms);
|
||||
|
||||
LOGI("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- objects num==%d, t_ms=%.4f", (int)objects.size(), dt_detect_ms);
|
||||
mtx_lock.lock();
|
||||
if (!shouldObjectDetectingResultsBeForgot) {
|
||||
resultDetect=objects;
|
||||
isObjectDetectingReady=true;
|
||||
} else { //shouldObjectDetectingResultsBeForgot==true
|
||||
resultDetect.clear();
|
||||
isObjectDetectingReady=false;
|
||||
shouldObjectDetectingResultsBeForgot=false;
|
||||
}
|
||||
if(isWorking()) {
|
||||
stateThread=STATE_THREAD_WORKING_SLEEPING;
|
||||
}
|
||||
mtx_lock.unlock();
|
||||
|
||||
objects.clear();
|
||||
}// while(isWorking())
|
||||
|
||||
LOGI("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector: Returning");
|
||||
}
|
||||
|
||||
void cv::DetectionBasedTracker::SeparateDetectionWork::stop()
|
||||
{
|
||||
//FIXME: TODO: should add quickStop functionality
|
||||
std::unique_lock<std::mutex> mtx_lock(mtx);
|
||||
if (!isWorking()) {
|
||||
mtx_lock.unlock();
|
||||
LOGE("SimpleHighguiDemoCore::stop is called but the SimpleHighguiDemoCore pthread is not active");
|
||||
stateThread = STATE_THREAD_STOPPING;
|
||||
return;
|
||||
}
|
||||
stateThread=STATE_THREAD_STOPPING;
|
||||
LOGD("DetectionBasedTracker::SeparateDetectionWork::stop: before going to sleep to wait for the signal from the workthread");
|
||||
objectDetectorRun.notify_one();
|
||||
objectDetectorThreadStartStop.wait(mtx_lock);
|
||||
LOGD("DetectionBasedTracker::SeparateDetectionWork::stop: after receiving the signal from the workthread, stateThread=%d", (int)stateThread);
|
||||
mtx_lock.unlock();
|
||||
}
|
||||
|
||||
void cv::DetectionBasedTracker::SeparateDetectionWork::resetTracking()
|
||||
{
|
||||
LOGD("DetectionBasedTracker::SeparateDetectionWork::resetTracking");
|
||||
std::unique_lock<std::mutex> mtx_lock(mtx);
|
||||
|
||||
if (stateThread == STATE_THREAD_WORKING_WITH_IMAGE) {
|
||||
LOGD("DetectionBasedTracker::SeparateDetectionWork::resetTracking: since workthread is detecting objects at the moment, we should make cascadeInThread stop detecting and forget the detecting results");
|
||||
shouldObjectDetectingResultsBeForgot=true;
|
||||
//cascadeInThread.setStopFlag();//FIXME: TODO: this feature also should be contributed to OpenCV
|
||||
} else {
|
||||
LOGD("DetectionBasedTracker::SeparateDetectionWork::resetTracking: since workthread is NOT detecting objects at the moment, we should NOT make any additional actions");
|
||||
}
|
||||
|
||||
resultDetect.clear();
|
||||
isObjectDetectingReady=false;
|
||||
|
||||
mtx_lock.unlock();
|
||||
}
|
||||
|
||||
bool cv::DetectionBasedTracker::SeparateDetectionWork::communicateWithDetectingThread(const Mat& imageGray, std::vector<Rect>& rectsWhereRegions)
|
||||
{
|
||||
static double freq = getTickFrequency();
|
||||
|
||||
bool shouldCommunicateWithDetectingThread = (stateThread==STATE_THREAD_WORKING_SLEEPING);
|
||||
LOGD("DetectionBasedTracker::SeparateDetectionWork::communicateWithDetectingThread: shouldCommunicateWithDetectingThread=%d", (shouldCommunicateWithDetectingThread?1:0));
|
||||
|
||||
if (!shouldCommunicateWithDetectingThread) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool shouldHandleResult = false;
|
||||
|
||||
std::unique_lock<std::mutex> mtx_lock(mtx);
|
||||
|
||||
if (isObjectDetectingReady) {
|
||||
shouldHandleResult=true;
|
||||
rectsWhereRegions = resultDetect;
|
||||
isObjectDetectingReady=false;
|
||||
|
||||
double lastBigDetectionDuration = 1000.0 * (((double)(getTickCount() - timeWhenDetectingThreadStartedWork )) / freq);
|
||||
(void)(lastBigDetectionDuration);
|
||||
LOGD("DetectionBasedTracker::SeparateDetectionWork::communicateWithDetectingThread: lastBigDetectionDuration=%f ms", (double)lastBigDetectionDuration);
|
||||
}
|
||||
|
||||
bool shouldSendNewDataToWorkThread = true;
|
||||
if (timeWhenDetectingThreadStartedWork > 0) {
|
||||
double time_from_previous_launch_in_ms=1000.0 * (((double)(getTickCount() - timeWhenDetectingThreadStartedWork )) / freq); //the same formula as for lastBigDetectionDuration
|
||||
shouldSendNewDataToWorkThread = (time_from_previous_launch_in_ms >= detectionBasedTracker.parameters.minDetectionPeriod);
|
||||
LOGD("DetectionBasedTracker::SeparateDetectionWork::communicateWithDetectingThread: shouldSendNewDataToWorkThread was 1, now it is %d, since time_from_previous_launch_in_ms=%.2f, minDetectionPeriod=%d",
|
||||
(shouldSendNewDataToWorkThread?1:0), time_from_previous_launch_in_ms, detectionBasedTracker.parameters.minDetectionPeriod);
|
||||
}
|
||||
|
||||
if (shouldSendNewDataToWorkThread) {
|
||||
|
||||
imageSeparateDetecting.create(imageGray.size(), CV_8UC1);
|
||||
|
||||
imageGray.copyTo(imageSeparateDetecting);//may change imageSeparateDetecting ptr. But should not.
|
||||
|
||||
|
||||
timeWhenDetectingThreadStartedWork = getTickCount() ;
|
||||
|
||||
objectDetectorRun.notify_one();
|
||||
}
|
||||
|
||||
mtx_lock.unlock();
|
||||
LOGD("DetectionBasedTracker::SeparateDetectionWork::communicateWithDetectingThread: result: shouldHandleResult=%d", (shouldHandleResult?1:0));
|
||||
|
||||
return shouldHandleResult;
|
||||
}
|
||||
|
||||
cv::DetectionBasedTracker::Parameters::Parameters()
|
||||
{
|
||||
maxTrackLifetime = 5;
|
||||
minDetectionPeriod = 0;
|
||||
}
|
||||
|
||||
cv::DetectionBasedTracker::InnerParameters::InnerParameters()
|
||||
{
|
||||
numLastPositionsToTrack=4;
|
||||
numStepsToWaitBeforeFirstShow=6;
|
||||
numStepsToTrackWithoutDetectingIfObjectHasNotBeenShown=3;
|
||||
numStepsToShowWithoutDetecting=3;
|
||||
|
||||
coeffTrackingWindowSize=2.0;
|
||||
coeffObjectSizeToTrack=0.85f;
|
||||
coeffObjectSpeedUsingInPrediction=0.8f;
|
||||
|
||||
}
|
||||
|
||||
cv::DetectionBasedTracker::DetectionBasedTracker(cv::Ptr<IDetector> mainDetector, cv::Ptr<IDetector> trackingDetector, const Parameters& params)
|
||||
:separateDetectionWork(),
|
||||
parameters(params),
|
||||
innerParameters(),
|
||||
numTrackedSteps(0),
|
||||
cascadeForTracking(trackingDetector)
|
||||
{
|
||||
CV_Assert( (params.maxTrackLifetime >= 0)
|
||||
// && mainDetector
|
||||
&& trackingDetector );
|
||||
|
||||
if (mainDetector) {
|
||||
Ptr<SeparateDetectionWork> tmp(new SeparateDetectionWork(*this, mainDetector, params));
|
||||
separateDetectionWork.swap(tmp);
|
||||
}
|
||||
|
||||
weightsPositionsSmoothing.push_back(1);
|
||||
weightsSizesSmoothing.push_back(0.5);
|
||||
weightsSizesSmoothing.push_back(0.3f);
|
||||
weightsSizesSmoothing.push_back(0.2f);
|
||||
}
|
||||
|
||||
cv::DetectionBasedTracker::~DetectionBasedTracker()
|
||||
{
|
||||
}
|
||||
|
||||
void DetectionBasedTracker::process(const Mat& imageGray)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
CV_Assert(imageGray.type()==CV_8UC1);
|
||||
|
||||
if ( separateDetectionWork && !separateDetectionWork->isWorking() ) {
|
||||
separateDetectionWork->run();
|
||||
}
|
||||
|
||||
static double freq = getTickFrequency();
|
||||
static long long time_when_last_call_started=getTickCount();
|
||||
|
||||
{
|
||||
double delta_time_from_prev_call=1000.0 * (((double)(getTickCount() - time_when_last_call_started)) / freq);
|
||||
(void)(delta_time_from_prev_call);
|
||||
LOGD("DetectionBasedTracker::process: time from the previous call is %f ms", (double)delta_time_from_prev_call);
|
||||
time_when_last_call_started=getTickCount();
|
||||
}
|
||||
|
||||
Mat imageDetect=imageGray;
|
||||
|
||||
std::vector<Rect> rectsWhereRegions;
|
||||
bool shouldHandleResult=false;
|
||||
if (separateDetectionWork) {
|
||||
shouldHandleResult = separateDetectionWork->communicateWithDetectingThread(imageGray, rectsWhereRegions);
|
||||
}
|
||||
|
||||
if (shouldHandleResult) {
|
||||
LOGD("DetectionBasedTracker::process: get _rectsWhereRegions were got from resultDetect");
|
||||
} else {
|
||||
LOGD("DetectionBasedTracker::process: get _rectsWhereRegions from previous positions");
|
||||
for(size_t i = 0; i < trackedObjects.size(); i++) {
|
||||
size_t n = trackedObjects[i].lastPositions.size();
|
||||
CV_Assert(n > 0);
|
||||
|
||||
Rect r = trackedObjects[i].lastPositions[n-1];
|
||||
if(r.empty()) {
|
||||
LOGE("DetectionBasedTracker::process: ERROR: ATTENTION: strange algorithm's behavior: trackedObjects[i].rect() is empty");
|
||||
continue;
|
||||
}
|
||||
|
||||
//correction by speed of rectangle
|
||||
if (n > 1) {
|
||||
Point2f center = centerRect(r);
|
||||
Point2f center_prev = centerRect(trackedObjects[i].lastPositions[n-2]);
|
||||
Point2f shift = (center - center_prev) * innerParameters.coeffObjectSpeedUsingInPrediction;
|
||||
|
||||
r.x += cvRound(shift.x);
|
||||
r.y += cvRound(shift.y);
|
||||
}
|
||||
|
||||
|
||||
rectsWhereRegions.push_back(r);
|
||||
}
|
||||
}
|
||||
LOGI("DetectionBasedTracker::process: tracked objects num==%d", (int)trackedObjects.size());
|
||||
|
||||
std::vector<Rect> detectedObjectsInRegions;
|
||||
|
||||
LOGD("DetectionBasedTracker::process: rectsWhereRegions.size()=%d", (int)rectsWhereRegions.size());
|
||||
for(size_t i=0; i < rectsWhereRegions.size(); i++) {
|
||||
Rect r = rectsWhereRegions[i];
|
||||
|
||||
detectInRegion(imageDetect, r, detectedObjectsInRegions);
|
||||
}
|
||||
LOGD("DetectionBasedTracker::process: detectedObjectsInRegions.size()=%d", (int)detectedObjectsInRegions.size());
|
||||
|
||||
updateTrackedObjects(detectedObjectsInRegions);
|
||||
}
|
||||
|
||||
void cv::DetectionBasedTracker::getObjects(std::vector<cv::Rect>& result) const
|
||||
{
|
||||
result.clear();
|
||||
|
||||
for(size_t i=0; i < trackedObjects.size(); i++) {
|
||||
Rect r=calcTrackedObjectPositionToShow((int)i);
|
||||
if (r.empty()) {
|
||||
continue;
|
||||
}
|
||||
result.push_back(r);
|
||||
LOGD("DetectionBasedTracker::process: found a object with SIZE %d x %d, rect={%d, %d, %d x %d}", r.width, r.height, r.x, r.y, r.width, r.height);
|
||||
}
|
||||
}
|
||||
|
||||
void cv::DetectionBasedTracker::getObjects(std::vector<Object>& result) const
|
||||
{
|
||||
result.clear();
|
||||
|
||||
for(size_t i=0; i < trackedObjects.size(); i++) {
|
||||
Rect r=calcTrackedObjectPositionToShow((int)i);
|
||||
if (r.empty()) {
|
||||
continue;
|
||||
}
|
||||
result.push_back(Object(r, trackedObjects[i].id));
|
||||
LOGD("DetectionBasedTracker::process: found a object with SIZE %d x %d, rect={%d, %d, %d x %d}", r.width, r.height, r.x, r.y, r.width, r.height);
|
||||
}
|
||||
}
|
||||
void cv::DetectionBasedTracker::getObjects(std::vector<ExtObject>& result) const
|
||||
{
|
||||
result.clear();
|
||||
|
||||
for(size_t i=0; i < trackedObjects.size(); i++) {
|
||||
ObjectStatus status;
|
||||
Rect r=calcTrackedObjectPositionToShow((int)i, status);
|
||||
result.push_back(ExtObject(trackedObjects[i].id, r, status));
|
||||
LOGD("DetectionBasedTracker::process: found a object with SIZE %d x %d, rect={%d, %d, %d x %d}, status = %d", r.width, r.height, r.x, r.y, r.width, r.height, (int)status);
|
||||
}
|
||||
}
|
||||
|
||||
bool cv::DetectionBasedTracker::run()
|
||||
{
|
||||
if (separateDetectionWork) {
|
||||
return separateDetectionWork->run();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void cv::DetectionBasedTracker::stop()
|
||||
{
|
||||
if (separateDetectionWork) {
|
||||
separateDetectionWork->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void cv::DetectionBasedTracker::resetTracking()
|
||||
{
|
||||
if (separateDetectionWork) {
|
||||
separateDetectionWork->resetTracking();
|
||||
}
|
||||
trackedObjects.clear();
|
||||
}
|
||||
|
||||
void cv::DetectionBasedTracker::updateTrackedObjects(const std::vector<Rect>& detectedObjects)
|
||||
{
|
||||
enum {
|
||||
NEW_RECTANGLE=-1,
|
||||
INTERSECTED_RECTANGLE=-2
|
||||
};
|
||||
|
||||
int N1=(int)trackedObjects.size();
|
||||
int N2=(int)detectedObjects.size();
|
||||
LOGD("DetectionBasedTracker::updateTrackedObjects: N1=%d, N2=%d", N1, N2);
|
||||
|
||||
for(int i=0; i < N1; i++) {
|
||||
trackedObjects[i].numDetectedFrames++;
|
||||
}
|
||||
|
||||
std::vector<int> correspondence(detectedObjects.size(), NEW_RECTANGLE);
|
||||
correspondence.clear();
|
||||
correspondence.resize(detectedObjects.size(), NEW_RECTANGLE);
|
||||
|
||||
for(int i=0; i < N1; i++) {
|
||||
LOGD("DetectionBasedTracker::updateTrackedObjects: i=%d", i);
|
||||
TrackedObject& curObject=trackedObjects[i];
|
||||
|
||||
int bestIndex=-1;
|
||||
int bestArea=-1;
|
||||
|
||||
int numpositions=(int)curObject.lastPositions.size();
|
||||
CV_Assert(numpositions > 0);
|
||||
Rect prevRect=curObject.lastPositions[numpositions-1];
|
||||
LOGD("DetectionBasedTracker::updateTrackedObjects: prevRect[%d]={%d, %d, %d x %d}", i, prevRect.x, prevRect.y, prevRect.width, prevRect.height);
|
||||
|
||||
for(int j=0; j < N2; j++) {
|
||||
LOGD("DetectionBasedTracker::updateTrackedObjects: j=%d", j);
|
||||
if (correspondence[j] >= 0) {
|
||||
LOGD("DetectionBasedTracker::updateTrackedObjects: j=%d is rejected, because it has correspondence=%d", j, correspondence[j]);
|
||||
continue;
|
||||
}
|
||||
if (correspondence[j] !=NEW_RECTANGLE) {
|
||||
LOGD("DetectionBasedTracker::updateTrackedObjects: j=%d is rejected, because it is intersected with another rectangle", j);
|
||||
continue;
|
||||
}
|
||||
LOGD("DetectionBasedTracker::updateTrackedObjects: detectedObjects[%d]={%d, %d, %d x %d}",
|
||||
j, detectedObjects[j].x, detectedObjects[j].y, detectedObjects[j].width, detectedObjects[j].height);
|
||||
|
||||
Rect r=prevRect & detectedObjects[j];
|
||||
if ( (r.width > 0) && (r.height > 0) ) {
|
||||
LOGD("DetectionBasedTracker::updateTrackedObjects: There is intersection between prevRect and detectedRect, r={%d, %d, %d x %d}",
|
||||
r.x, r.y, r.width, r.height);
|
||||
correspondence[j]=INTERSECTED_RECTANGLE;
|
||||
|
||||
if ( r.area() > bestArea) {
|
||||
LOGD("DetectionBasedTracker::updateTrackedObjects: The area of intersection is %d, it is better than bestArea=%d", r.area(), bestArea);
|
||||
bestIndex=j;
|
||||
bestArea=r.area();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bestIndex >= 0) {
|
||||
LOGD("DetectionBasedTracker::updateTrackedObjects: The best correspondence for i=%d is j=%d", i, bestIndex);
|
||||
correspondence[bestIndex]=i;
|
||||
|
||||
for(int j=0; j < N2; j++) {
|
||||
if (correspondence[j] >= 0)
|
||||
continue;
|
||||
|
||||
Rect r=detectedObjects[j] & detectedObjects[bestIndex];
|
||||
if ( (r.width > 0) && (r.height > 0) ) {
|
||||
LOGD("DetectionBasedTracker::updateTrackedObjects: Found intersection between "
|
||||
"rectangles j=%d and bestIndex=%d, rectangle j=%d is marked as intersected", j, bestIndex, j);
|
||||
correspondence[j]=INTERSECTED_RECTANGLE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOGD("DetectionBasedTracker::updateTrackedObjects: There is no correspondence for i=%d ", i);
|
||||
curObject.numFramesNotDetected++;
|
||||
}
|
||||
}
|
||||
|
||||
LOGD("DetectionBasedTracker::updateTrackedObjects: start second cycle");
|
||||
for(int j=0; j < N2; j++) {
|
||||
LOGD("DetectionBasedTracker::updateTrackedObjects: j=%d", j);
|
||||
int i=correspondence[j];
|
||||
if (i >= 0) {//add position
|
||||
LOGD("DetectionBasedTracker::updateTrackedObjects: add position");
|
||||
trackedObjects[i].lastPositions.push_back(detectedObjects[j]);
|
||||
while ((int)trackedObjects[i].lastPositions.size() > (int) innerParameters.numLastPositionsToTrack) {
|
||||
trackedObjects[i].lastPositions.erase(trackedObjects[i].lastPositions.begin());
|
||||
}
|
||||
trackedObjects[i].numFramesNotDetected=0;
|
||||
} else if (i==NEW_RECTANGLE){ //new object
|
||||
LOGD("DetectionBasedTracker::updateTrackedObjects: new object");
|
||||
trackedObjects.push_back(detectedObjects[j]);
|
||||
} else {
|
||||
LOGD("DetectionBasedTracker::updateTrackedObjects: was auxiliary intersection");
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<TrackedObject>::iterator it=trackedObjects.begin();
|
||||
while( it != trackedObjects.end() ) {
|
||||
if ( (it->numFramesNotDetected > parameters.maxTrackLifetime)
|
||||
||
|
||||
(
|
||||
(it->numDetectedFrames <= innerParameters.numStepsToWaitBeforeFirstShow)
|
||||
&&
|
||||
(it->numFramesNotDetected > innerParameters.numStepsToTrackWithoutDetectingIfObjectHasNotBeenShown)
|
||||
)
|
||||
)
|
||||
{
|
||||
int numpos=(int)it->lastPositions.size();
|
||||
CV_Assert(numpos > 0);
|
||||
Rect r = it->lastPositions[numpos-1];
|
||||
(void)(r);
|
||||
LOGD("DetectionBasedTracker::updateTrackedObjects: deleted object {%d, %d, %d x %d}",
|
||||
r.x, r.y, r.width, r.height);
|
||||
it=trackedObjects.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int cv::DetectionBasedTracker::addObject(const Rect& location)
|
||||
{
|
||||
LOGD("DetectionBasedTracker::addObject: new object {%d, %d %dx%d}",location.x, location.y, location.width, location.height);
|
||||
trackedObjects.push_back(TrackedObject(location));
|
||||
int newId = trackedObjects.back().id;
|
||||
LOGD("DetectionBasedTracker::addObject: newId = %d", newId);
|
||||
return newId;
|
||||
}
|
||||
|
||||
Rect cv::DetectionBasedTracker::calcTrackedObjectPositionToShow(int i) const
|
||||
{
|
||||
ObjectStatus status;
|
||||
return calcTrackedObjectPositionToShow(i, status);
|
||||
}
|
||||
Rect cv::DetectionBasedTracker::calcTrackedObjectPositionToShow(int i, ObjectStatus& status) const
|
||||
{
|
||||
if ( (i < 0) || (i >= (int)trackedObjects.size()) ) {
|
||||
LOGE("DetectionBasedTracker::calcTrackedObjectPositionToShow: ERROR: wrong i=%d", i);
|
||||
status = WRONG_OBJECT;
|
||||
return Rect();
|
||||
}
|
||||
if (trackedObjects[i].numDetectedFrames <= innerParameters.numStepsToWaitBeforeFirstShow){
|
||||
LOGI("DetectionBasedTracker::calcTrackedObjectPositionToShow: trackedObjects[%d].numDetectedFrames=%d <= numStepsToWaitBeforeFirstShow=%d --- return empty Rect()",
|
||||
i, trackedObjects[i].numDetectedFrames, innerParameters.numStepsToWaitBeforeFirstShow);
|
||||
status = DETECTED_NOT_SHOWN_YET;
|
||||
return Rect();
|
||||
}
|
||||
if (trackedObjects[i].numFramesNotDetected > innerParameters.numStepsToShowWithoutDetecting) {
|
||||
status = DETECTED_TEMPORARY_LOST;
|
||||
return Rect();
|
||||
}
|
||||
|
||||
const TrackedObject::PositionsVector& lastPositions=trackedObjects[i].lastPositions;
|
||||
|
||||
int N=(int)lastPositions.size();
|
||||
if (N<=0) {
|
||||
LOGE("DetectionBasedTracker::calcTrackedObjectPositionToShow: ERROR: no positions for i=%d", i);
|
||||
status = WRONG_OBJECT;
|
||||
return Rect();
|
||||
}
|
||||
|
||||
int Nsize=std::min(N, (int)weightsSizesSmoothing.size());
|
||||
int Ncenter= std::min(N, (int)weightsPositionsSmoothing.size());
|
||||
|
||||
Point2f center;
|
||||
double w=0, h=0;
|
||||
if (Nsize > 0) {
|
||||
double sum=0;
|
||||
for(int j=0; j < Nsize; j++) {
|
||||
int k=N-j-1;
|
||||
w += lastPositions[k].width * weightsSizesSmoothing[j];
|
||||
h += lastPositions[k].height * weightsSizesSmoothing[j];
|
||||
sum+=weightsSizesSmoothing[j];
|
||||
}
|
||||
w /= sum;
|
||||
h /= sum;
|
||||
} else {
|
||||
w=lastPositions[N-1].width;
|
||||
h=lastPositions[N-1].height;
|
||||
}
|
||||
|
||||
if (Ncenter > 0) {
|
||||
double sum=0;
|
||||
for(int j=0; j < Ncenter; j++) {
|
||||
int k=N-j-1;
|
||||
Point tl(lastPositions[k].tl());
|
||||
Point br(lastPositions[k].br());
|
||||
Point2f c1;
|
||||
c1=tl;
|
||||
c1=c1* 0.5f;
|
||||
Point2f c2;
|
||||
c2=br;
|
||||
c2=c2*0.5f;
|
||||
c1=c1+c2;
|
||||
|
||||
center=center+ (c1 * weightsPositionsSmoothing[j]);
|
||||
sum+=weightsPositionsSmoothing[j];
|
||||
}
|
||||
center *= (float)(1 / sum);
|
||||
} else {
|
||||
int k=N-1;
|
||||
Point tl(lastPositions[k].tl());
|
||||
Point br(lastPositions[k].br());
|
||||
Point2f c1;
|
||||
c1=tl;
|
||||
c1=c1* 0.5f;
|
||||
Point2f c2;
|
||||
c2=br;
|
||||
c2=c2*0.5f;
|
||||
|
||||
center=c1+c2;
|
||||
}
|
||||
Point2f tl=center-Point2f((float)w*0.5f,(float)h*0.5f);
|
||||
Rect res(cvRound(tl.x), cvRound(tl.y), cvRound(w), cvRound(h));
|
||||
LOGD("DetectionBasedTracker::calcTrackedObjectPositionToShow: Result for i=%d: {%d, %d, %d x %d}", i, res.x, res.y, res.width, res.height);
|
||||
|
||||
status = DETECTED;
|
||||
return res;
|
||||
}
|
||||
|
||||
void cv::DetectionBasedTracker::detectInRegion(const Mat& img, const Rect& r, std::vector<Rect>& detectedObjectsInRegions)
|
||||
{
|
||||
Rect r0(Point(), img.size());
|
||||
Rect r1 = scale_rect(r, innerParameters.coeffTrackingWindowSize);
|
||||
r1 = r1 & r0;
|
||||
|
||||
if ( (r1.width <=0) || (r1.height <= 0) ) {
|
||||
LOGD("DetectionBasedTracker::detectInRegion: Empty intersection");
|
||||
return;
|
||||
}
|
||||
|
||||
int d = cvRound(std::min(r.width, r.height) * innerParameters.coeffObjectSizeToTrack);
|
||||
|
||||
std::vector<Rect> tmpobjects;
|
||||
|
||||
Mat img1(img, r1);//subimage for rectangle -- without data copying
|
||||
LOGD("DetectionBasedTracker::detectInRegion: img1.size()=%d x %d, d=%d",
|
||||
img1.size().width, img1.size().height, d);
|
||||
|
||||
cascadeForTracking->setMinObjectSize(Size(d, d));
|
||||
cascadeForTracking->detect(img1, tmpobjects);
|
||||
/*
|
||||
detectMultiScale( img1, tmpobjects,
|
||||
parameters.scaleFactor, parameters.minNeighbors, 0
|
||||
|CV_HAAR_FIND_BIGGEST_OBJECT
|
||||
|CV_HAAR_SCALE_IMAGE
|
||||
,
|
||||
Size(d,d),
|
||||
max_objectSize
|
||||
);*/
|
||||
|
||||
for(size_t i=0; i < tmpobjects.size(); i++) {
|
||||
Rect curres(tmpobjects[i].tl() + r1.tl(), tmpobjects[i].size());
|
||||
detectedObjectsInRegions.push_back(curres);
|
||||
}
|
||||
}
|
||||
|
||||
bool cv::DetectionBasedTracker::setParameters(const Parameters& params)
|
||||
{
|
||||
if ( params.maxTrackLifetime < 0 )
|
||||
{
|
||||
LOGE("DetectionBasedTracker::setParameters: ERROR: wrong parameters value");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (separateDetectionWork) {
|
||||
separateDetectionWork->setParameters(params);
|
||||
}
|
||||
parameters=params;
|
||||
return true;
|
||||
}
|
||||
|
||||
const cv::DetectionBasedTracker::Parameters& DetectionBasedTracker::getParameters() const
|
||||
{
|
||||
return parameters;
|
||||
}
|
288
3rdparty/opencv-4.5.4/modules/objdetect/src/face_detect.cpp
vendored
Normal file
288
3rdparty/opencv-4.5.4/modules/objdetect/src/face_detect.cpp
vendored
Normal file
@ -0,0 +1,288 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/core.hpp"
|
||||
#include "opencv2/dnn.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
class FaceDetectorYNImpl : public FaceDetectorYN
|
||||
{
|
||||
public:
|
||||
FaceDetectorYNImpl(const String& model,
|
||||
const String& config,
|
||||
const Size& input_size,
|
||||
float score_threshold,
|
||||
float nms_threshold,
|
||||
int top_k,
|
||||
int backend_id,
|
||||
int target_id)
|
||||
{
|
||||
net = dnn::readNet(model, config);
|
||||
CV_Assert(!net.empty());
|
||||
|
||||
net.setPreferableBackend(backend_id);
|
||||
net.setPreferableTarget(target_id);
|
||||
|
||||
inputW = input_size.width;
|
||||
inputH = input_size.height;
|
||||
|
||||
scoreThreshold = score_threshold;
|
||||
nmsThreshold = nms_threshold;
|
||||
topK = top_k;
|
||||
|
||||
generatePriors();
|
||||
}
|
||||
|
||||
void setInputSize(const Size& input_size) override
|
||||
{
|
||||
inputW = input_size.width;
|
||||
inputH = input_size.height;
|
||||
generatePriors();
|
||||
}
|
||||
|
||||
Size getInputSize() override
|
||||
{
|
||||
Size input_size;
|
||||
input_size.width = inputW;
|
||||
input_size.height = inputH;
|
||||
return input_size;
|
||||
}
|
||||
|
||||
void setScoreThreshold(float score_threshold) override
|
||||
{
|
||||
scoreThreshold = score_threshold;
|
||||
}
|
||||
|
||||
float getScoreThreshold() override
|
||||
{
|
||||
return scoreThreshold;
|
||||
}
|
||||
|
||||
void setNMSThreshold(float nms_threshold) override
|
||||
{
|
||||
nmsThreshold = nms_threshold;
|
||||
}
|
||||
|
||||
float getNMSThreshold() override
|
||||
{
|
||||
return nmsThreshold;
|
||||
}
|
||||
|
||||
void setTopK(int top_k) override
|
||||
{
|
||||
topK = top_k;
|
||||
}
|
||||
|
||||
int getTopK() override
|
||||
{
|
||||
return topK;
|
||||
}
|
||||
|
||||
int detect(InputArray input_image, OutputArray faces) override
|
||||
{
|
||||
// TODO: more checkings should be done?
|
||||
if (input_image.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
CV_CheckEQ(input_image.size(), Size(inputW, inputH), "Size does not match. Call setInputSize(size) if input size does not match the preset size");
|
||||
|
||||
// Build blob from input image
|
||||
Mat input_blob = dnn::blobFromImage(input_image);
|
||||
|
||||
// Forward
|
||||
std::vector<String> output_names = { "loc", "conf", "iou" };
|
||||
std::vector<Mat> output_blobs;
|
||||
net.setInput(input_blob);
|
||||
net.forward(output_blobs, output_names);
|
||||
|
||||
// Post process
|
||||
Mat results = postProcess(output_blobs);
|
||||
results.convertTo(faces, CV_32FC1);
|
||||
return 1;
|
||||
}
|
||||
private:
|
||||
void generatePriors()
|
||||
{
|
||||
// Calculate shapes of different scales according to the shape of input image
|
||||
Size feature_map_2nd = {
|
||||
int(int((inputW+1)/2)/2), int(int((inputH+1)/2)/2)
|
||||
};
|
||||
Size feature_map_3rd = {
|
||||
int(feature_map_2nd.width/2), int(feature_map_2nd.height/2)
|
||||
};
|
||||
Size feature_map_4th = {
|
||||
int(feature_map_3rd.width/2), int(feature_map_3rd.height/2)
|
||||
};
|
||||
Size feature_map_5th = {
|
||||
int(feature_map_4th.width/2), int(feature_map_4th.height/2)
|
||||
};
|
||||
Size feature_map_6th = {
|
||||
int(feature_map_5th.width/2), int(feature_map_5th.height/2)
|
||||
};
|
||||
|
||||
std::vector<Size> feature_map_sizes;
|
||||
feature_map_sizes.push_back(feature_map_3rd);
|
||||
feature_map_sizes.push_back(feature_map_4th);
|
||||
feature_map_sizes.push_back(feature_map_5th);
|
||||
feature_map_sizes.push_back(feature_map_6th);
|
||||
|
||||
// Fixed params for generating priors
|
||||
const std::vector<std::vector<float>> min_sizes = {
|
||||
{10.0f, 16.0f, 24.0f},
|
||||
{32.0f, 48.0f},
|
||||
{64.0f, 96.0f},
|
||||
{128.0f, 192.0f, 256.0f}
|
||||
};
|
||||
const std::vector<int> steps = { 8, 16, 32, 64 };
|
||||
|
||||
// Generate priors
|
||||
priors.clear();
|
||||
for (size_t i = 0; i < feature_map_sizes.size(); ++i)
|
||||
{
|
||||
Size feature_map_size = feature_map_sizes[i];
|
||||
std::vector<float> min_size = min_sizes[i];
|
||||
|
||||
for (int _h = 0; _h < feature_map_size.height; ++_h)
|
||||
{
|
||||
for (int _w = 0; _w < feature_map_size.width; ++_w)
|
||||
{
|
||||
for (size_t j = 0; j < min_size.size(); ++j)
|
||||
{
|
||||
float s_kx = min_size[j] / inputW;
|
||||
float s_ky = min_size[j] / inputH;
|
||||
|
||||
float cx = (_w + 0.5f) * steps[i] / inputW;
|
||||
float cy = (_h + 0.5f) * steps[i] / inputH;
|
||||
|
||||
Rect2f prior = { cx, cy, s_kx, s_ky };
|
||||
priors.push_back(prior);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Mat postProcess(const std::vector<Mat>& output_blobs)
|
||||
{
|
||||
// Extract from output_blobs
|
||||
Mat loc = output_blobs[0];
|
||||
Mat conf = output_blobs[1];
|
||||
Mat iou = output_blobs[2];
|
||||
|
||||
// Decode from deltas and priors
|
||||
const std::vector<float> variance = {0.1f, 0.2f};
|
||||
float* loc_v = (float*)(loc.data);
|
||||
float* conf_v = (float*)(conf.data);
|
||||
float* iou_v = (float*)(iou.data);
|
||||
Mat faces;
|
||||
// (tl_x, tl_y, w, h, re_x, re_y, le_x, le_y, nt_x, nt_y, rcm_x, rcm_y, lcm_x, lcm_y, score)
|
||||
// 'tl': top left point of the bounding box
|
||||
// 're': right eye, 'le': left eye
|
||||
// 'nt': nose tip
|
||||
// 'rcm': right corner of mouth, 'lcm': left corner of mouth
|
||||
Mat face(1, 15, CV_32FC1);
|
||||
for (size_t i = 0; i < priors.size(); ++i) {
|
||||
// Get score
|
||||
float clsScore = conf_v[i*2+1];
|
||||
float iouScore = iou_v[i];
|
||||
// Clamp
|
||||
if (iouScore < 0.f) {
|
||||
iouScore = 0.f;
|
||||
}
|
||||
else if (iouScore > 1.f) {
|
||||
iouScore = 1.f;
|
||||
}
|
||||
float score = std::sqrt(clsScore * iouScore);
|
||||
face.at<float>(0, 14) = score;
|
||||
|
||||
// Get bounding box
|
||||
float cx = (priors[i].x + loc_v[i*14+0] * variance[0] * priors[i].width) * inputW;
|
||||
float cy = (priors[i].y + loc_v[i*14+1] * variance[0] * priors[i].height) * inputH;
|
||||
float w = priors[i].width * exp(loc_v[i*14+2] * variance[0]) * inputW;
|
||||
float h = priors[i].height * exp(loc_v[i*14+3] * variance[1]) * inputH;
|
||||
float x1 = cx - w / 2;
|
||||
float y1 = cy - h / 2;
|
||||
face.at<float>(0, 0) = x1;
|
||||
face.at<float>(0, 1) = y1;
|
||||
face.at<float>(0, 2) = w;
|
||||
face.at<float>(0, 3) = h;
|
||||
|
||||
// Get landmarks
|
||||
face.at<float>(0, 4) = (priors[i].x + loc_v[i*14+ 4] * variance[0] * priors[i].width) * inputW; // right eye, x
|
||||
face.at<float>(0, 5) = (priors[i].y + loc_v[i*14+ 5] * variance[0] * priors[i].height) * inputH; // right eye, y
|
||||
face.at<float>(0, 6) = (priors[i].x + loc_v[i*14+ 6] * variance[0] * priors[i].width) * inputW; // left eye, x
|
||||
face.at<float>(0, 7) = (priors[i].y + loc_v[i*14+ 7] * variance[0] * priors[i].height) * inputH; // left eye, y
|
||||
face.at<float>(0, 8) = (priors[i].x + loc_v[i*14+ 8] * variance[0] * priors[i].width) * inputW; // nose tip, x
|
||||
face.at<float>(0, 9) = (priors[i].y + loc_v[i*14+ 9] * variance[0] * priors[i].height) * inputH; // nose tip, y
|
||||
face.at<float>(0, 10) = (priors[i].x + loc_v[i*14+10] * variance[0] * priors[i].width) * inputW; // right corner of mouth, x
|
||||
face.at<float>(0, 11) = (priors[i].y + loc_v[i*14+11] * variance[0] * priors[i].height) * inputH; // right corner of mouth, y
|
||||
face.at<float>(0, 12) = (priors[i].x + loc_v[i*14+12] * variance[0] * priors[i].width) * inputW; // left corner of mouth, x
|
||||
face.at<float>(0, 13) = (priors[i].y + loc_v[i*14+13] * variance[0] * priors[i].height) * inputH; // left corner of mouth, y
|
||||
|
||||
faces.push_back(face);
|
||||
}
|
||||
|
||||
if (faces.rows > 1)
|
||||
{
|
||||
// Retrieve boxes and scores
|
||||
std::vector<Rect2i> faceBoxes;
|
||||
std::vector<float> faceScores;
|
||||
for (int rIdx = 0; rIdx < faces.rows; rIdx++)
|
||||
{
|
||||
faceBoxes.push_back(Rect2i(int(faces.at<float>(rIdx, 0)),
|
||||
int(faces.at<float>(rIdx, 1)),
|
||||
int(faces.at<float>(rIdx, 2)),
|
||||
int(faces.at<float>(rIdx, 3))));
|
||||
faceScores.push_back(faces.at<float>(rIdx, 14));
|
||||
}
|
||||
|
||||
std::vector<int> keepIdx;
|
||||
dnn::NMSBoxes(faceBoxes, faceScores, scoreThreshold, nmsThreshold, keepIdx, 1.f, topK);
|
||||
|
||||
// Get NMS results
|
||||
Mat nms_faces;
|
||||
for (int idx: keepIdx)
|
||||
{
|
||||
nms_faces.push_back(faces.row(idx));
|
||||
}
|
||||
return nms_faces;
|
||||
}
|
||||
else
|
||||
{
|
||||
return faces;
|
||||
}
|
||||
}
|
||||
private:
|
||||
dnn::Net net;
|
||||
|
||||
int inputW;
|
||||
int inputH;
|
||||
float scoreThreshold;
|
||||
float nmsThreshold;
|
||||
int topK;
|
||||
|
||||
std::vector<Rect2f> priors;
|
||||
};
|
||||
|
||||
Ptr<FaceDetectorYN> FaceDetectorYN::create(const String& model,
|
||||
const String& config,
|
||||
const Size& input_size,
|
||||
const float score_threshold,
|
||||
const float nms_threshold,
|
||||
const int top_k,
|
||||
const int backend_id,
|
||||
const int target_id)
|
||||
{
|
||||
return makePtr<FaceDetectorYNImpl>(model, config, input_size, score_threshold, nms_threshold, top_k, backend_id, target_id);
|
||||
}
|
||||
|
||||
} // namespace cv
|
182
3rdparty/opencv-4.5.4/modules/objdetect/src/face_recognize.cpp
vendored
Normal file
182
3rdparty/opencv-4.5.4/modules/objdetect/src/face_recognize.cpp
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
#include "opencv2/dnn.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
class FaceRecognizerSFImpl : public FaceRecognizerSF
|
||||
{
|
||||
public:
|
||||
FaceRecognizerSFImpl(const String& model, const String& config, int backend_id, int target_id)
|
||||
{
|
||||
net = dnn::readNet(model, config);
|
||||
CV_Assert(!net.empty());
|
||||
|
||||
net.setPreferableBackend(backend_id);
|
||||
net.setPreferableTarget(target_id);
|
||||
};
|
||||
void alignCrop(InputArray _src_img, InputArray _face_mat, OutputArray _aligned_img) const override
|
||||
{
|
||||
Mat face_mat = _face_mat.getMat();
|
||||
float src_point[5][2];
|
||||
for (int row = 0; row < 5; ++row)
|
||||
{
|
||||
for(int col = 0; col < 2; ++col)
|
||||
{
|
||||
src_point[row][col] = face_mat.at<float>(0, row*2+col+4);
|
||||
}
|
||||
}
|
||||
Mat warp_mat = getSimilarityTransformMatrix(src_point);
|
||||
warpAffine(_src_img, _aligned_img, warp_mat, Size(112, 112), INTER_LINEAR);
|
||||
};
|
||||
void feature(InputArray _aligned_img, OutputArray _face_feature) override
|
||||
{
|
||||
Mat inputBolb = dnn::blobFromImage(_aligned_img, 1, Size(112, 112), Scalar(0, 0, 0), true, false);
|
||||
net.setInput(inputBolb);
|
||||
net.forward(_face_feature);
|
||||
};
|
||||
double match(InputArray _face_feature1, InputArray _face_feature2, int dis_type) const override
|
||||
{
|
||||
Mat face_feature1 = _face_feature1.getMat(), face_feature2 = _face_feature2.getMat();
|
||||
face_feature1 /= norm(face_feature1);
|
||||
face_feature2 /= norm(face_feature2);
|
||||
|
||||
if(dis_type == DisType::FR_COSINE){
|
||||
return sum(face_feature1.mul(face_feature2))[0];
|
||||
}else if(dis_type == DisType::FR_NORM_L2){
|
||||
return norm(face_feature1, face_feature2);
|
||||
}else{
|
||||
throw std::invalid_argument("invalid parameter " + std::to_string(dis_type));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
Mat getSimilarityTransformMatrix(float src[5][2]) const {
|
||||
float dst[5][2] = { {38.2946f, 51.6963f}, {73.5318f, 51.5014f}, {56.0252f, 71.7366f}, {41.5493f, 92.3655f}, {70.7299f, 92.2041f} };
|
||||
float avg0 = (src[0][0] + src[1][0] + src[2][0] + src[3][0] + src[4][0]) / 5;
|
||||
float avg1 = (src[0][1] + src[1][1] + src[2][1] + src[3][1] + src[4][1]) / 5;
|
||||
//Compute mean of src and dst.
|
||||
float src_mean[2] = { avg0, avg1 };
|
||||
float dst_mean[2] = { 56.0262f, 71.9008f };
|
||||
//Subtract mean from src and dst.
|
||||
float src_demean[5][2];
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
for (int j = 0; j < 5; j++)
|
||||
{
|
||||
src_demean[j][i] = src[j][i] - src_mean[i];
|
||||
}
|
||||
}
|
||||
float dst_demean[5][2];
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
for (int j = 0; j < 5; j++)
|
||||
{
|
||||
dst_demean[j][i] = dst[j][i] - dst_mean[i];
|
||||
}
|
||||
}
|
||||
double A00 = 0.0, A01 = 0.0, A10 = 0.0, A11 = 0.0;
|
||||
for (int i = 0; i < 5; i++)
|
||||
A00 += dst_demean[i][0] * src_demean[i][0];
|
||||
A00 = A00 / 5;
|
||||
for (int i = 0; i < 5; i++)
|
||||
A01 += dst_demean[i][0] * src_demean[i][1];
|
||||
A01 = A01 / 5;
|
||||
for (int i = 0; i < 5; i++)
|
||||
A10 += dst_demean[i][1] * src_demean[i][0];
|
||||
A10 = A10 / 5;
|
||||
for (int i = 0; i < 5; i++)
|
||||
A11 += dst_demean[i][1] * src_demean[i][1];
|
||||
A11 = A11 / 5;
|
||||
Mat A = (Mat_<double>(2, 2) << A00, A01, A10, A11);
|
||||
double d[2] = { 1.0, 1.0 };
|
||||
double detA = A00 * A11 - A01 * A10;
|
||||
if (detA < 0)
|
||||
d[1] = -1;
|
||||
double T[3][3] = { {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0} };
|
||||
Mat s, u, vt, v;
|
||||
SVD::compute(A, s, u, vt);
|
||||
double smax = s.ptr<double>(0)[0]>s.ptr<double>(1)[0] ? s.ptr<double>(0)[0] : s.ptr<double>(1)[0];
|
||||
double tol = smax * 2 * FLT_MIN;
|
||||
int rank = 0;
|
||||
if (s.ptr<double>(0)[0]>tol)
|
||||
rank += 1;
|
||||
if (s.ptr<double>(1)[0]>tol)
|
||||
rank += 1;
|
||||
double arr_u[2][2] = { {u.ptr<double>(0)[0], u.ptr<double>(0)[1]}, {u.ptr<double>(1)[0], u.ptr<double>(1)[1]} };
|
||||
double arr_vt[2][2] = { {vt.ptr<double>(0)[0], vt.ptr<double>(0)[1]}, {vt.ptr<double>(1)[0], vt.ptr<double>(1)[1]} };
|
||||
double det_u = arr_u[0][0] * arr_u[1][1] - arr_u[0][1] * arr_u[1][0];
|
||||
double det_vt = arr_vt[0][0] * arr_vt[1][1] - arr_vt[0][1] * arr_vt[1][0];
|
||||
if (rank == 1)
|
||||
{
|
||||
if ((det_u*det_vt) > 0)
|
||||
{
|
||||
Mat uvt = u*vt;
|
||||
T[0][0] = uvt.ptr<double>(0)[0];
|
||||
T[0][1] = uvt.ptr<double>(0)[1];
|
||||
T[1][0] = uvt.ptr<double>(1)[0];
|
||||
T[1][1] = uvt.ptr<double>(1)[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
double temp = d[1];
|
||||
d[1] = -1;
|
||||
Mat D = (Mat_<double>(2, 2) << d[0], 0.0, 0.0, d[1]);
|
||||
Mat Dvt = D*vt;
|
||||
Mat uDvt = u*Dvt;
|
||||
T[0][0] = uDvt.ptr<double>(0)[0];
|
||||
T[0][1] = uDvt.ptr<double>(0)[1];
|
||||
T[1][0] = uDvt.ptr<double>(1)[0];
|
||||
T[1][1] = uDvt.ptr<double>(1)[1];
|
||||
d[1] = temp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Mat D = (Mat_<double>(2, 2) << d[0], 0.0, 0.0, d[1]);
|
||||
Mat Dvt = D*vt;
|
||||
Mat uDvt = u*Dvt;
|
||||
T[0][0] = uDvt.ptr<double>(0)[0];
|
||||
T[0][1] = uDvt.ptr<double>(0)[1];
|
||||
T[1][0] = uDvt.ptr<double>(1)[0];
|
||||
T[1][1] = uDvt.ptr<double>(1)[1];
|
||||
}
|
||||
double var1 = 0.0;
|
||||
for (int i = 0; i < 5; i++)
|
||||
var1 += src_demean[i][0] * src_demean[i][0];
|
||||
var1 = var1 / 5;
|
||||
double var2 = 0.0;
|
||||
for (int i = 0; i < 5; i++)
|
||||
var2 += src_demean[i][1] * src_demean[i][1];
|
||||
var2 = var2 / 5;
|
||||
double scale = 1.0 / (var1 + var2)* (s.ptr<double>(0)[0] * d[0] + s.ptr<double>(1)[0] * d[1]);
|
||||
double TS[2];
|
||||
TS[0] = T[0][0] * src_mean[0] + T[0][1] * src_mean[1];
|
||||
TS[1] = T[1][0] * src_mean[0] + T[1][1] * src_mean[1];
|
||||
T[0][2] = dst_mean[0] - scale*TS[0];
|
||||
T[1][2] = dst_mean[1] - scale*TS[1];
|
||||
T[0][0] *= scale;
|
||||
T[0][1] *= scale;
|
||||
T[1][0] *= scale;
|
||||
T[1][1] *= scale;
|
||||
Mat transform_mat = (Mat_<double>(2, 3) << T[0][0], T[0][1], T[0][2], T[1][0], T[1][1], T[1][2]);
|
||||
return transform_mat;
|
||||
}
|
||||
private:
|
||||
dnn::Net net;
|
||||
};
|
||||
|
||||
Ptr<FaceRecognizerSF> FaceRecognizerSF::create(const String& model, const String& config, int backend_id, int target_id)
|
||||
{
|
||||
return makePtr<FaceRecognizerSFImpl>(model, config, backend_id, target_id);
|
||||
}
|
||||
|
||||
} // namespace cv
|
3524
3rdparty/opencv-4.5.4/modules/objdetect/src/hog.cpp
vendored
Normal file
3524
3rdparty/opencv-4.5.4/modules/objdetect/src/hog.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
52
3rdparty/opencv-4.5.4/modules/objdetect/src/main.cpp
vendored
Normal file
52
3rdparty/opencv-4.5.4/modules/objdetect/src/main.cpp
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
/*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.
|
||||
// Copyright (C) 2015, Itseez 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*/
|
||||
|
||||
//
|
||||
// Library initialization file
|
||||
//
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
IPP_INITIALIZER_AUTO
|
||||
|
||||
/* End of file. */
|
661
3rdparty/opencv-4.5.4/modules/objdetect/src/opencl/cascadedetect.cl
vendored
Normal file
661
3rdparty/opencv-4.5.4/modules/objdetect/src/opencl/cascadedetect.cl
vendored
Normal file
@ -0,0 +1,661 @@
|
||||
///////////////////////////// OpenCL kernels for face detection //////////////////////////////
|
||||
////////////////////////////// see the opencv/doc/license.txt ///////////////////////////////
|
||||
|
||||
//
|
||||
// the code has been derived from the OpenCL Haar cascade kernel by
|
||||
//
|
||||
// Niko Li, newlife20080214@gmail.com
|
||||
// Wang Weiyan, wangweiyanster@gmail.com
|
||||
// Jia Haipeng, jiahaipeng95@gmail.com
|
||||
// Nathan, liujun@multicorewareinc.com
|
||||
// Peng Xiao, pengxiao@outlook.com
|
||||
// Erping Pang, erping@multicorewareinc.com
|
||||
//
|
||||
|
||||
#ifdef HAAR
|
||||
typedef struct __attribute__((aligned(4))) OptHaarFeature
|
||||
{
|
||||
int4 ofs[3] __attribute__((aligned (4)));
|
||||
float4 weight __attribute__((aligned (4)));
|
||||
}
|
||||
OptHaarFeature;
|
||||
#endif
|
||||
|
||||
#ifdef LBP
|
||||
typedef struct __attribute__((aligned(4))) OptLBPFeature
|
||||
{
|
||||
int16 ofs __attribute__((aligned (4)));
|
||||
}
|
||||
OptLBPFeature;
|
||||
#endif
|
||||
|
||||
typedef struct __attribute__((aligned(4))) Stump
|
||||
{
|
||||
float4 st __attribute__((aligned (4)));
|
||||
}
|
||||
Stump;
|
||||
|
||||
typedef struct __attribute__((aligned(4))) Node
|
||||
{
|
||||
int4 n __attribute__((aligned (4)));
|
||||
}
|
||||
Node;
|
||||
|
||||
typedef struct __attribute__((aligned (4))) Stage
|
||||
{
|
||||
int first __attribute__((aligned (4)));
|
||||
int ntrees __attribute__((aligned (4)));
|
||||
float threshold __attribute__((aligned (4)));
|
||||
}
|
||||
Stage;
|
||||
|
||||
typedef struct __attribute__((aligned (4))) ScaleData
|
||||
{
|
||||
float scale __attribute__((aligned (4)));
|
||||
int szi_width __attribute__((aligned (4)));
|
||||
int szi_height __attribute__((aligned (4)));
|
||||
int layer_ofs __attribute__((aligned (4)));
|
||||
int ystep __attribute__((aligned (4)));
|
||||
}
|
||||
ScaleData;
|
||||
|
||||
#ifndef SUM_BUF_SIZE
|
||||
#define SUM_BUF_SIZE 0
|
||||
#endif
|
||||
|
||||
#ifndef NODE_COUNT
|
||||
#define NODE_COUNT 1
|
||||
#endif
|
||||
|
||||
#ifdef HAAR
|
||||
__kernel __attribute__((reqd_work_group_size(LOCAL_SIZE_X,LOCAL_SIZE_Y,1)))
|
||||
void runHaarClassifier(
|
||||
int nscales, __global const ScaleData* scaleData,
|
||||
__global const int* sum,
|
||||
int _sumstep, int sumoffset,
|
||||
__global const OptHaarFeature* optfeatures,
|
||||
__global const Stage* stages,
|
||||
__global const Node* nodes,
|
||||
__global const float* leaves0,
|
||||
|
||||
volatile __global int* facepos,
|
||||
int4 normrect, int sqofs, int2 windowsize)
|
||||
{
|
||||
int lx = get_local_id(0);
|
||||
int ly = get_local_id(1);
|
||||
int groupIdx = get_group_id(0);
|
||||
int i, ngroups = get_global_size(0)/LOCAL_SIZE_X;
|
||||
int scaleIdx, tileIdx, stageIdx;
|
||||
int sumstep = (int)(_sumstep/sizeof(int));
|
||||
int4 nofs0 = (int4)(mad24(normrect.y, sumstep, normrect.x),
|
||||
mad24(normrect.y, sumstep, normrect.x + normrect.z),
|
||||
mad24(normrect.y + normrect.w, sumstep, normrect.x),
|
||||
mad24(normrect.y + normrect.w, sumstep, normrect.x + normrect.z));
|
||||
int normarea = normrect.z * normrect.w;
|
||||
float invarea = 1.f/normarea;
|
||||
int lidx = ly*LOCAL_SIZE_X + lx;
|
||||
|
||||
#if SUM_BUF_SIZE > 0
|
||||
int4 nofs = (int4)(mad24(normrect.y, SUM_BUF_STEP, normrect.x),
|
||||
mad24(normrect.y, SUM_BUF_STEP, normrect.x + normrect.z),
|
||||
mad24(normrect.y + normrect.w, SUM_BUF_STEP, normrect.x),
|
||||
mad24(normrect.y + normrect.w, SUM_BUF_STEP, normrect.x + normrect.z));
|
||||
#else
|
||||
int4 nofs = nofs0;
|
||||
#endif
|
||||
#define LOCAL_SIZE (LOCAL_SIZE_X*LOCAL_SIZE_Y)
|
||||
__local int lstore[SUM_BUF_SIZE + LOCAL_SIZE*5/2+1];
|
||||
#if SUM_BUF_SIZE > 0
|
||||
__local int* ibuf = lstore;
|
||||
__local int* lcount = ibuf + SUM_BUF_SIZE;
|
||||
#else
|
||||
__local int* lcount = lstore;
|
||||
#endif
|
||||
__local float* lnf = (__local float*)(lcount + 1);
|
||||
__local float* lpartsum = lnf + LOCAL_SIZE;
|
||||
__local short* lbuf = (__local short*)(lpartsum + LOCAL_SIZE);
|
||||
|
||||
for( scaleIdx = nscales-1; scaleIdx >= 0; scaleIdx-- )
|
||||
{
|
||||
__global const ScaleData* s = scaleData + scaleIdx;
|
||||
int ystep = s->ystep;
|
||||
int2 worksize = (int2)(max(s->szi_width - windowsize.x, 0), max(s->szi_height - windowsize.y, 0));
|
||||
int2 ntiles = (int2)((worksize.x + LOCAL_SIZE_X-1)/LOCAL_SIZE_X,
|
||||
(worksize.y + LOCAL_SIZE_Y-1)/LOCAL_SIZE_Y);
|
||||
int totalTiles = ntiles.x*ntiles.y;
|
||||
|
||||
for( tileIdx = groupIdx; tileIdx < totalTiles; tileIdx += ngroups )
|
||||
{
|
||||
int ix0 = (tileIdx % ntiles.x)*LOCAL_SIZE_X;
|
||||
int iy0 = (tileIdx / ntiles.x)*LOCAL_SIZE_Y;
|
||||
int ix = lx, iy = ly;
|
||||
__global const int* psum0 = sum + mad24(iy0, sumstep, ix0) + s->layer_ofs;
|
||||
__global const int* psum1 = psum0 + mad24(iy, sumstep, ix);
|
||||
|
||||
if( ix0 >= worksize.x || iy0 >= worksize.y )
|
||||
continue;
|
||||
#if SUM_BUF_SIZE > 0
|
||||
for( i = lidx*4; i < SUM_BUF_SIZE; i += LOCAL_SIZE_X*LOCAL_SIZE_Y*4 )
|
||||
{
|
||||
int dy = i/SUM_BUF_STEP, dx = i - dy*SUM_BUF_STEP;
|
||||
vstore4(vload4(0, psum0 + mad24(dy, sumstep, dx)), 0, ibuf+i);
|
||||
}
|
||||
#endif
|
||||
|
||||
if( lidx == 0 )
|
||||
lcount[0] = 0;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if( ix0 + ix < worksize.x && iy0 + iy < worksize.y )
|
||||
{
|
||||
#if NODE_COUNT==1
|
||||
__global const Stump* stump = (__global const Stump*)nodes;
|
||||
#else
|
||||
__global const Node* node = nodes;
|
||||
__global const float* leaves = leaves0;
|
||||
#endif
|
||||
#if SUM_BUF_SIZE > 0
|
||||
__local const int* psum = ibuf + mad24(iy, SUM_BUF_STEP, ix);
|
||||
#else
|
||||
__global const int* psum = psum1;
|
||||
#endif
|
||||
|
||||
__global const int* psqsum = (__global const int*)(psum1 + sqofs);
|
||||
float sval = (psum[nofs.x] - psum[nofs.y] - psum[nofs.z] + psum[nofs.w])*invarea;
|
||||
float sqval = (psqsum[nofs0.x] - psqsum[nofs0.y] - psqsum[nofs0.z] + psqsum[nofs0.w])*invarea;
|
||||
float nf = (float)normarea * sqrt(max(sqval - sval * sval, 0.f));
|
||||
nf = nf > 0 ? nf : 1.f;
|
||||
|
||||
for( stageIdx = 0; stageIdx < SPLIT_STAGE; stageIdx++ )
|
||||
{
|
||||
int ntrees = stages[stageIdx].ntrees;
|
||||
float s = 0.f;
|
||||
#if NODE_COUNT==1
|
||||
for( i = 0; i < ntrees; i++ )
|
||||
{
|
||||
float4 st = stump[i].st;
|
||||
__global const OptHaarFeature* f = optfeatures + as_int(st.x);
|
||||
float4 weight = f->weight;
|
||||
|
||||
int4 ofs = f->ofs[0];
|
||||
sval = (psum[ofs.x] - psum[ofs.y] - psum[ofs.z] + psum[ofs.w])*weight.x;
|
||||
ofs = f->ofs[1];
|
||||
sval = mad((float)(psum[ofs.x] - psum[ofs.y] - psum[ofs.z] + psum[ofs.w]), weight.y, sval);
|
||||
if( weight.z > 0 )
|
||||
{
|
||||
ofs = f->ofs[2];
|
||||
sval = mad((float)(psum[ofs.x] - psum[ofs.y] - psum[ofs.z] + psum[ofs.w]), weight.z, sval);
|
||||
}
|
||||
|
||||
s += (sval < st.y*nf) ? st.z : st.w;
|
||||
}
|
||||
stump += ntrees;
|
||||
#else
|
||||
for( i = 0; i < ntrees; i++, node += NODE_COUNT, leaves += NODE_COUNT+1 )
|
||||
{
|
||||
int idx = 0;
|
||||
do
|
||||
{
|
||||
int4 n = node[idx].n;
|
||||
__global const OptHaarFeature* f = optfeatures + n.x;
|
||||
float4 weight = f->weight;
|
||||
|
||||
int4 ofs = f->ofs[0];
|
||||
|
||||
sval = (psum[ofs.x] - psum[ofs.y] - psum[ofs.z] + psum[ofs.w])*weight.x;
|
||||
ofs = f->ofs[1];
|
||||
sval = mad((float)(psum[ofs.x] - psum[ofs.y] - psum[ofs.z] + psum[ofs.w]), weight.y, sval);
|
||||
if( weight.z > 0 )
|
||||
{
|
||||
ofs = f->ofs[2];
|
||||
sval = mad((float)(psum[ofs.x] - psum[ofs.y] - psum[ofs.z] + psum[ofs.w]), weight.z, sval);
|
||||
}
|
||||
|
||||
idx = (sval < as_float(n.y)*nf) ? n.z : n.w;
|
||||
}
|
||||
while(idx > 0);
|
||||
s += leaves[-idx];
|
||||
}
|
||||
#endif
|
||||
|
||||
if( s < stages[stageIdx].threshold )
|
||||
break;
|
||||
}
|
||||
|
||||
if( stageIdx == SPLIT_STAGE && (ystep == 1 || ((ix | iy) & 1) == 0) )
|
||||
{
|
||||
int count = atomic_inc(lcount);
|
||||
lbuf[count] = (int)(ix | (iy << 8));
|
||||
lnf[count] = nf;
|
||||
}
|
||||
}
|
||||
|
||||
for( stageIdx = SPLIT_STAGE; stageIdx < N_STAGES; stageIdx++ )
|
||||
{
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
int nrects = lcount[0];
|
||||
|
||||
if( nrects == 0 )
|
||||
break;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if( lidx == 0 )
|
||||
lcount[0] = 0;
|
||||
|
||||
{
|
||||
#if NODE_COUNT == 1
|
||||
__global const Stump* stump = (__global const Stump*)nodes + stages[stageIdx].first;
|
||||
#else
|
||||
__global const Node* node = nodes + stages[stageIdx].first*NODE_COUNT;
|
||||
__global const float* leaves = leaves0 + stages[stageIdx].first*(NODE_COUNT+1);
|
||||
#endif
|
||||
int nparts = LOCAL_SIZE / nrects;
|
||||
int ntrees = stages[stageIdx].ntrees;
|
||||
int ntrees_p = (ntrees + nparts - 1)/nparts;
|
||||
int nr = lidx / nparts;
|
||||
int partidx = -1, idxval = 0;
|
||||
float partsum = 0.f, nf = 0.f;
|
||||
|
||||
if( nr < nrects )
|
||||
{
|
||||
partidx = lidx % nparts;
|
||||
idxval = lbuf[nr];
|
||||
nf = lnf[nr];
|
||||
|
||||
{
|
||||
int ntrees0 = ntrees_p*partidx;
|
||||
int ntrees1 = min(ntrees0 + ntrees_p, ntrees);
|
||||
int ix1 = idxval & 255, iy1 = idxval >> 8;
|
||||
#if SUM_BUF_SIZE > 0
|
||||
__local const int* psum = ibuf + mad24(iy1, SUM_BUF_STEP, ix1);
|
||||
#else
|
||||
__global const int* psum = psum0 + mad24(iy1, sumstep, ix1);
|
||||
#endif
|
||||
|
||||
#if NODE_COUNT == 1
|
||||
for( i = ntrees0; i < ntrees1; i++ )
|
||||
{
|
||||
float4 st = stump[i].st;
|
||||
__global const OptHaarFeature* f = optfeatures + as_int(st.x);
|
||||
float4 weight = f->weight;
|
||||
|
||||
int4 ofs = f->ofs[0];
|
||||
float sval = (psum[ofs.x] - psum[ofs.y] - psum[ofs.z] + psum[ofs.w])*weight.x;
|
||||
ofs = f->ofs[1];
|
||||
sval = mad((float)(psum[ofs.x] - psum[ofs.y] - psum[ofs.z] + psum[ofs.w]), weight.y, sval);
|
||||
//if( weight.z > 0 )
|
||||
if( fabs(weight.z) > 0 )
|
||||
{
|
||||
ofs = f->ofs[2];
|
||||
sval = mad((float)(psum[ofs.x] - psum[ofs.y] - psum[ofs.z] + psum[ofs.w]), weight.z, sval);
|
||||
}
|
||||
|
||||
partsum += (sval < st.y*nf) ? st.z : st.w;
|
||||
}
|
||||
#else
|
||||
for( i = ntrees0; i < ntrees1; i++ )
|
||||
{
|
||||
int idx = 0;
|
||||
do
|
||||
{
|
||||
int4 n = node[i*2 + idx].n;
|
||||
__global const OptHaarFeature* f = optfeatures + n.x;
|
||||
float4 weight = f->weight;
|
||||
int4 ofs = f->ofs[0];
|
||||
|
||||
float sval = (psum[ofs.x] - psum[ofs.y] - psum[ofs.z] + psum[ofs.w])*weight.x;
|
||||
ofs = f->ofs[1];
|
||||
sval = mad((float)(psum[ofs.x] - psum[ofs.y] - psum[ofs.z] + psum[ofs.w]), weight.y, sval);
|
||||
if( weight.z > 0 )
|
||||
{
|
||||
ofs = f->ofs[2];
|
||||
sval = mad((float)(psum[ofs.x] - psum[ofs.y] - psum[ofs.z] + psum[ofs.w]), weight.z, sval);
|
||||
}
|
||||
|
||||
idx = (sval < as_float(n.y)*nf) ? n.z : n.w;
|
||||
}
|
||||
while(idx > 0);
|
||||
partsum += leaves[i*3-idx];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
lpartsum[lidx] = partsum;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if( partidx == 0 )
|
||||
{
|
||||
float s = lpartsum[nr*nparts];
|
||||
for( i = 1; i < nparts; i++ )
|
||||
s += lpartsum[i + nr*nparts];
|
||||
if( s >= stages[stageIdx].threshold )
|
||||
{
|
||||
int count = atomic_inc(lcount);
|
||||
lbuf[count] = idxval;
|
||||
lnf[count] = nf;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if( stageIdx == N_STAGES )
|
||||
{
|
||||
int nrects = lcount[0];
|
||||
if( lidx < nrects )
|
||||
{
|
||||
int nfaces = atomic_inc(facepos);
|
||||
if( nfaces < MAX_FACES )
|
||||
{
|
||||
volatile __global int* face = facepos + 1 + nfaces*3;
|
||||
int val = lbuf[lidx];
|
||||
face[0] = scaleIdx;
|
||||
face[1] = ix0 + (val & 255);
|
||||
face[2] = iy0 + (val >> 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LBP
|
||||
#undef CALC_SUM_OFS_
|
||||
#define CALC_SUM_OFS_(p0, p1, p2, p3, ptr) \
|
||||
((ptr)[p0] - (ptr)[p1] - (ptr)[p2] + (ptr)[p3])
|
||||
|
||||
__kernel void runLBPClassifierStumpSimple(
|
||||
int nscales, __global const ScaleData* scaleData,
|
||||
__global const int* sum,
|
||||
int _sumstep, int sumoffset,
|
||||
__global const OptLBPFeature* optfeatures,
|
||||
__global const Stage* stages,
|
||||
__global const Stump* stumps,
|
||||
__global const int* bitsets,
|
||||
int bitsetSize,
|
||||
|
||||
volatile __global int* facepos,
|
||||
int2 windowsize)
|
||||
{
|
||||
int lx = get_local_id(0);
|
||||
int ly = get_local_id(1);
|
||||
int local_size_x = get_local_size(0);
|
||||
int local_size_y = get_local_size(1);
|
||||
int groupIdx = get_group_id(1)*get_num_groups(0) + get_group_id(0);
|
||||
int ngroups = get_num_groups(0)*get_num_groups(1);
|
||||
int scaleIdx, tileIdx, stageIdx;
|
||||
int sumstep = (int)(_sumstep/sizeof(int));
|
||||
|
||||
for( scaleIdx = nscales-1; scaleIdx >= 0; scaleIdx-- )
|
||||
{
|
||||
__global const ScaleData* s = scaleData + scaleIdx;
|
||||
int ystep = s->ystep;
|
||||
int2 worksize = (int2)(max(s->szi_width - windowsize.x, 0), max(s->szi_height - windowsize.y, 0));
|
||||
int2 ntiles = (int2)((worksize.x/ystep + local_size_x-1)/local_size_x,
|
||||
(worksize.y/ystep + local_size_y-1)/local_size_y);
|
||||
int totalTiles = ntiles.x*ntiles.y;
|
||||
|
||||
for( tileIdx = groupIdx; tileIdx < totalTiles; tileIdx += ngroups )
|
||||
{
|
||||
int iy = mad24((tileIdx / ntiles.x), local_size_y, ly) * ystep;
|
||||
int ix = mad24((tileIdx % ntiles.x), local_size_x, lx) * ystep;
|
||||
|
||||
if( ix < worksize.x && iy < worksize.y )
|
||||
{
|
||||
__global const int* p = sum + mad24(iy, sumstep, ix) + s->layer_ofs;
|
||||
__global const Stump* stump = stumps;
|
||||
__global const int* bitset = bitsets;
|
||||
|
||||
for( stageIdx = 0; stageIdx < N_STAGES; stageIdx++ )
|
||||
{
|
||||
int i, ntrees = stages[stageIdx].ntrees;
|
||||
float s = 0.f;
|
||||
for( i = 0; i < ntrees; i++, stump++, bitset += bitsetSize )
|
||||
{
|
||||
float4 st = stump->st;
|
||||
__global const OptLBPFeature* f = optfeatures + as_int(st.x);
|
||||
int16 ofs = f->ofs;
|
||||
|
||||
int cval = CALC_SUM_OFS_( ofs.s5, ofs.s6, ofs.s9, ofs.sa, p );
|
||||
|
||||
int mask, idx = (CALC_SUM_OFS_( ofs.s0, ofs.s1, ofs.s4, ofs.s5, p ) >= cval ? 4 : 0); // 0
|
||||
idx |= (CALC_SUM_OFS_( ofs.s1, ofs.s2, ofs.s5, ofs.s6, p ) >= cval ? 2 : 0); // 1
|
||||
idx |= (CALC_SUM_OFS_( ofs.s2, ofs.s3, ofs.s6, ofs.s7, p ) >= cval ? 1 : 0); // 2
|
||||
|
||||
mask = (CALC_SUM_OFS_( ofs.s6, ofs.s7, ofs.sa, ofs.sb, p ) >= cval ? 16 : 0); // 5
|
||||
mask |= (CALC_SUM_OFS_( ofs.sa, ofs.sb, ofs.se, ofs.sf, p ) >= cval ? 8 : 0); // 8
|
||||
mask |= (CALC_SUM_OFS_( ofs.s9, ofs.sa, ofs.sd, ofs.se, p ) >= cval ? 4 : 0); // 7
|
||||
mask |= (CALC_SUM_OFS_( ofs.s8, ofs.s9, ofs.sc, ofs.sd, p ) >= cval ? 2 : 0); // 6
|
||||
mask |= (CALC_SUM_OFS_( ofs.s4, ofs.s5, ofs.s8, ofs.s9, p ) >= cval ? 1 : 0); // 7
|
||||
|
||||
s += (bitset[idx] & (1 << mask)) ? st.z : st.w;
|
||||
}
|
||||
|
||||
if( s < stages[stageIdx].threshold )
|
||||
break;
|
||||
}
|
||||
|
||||
if( stageIdx == N_STAGES )
|
||||
{
|
||||
int nfaces = atomic_inc(facepos);
|
||||
if( nfaces < MAX_FACES )
|
||||
{
|
||||
volatile __global int* face = facepos + 1 + nfaces*3;
|
||||
face[0] = scaleIdx;
|
||||
face[1] = ix;
|
||||
face[2] = iy;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__kernel __attribute__((reqd_work_group_size(LOCAL_SIZE_X,LOCAL_SIZE_Y,1)))
|
||||
void runLBPClassifierStump(
|
||||
int nscales, __global const ScaleData* scaleData,
|
||||
__global const int* sum,
|
||||
int _sumstep, int sumoffset,
|
||||
__global const OptLBPFeature* optfeatures,
|
||||
__global const Stage* stages,
|
||||
__global const Stump* stumps,
|
||||
__global const int* bitsets,
|
||||
int bitsetSize,
|
||||
|
||||
volatile __global int* facepos,
|
||||
int2 windowsize)
|
||||
{
|
||||
int lx = get_local_id(0);
|
||||
int ly = get_local_id(1);
|
||||
int groupIdx = get_group_id(0);
|
||||
int i, ngroups = get_global_size(0)/LOCAL_SIZE_X;
|
||||
int scaleIdx, tileIdx, stageIdx;
|
||||
int sumstep = (int)(_sumstep/sizeof(int));
|
||||
int lidx = ly*LOCAL_SIZE_X + lx;
|
||||
|
||||
#define LOCAL_SIZE (LOCAL_SIZE_X*LOCAL_SIZE_Y)
|
||||
__local int lstore[SUM_BUF_SIZE + LOCAL_SIZE*3/2+1];
|
||||
#if SUM_BUF_SIZE > 0
|
||||
__local int* ibuf = lstore;
|
||||
__local int* lcount = ibuf + SUM_BUF_SIZE;
|
||||
#else
|
||||
__local int* lcount = lstore;
|
||||
#endif
|
||||
__local float* lpartsum = (__local float*)(lcount + 1);
|
||||
__local short* lbuf = (__local short*)(lpartsum + LOCAL_SIZE);
|
||||
|
||||
for( scaleIdx = nscales-1; scaleIdx >= 0; scaleIdx-- )
|
||||
{
|
||||
__global const ScaleData* s = scaleData + scaleIdx;
|
||||
int ystep = s->ystep;
|
||||
int2 worksize = (int2)(max(s->szi_width - windowsize.x, 0), max(s->szi_height - windowsize.y, 0));
|
||||
int2 ntiles = (int2)((worksize.x + LOCAL_SIZE_X-1)/LOCAL_SIZE_X,
|
||||
(worksize.y + LOCAL_SIZE_Y-1)/LOCAL_SIZE_Y);
|
||||
int totalTiles = ntiles.x*ntiles.y;
|
||||
|
||||
for( tileIdx = groupIdx; tileIdx < totalTiles; tileIdx += ngroups )
|
||||
{
|
||||
int ix0 = (tileIdx % ntiles.x)*LOCAL_SIZE_X;
|
||||
int iy0 = (tileIdx / ntiles.x)*LOCAL_SIZE_Y;
|
||||
int ix = lx, iy = ly;
|
||||
__global const int* psum0 = sum + mad24(iy0, sumstep, ix0) + s->layer_ofs;
|
||||
|
||||
if( ix0 >= worksize.x || iy0 >= worksize.y )
|
||||
continue;
|
||||
#if SUM_BUF_SIZE > 0
|
||||
for( i = lidx*4; i < SUM_BUF_SIZE; i += LOCAL_SIZE_X*LOCAL_SIZE_Y*4 )
|
||||
{
|
||||
int dy = i/SUM_BUF_STEP, dx = i - dy*SUM_BUF_STEP;
|
||||
vstore4(vload4(0, psum0 + mad24(dy, sumstep, dx)), 0, ibuf+i);
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
#endif
|
||||
|
||||
if( lidx == 0 )
|
||||
lcount[0] = 0;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if( ix0 + ix < worksize.x && iy0 + iy < worksize.y )
|
||||
{
|
||||
__global const Stump* stump = stumps;
|
||||
__global const int* bitset = bitsets;
|
||||
#if SUM_BUF_SIZE > 0
|
||||
__local const int* p = ibuf + mad24(iy, SUM_BUF_STEP, ix);
|
||||
#else
|
||||
__global const int* p = psum0 + mad24(iy, sumstep, ix);
|
||||
#endif
|
||||
|
||||
for( stageIdx = 0; stageIdx < SPLIT_STAGE; stageIdx++ )
|
||||
{
|
||||
int ntrees = stages[stageIdx].ntrees;
|
||||
float s = 0.f;
|
||||
for( i = 0; i < ntrees; i++, stump++, bitset += bitsetSize )
|
||||
{
|
||||
float4 st = stump->st;
|
||||
__global const OptLBPFeature* f = optfeatures + as_int(st.x);
|
||||
int16 ofs = f->ofs;
|
||||
|
||||
int cval = CALC_SUM_OFS_( ofs.s5, ofs.s6, ofs.s9, ofs.sa, p );
|
||||
|
||||
int mask, idx = (CALC_SUM_OFS_( ofs.s0, ofs.s1, ofs.s4, ofs.s5, p ) >= cval ? 4 : 0); // 0
|
||||
idx |= (CALC_SUM_OFS_( ofs.s1, ofs.s2, ofs.s5, ofs.s6, p ) >= cval ? 2 : 0); // 1
|
||||
idx |= (CALC_SUM_OFS_( ofs.s2, ofs.s3, ofs.s6, ofs.s7, p ) >= cval ? 1 : 0); // 2
|
||||
|
||||
mask = (CALC_SUM_OFS_( ofs.s6, ofs.s7, ofs.sa, ofs.sb, p ) >= cval ? 16 : 0); // 5
|
||||
mask |= (CALC_SUM_OFS_( ofs.sa, ofs.sb, ofs.se, ofs.sf, p ) >= cval ? 8 : 0); // 8
|
||||
mask |= (CALC_SUM_OFS_( ofs.s9, ofs.sa, ofs.sd, ofs.se, p ) >= cval ? 4 : 0); // 7
|
||||
mask |= (CALC_SUM_OFS_( ofs.s8, ofs.s9, ofs.sc, ofs.sd, p ) >= cval ? 2 : 0); // 6
|
||||
mask |= (CALC_SUM_OFS_( ofs.s4, ofs.s5, ofs.s8, ofs.s9, p ) >= cval ? 1 : 0); // 7
|
||||
|
||||
s += (bitset[idx] & (1 << mask)) ? st.z : st.w;
|
||||
}
|
||||
|
||||
if( s < stages[stageIdx].threshold )
|
||||
break;
|
||||
}
|
||||
|
||||
if( stageIdx == SPLIT_STAGE && (ystep == 1 || ((ix | iy) & 1) == 0) )
|
||||
{
|
||||
int count = atomic_inc(lcount);
|
||||
lbuf[count] = (int)(ix | (iy << 8));
|
||||
}
|
||||
}
|
||||
|
||||
for( stageIdx = SPLIT_STAGE; stageIdx < N_STAGES; stageIdx++ )
|
||||
{
|
||||
int nrects = lcount[0];
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if( nrects == 0 )
|
||||
break;
|
||||
if( lidx == 0 )
|
||||
lcount[0] = 0;
|
||||
|
||||
{
|
||||
__global const Stump* stump = stumps + stages[stageIdx].first;
|
||||
__global const int* bitset = bitsets + stages[stageIdx].first*bitsetSize;
|
||||
int nparts = LOCAL_SIZE / nrects;
|
||||
int ntrees = stages[stageIdx].ntrees;
|
||||
int ntrees_p = (ntrees + nparts - 1)/nparts;
|
||||
int nr = lidx / nparts;
|
||||
int partidx = -1, idxval = 0;
|
||||
float partsum = 0.f, nf = 0.f;
|
||||
|
||||
if( nr < nrects )
|
||||
{
|
||||
partidx = lidx % nparts;
|
||||
idxval = lbuf[nr];
|
||||
|
||||
{
|
||||
int ntrees0 = ntrees_p*partidx;
|
||||
int ntrees1 = min(ntrees0 + ntrees_p, ntrees);
|
||||
int ix1 = idxval & 255, iy1 = idxval >> 8;
|
||||
#if SUM_BUF_SIZE > 0
|
||||
__local const int* p = ibuf + mad24(iy1, SUM_BUF_STEP, ix1);
|
||||
#else
|
||||
__global const int* p = psum0 + mad24(iy1, sumstep, ix1);
|
||||
#endif
|
||||
|
||||
for( i = ntrees0; i < ntrees1; i++ )
|
||||
{
|
||||
float4 st = stump[i].st;
|
||||
__global const OptLBPFeature* f = optfeatures + as_int(st.x);
|
||||
int16 ofs = f->ofs;
|
||||
|
||||
#define CALC_SUM_OFS_(p0, p1, p2, p3, ptr) \
|
||||
((ptr)[p0] - (ptr)[p1] - (ptr)[p2] + (ptr)[p3])
|
||||
|
||||
int cval = CALC_SUM_OFS_( ofs.s5, ofs.s6, ofs.s9, ofs.sa, p );
|
||||
|
||||
int mask, idx = (CALC_SUM_OFS_( ofs.s0, ofs.s1, ofs.s4, ofs.s5, p ) >= cval ? 4 : 0); // 0
|
||||
idx |= (CALC_SUM_OFS_( ofs.s1, ofs.s2, ofs.s5, ofs.s6, p ) >= cval ? 2 : 0); // 1
|
||||
idx |= (CALC_SUM_OFS_( ofs.s2, ofs.s3, ofs.s6, ofs.s7, p ) >= cval ? 1 : 0); // 2
|
||||
|
||||
mask = (CALC_SUM_OFS_( ofs.s6, ofs.s7, ofs.sa, ofs.sb, p ) >= cval ? 16 : 0); // 5
|
||||
mask |= (CALC_SUM_OFS_( ofs.sa, ofs.sb, ofs.se, ofs.sf, p ) >= cval ? 8 : 0); // 8
|
||||
mask |= (CALC_SUM_OFS_( ofs.s9, ofs.sa, ofs.sd, ofs.se, p ) >= cval ? 4 : 0); // 7
|
||||
mask |= (CALC_SUM_OFS_( ofs.s8, ofs.s9, ofs.sc, ofs.sd, p ) >= cval ? 2 : 0); // 6
|
||||
mask |= (CALC_SUM_OFS_( ofs.s4, ofs.s5, ofs.s8, ofs.s9, p ) >= cval ? 1 : 0); // 7
|
||||
|
||||
partsum += (bitset[i*bitsetSize + idx] & (1 << mask)) ? st.z : st.w;
|
||||
}
|
||||
}
|
||||
}
|
||||
lpartsum[lidx] = partsum;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if( partidx == 0 )
|
||||
{
|
||||
float s = lpartsum[nr*nparts];
|
||||
for( i = 1; i < nparts; i++ )
|
||||
s += lpartsum[i + nr*nparts];
|
||||
if( s >= stages[stageIdx].threshold )
|
||||
{
|
||||
int count = atomic_inc(lcount);
|
||||
lbuf[count] = idxval;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if( stageIdx == N_STAGES )
|
||||
{
|
||||
int nrects = lcount[0];
|
||||
if( lidx < nrects )
|
||||
{
|
||||
int nfaces = atomic_inc(facepos);
|
||||
if( nfaces < MAX_FACES )
|
||||
{
|
||||
volatile __global int* face = facepos + 1 + nfaces*3;
|
||||
int val = lbuf[lidx];
|
||||
face[0] = scaleIdx;
|
||||
face[1] = ix0 + (val & 255);
|
||||
face[2] = iy0 + (val >> 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
633
3rdparty/opencv-4.5.4/modules/objdetect/src/opencl/objdetect_hog.cl
vendored
Normal file
633
3rdparty/opencv-4.5.4/modules/objdetect/src/opencl/objdetect_hog.cl
vendored
Normal file
@ -0,0 +1,633 @@
|
||||
/*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-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Wenju He, wenju@multicorewareinc.com
|
||||
//
|
||||
// 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*/
|
||||
|
||||
#define CELL_WIDTH 8
|
||||
#define CELL_HEIGHT 8
|
||||
#define CELLS_PER_BLOCK_X 2
|
||||
#define CELLS_PER_BLOCK_Y 2
|
||||
#define NTHREADS 256
|
||||
#define CV_PI_F M_PI_F
|
||||
|
||||
#ifdef INTEL_DEVICE
|
||||
#define QANGLE_TYPE int
|
||||
#define QANGLE_TYPE2 int2
|
||||
#else
|
||||
#define QANGLE_TYPE uchar
|
||||
#define QANGLE_TYPE2 uchar2
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Histogram computation
|
||||
// 12 threads for a cell, 12x4 threads per block
|
||||
// Use pre-computed gaussian and interp_weight lookup tables
|
||||
__kernel void compute_hists_lut_kernel(
|
||||
const int cblock_stride_x, const int cblock_stride_y,
|
||||
const int cnbins, const int cblock_hist_size, const int img_block_width,
|
||||
const int blocks_in_group, const int blocks_total,
|
||||
const int grad_quadstep, const int qangle_step,
|
||||
__global const float* grad, __global const QANGLE_TYPE* qangle,
|
||||
__global const float* gauss_w_lut,
|
||||
__global float* block_hists, __local float* smem)
|
||||
{
|
||||
const int lx = get_local_id(0);
|
||||
const int lp = lx / 24; /* local group id */
|
||||
const int gid = get_group_id(0) * blocks_in_group + lp;/* global group id */
|
||||
const int gidY = gid / img_block_width;
|
||||
const int gidX = gid - gidY * img_block_width;
|
||||
|
||||
const int lidX = lx - lp * 24;
|
||||
const int lidY = get_local_id(1);
|
||||
|
||||
const int cell_x = lidX / 12;
|
||||
const int cell_y = lidY;
|
||||
const int cell_thread_x = lidX - cell_x * 12;
|
||||
|
||||
__local float* hists = smem + lp * cnbins * (CELLS_PER_BLOCK_X *
|
||||
CELLS_PER_BLOCK_Y * 12 + CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y);
|
||||
__local float* final_hist = hists + cnbins *
|
||||
(CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y * 12);
|
||||
|
||||
const int offset_x = gidX * cblock_stride_x + (cell_x << 2) + cell_thread_x;
|
||||
const int offset_y = gidY * cblock_stride_y + (cell_y << 2);
|
||||
|
||||
__global const float* grad_ptr = (gid < blocks_total) ?
|
||||
grad + offset_y * grad_quadstep + (offset_x << 1) : grad;
|
||||
__global const QANGLE_TYPE* qangle_ptr = (gid < blocks_total) ?
|
||||
qangle + offset_y * qangle_step + (offset_x << 1) : qangle;
|
||||
|
||||
__local float* hist = hists + 12 * (cell_y * CELLS_PER_BLOCK_Y + cell_x) +
|
||||
cell_thread_x;
|
||||
for (int bin_id = 0; bin_id < cnbins; ++bin_id)
|
||||
hist[bin_id * 48] = 0.f;
|
||||
|
||||
const int dist_x = -4 + cell_thread_x - 4 * cell_x;
|
||||
const int dist_center_x = dist_x - 4 * (1 - 2 * cell_x);
|
||||
|
||||
const int dist_y_begin = -4 - 4 * lidY;
|
||||
for (int dist_y = dist_y_begin; dist_y < dist_y_begin + 12; ++dist_y)
|
||||
{
|
||||
float2 vote = (float2) (grad_ptr[0], grad_ptr[1]);
|
||||
QANGLE_TYPE2 bin = (QANGLE_TYPE2) (qangle_ptr[0], qangle_ptr[1]);
|
||||
|
||||
grad_ptr += grad_quadstep;
|
||||
qangle_ptr += qangle_step;
|
||||
|
||||
int dist_center_y = dist_y - 4 * (1 - 2 * cell_y);
|
||||
|
||||
int idx = (dist_center_y + 8) * 16 + (dist_center_x + 8);
|
||||
float gaussian = gauss_w_lut[idx];
|
||||
idx = (dist_y + 8) * 16 + (dist_x + 8);
|
||||
float interp_weight = gauss_w_lut[256+idx];
|
||||
|
||||
hist[bin.x * 48] += gaussian * interp_weight * vote.x;
|
||||
hist[bin.y * 48] += gaussian * interp_weight * vote.y;
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
volatile __local float* hist_ = hist;
|
||||
for (int bin_id = 0; bin_id < cnbins; ++bin_id, hist_ += 48)
|
||||
{
|
||||
if (cell_thread_x < 6)
|
||||
hist_[0] += hist_[6];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if (cell_thread_x < 3)
|
||||
hist_[0] += hist_[3];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if (cell_thread_x == 0)
|
||||
final_hist[(cell_x * 2 + cell_y) * cnbins + bin_id] =
|
||||
hist_[0] + hist_[1] + hist_[2];
|
||||
}
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
int tid = (cell_y * CELLS_PER_BLOCK_Y + cell_x) * 12 + cell_thread_x;
|
||||
if ((tid < cblock_hist_size) && (gid < blocks_total))
|
||||
{
|
||||
__global float* block_hist = block_hists +
|
||||
(gidY * img_block_width + gidX) * cblock_hist_size;
|
||||
block_hist[tid] = final_hist[tid];
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// Normalization of histograms via L2Hys_norm
|
||||
// optimized for the case of 9 bins
|
||||
__kernel void normalize_hists_36_kernel(__global float* block_hists,
|
||||
const float threshold, __local float *squares)
|
||||
{
|
||||
const int tid = get_local_id(0);
|
||||
const int gid = get_global_id(0);
|
||||
const int bid = tid / 36; /* block-hist id, (0 - 6) */
|
||||
const int boffset = bid * 36; /* block-hist offset in the work-group */
|
||||
const int hid = tid - boffset; /* histogram bin id, (0 - 35) */
|
||||
|
||||
float elem = block_hists[gid];
|
||||
squares[tid] = elem * elem;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
__local float* smem = squares + boffset;
|
||||
float sum = smem[hid];
|
||||
if (hid < 18)
|
||||
smem[hid] = sum = sum + smem[hid + 18];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if (hid < 9)
|
||||
smem[hid] = sum = sum + smem[hid + 9];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if (hid < 4)
|
||||
smem[hid] = sum + smem[hid + 4];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
sum = smem[0] + smem[1] + smem[2] + smem[3] + smem[8];
|
||||
|
||||
elem = elem / (sqrt(sum) + 3.6f);
|
||||
elem = min(elem, threshold);
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
squares[tid] = elem * elem;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
sum = smem[hid];
|
||||
if (hid < 18)
|
||||
smem[hid] = sum = sum + smem[hid + 18];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if (hid < 9)
|
||||
smem[hid] = sum = sum + smem[hid + 9];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if (hid < 4)
|
||||
smem[hid] = sum + smem[hid + 4];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
sum = smem[0] + smem[1] + smem[2] + smem[3] + smem[8];
|
||||
|
||||
block_hists[gid] = elem / (sqrt(sum) + 1e-3f);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// Normalization of histograms via L2Hys_norm
|
||||
//
|
||||
inline float reduce_smem(volatile __local float* smem, int size)
|
||||
{
|
||||
unsigned int tid = get_local_id(0);
|
||||
float sum = smem[tid];
|
||||
|
||||
if (size >= 512) { if (tid < 256) smem[tid] = sum = sum + smem[tid + 256];
|
||||
barrier(CLK_LOCAL_MEM_FENCE); }
|
||||
if (size >= 256) { if (tid < 128) smem[tid] = sum = sum + smem[tid + 128];
|
||||
barrier(CLK_LOCAL_MEM_FENCE); }
|
||||
if (size >= 128) { if (tid < 64) smem[tid] = sum = sum + smem[tid + 64];
|
||||
barrier(CLK_LOCAL_MEM_FENCE); }
|
||||
if (size >= 64) { if (tid < 32) smem[tid] = sum = sum + smem[tid + 32];
|
||||
barrier(CLK_LOCAL_MEM_FENCE); }
|
||||
if (size >= 32) { if (tid < 16) smem[tid] = sum = sum + smem[tid + 16];
|
||||
barrier(CLK_LOCAL_MEM_FENCE); }
|
||||
if (size >= 16) { if (tid < 8) smem[tid] = sum = sum + smem[tid + 8];
|
||||
barrier(CLK_LOCAL_MEM_FENCE); }
|
||||
if (size >= 8) { if (tid < 4) smem[tid] = sum = sum + smem[tid + 4];
|
||||
barrier(CLK_LOCAL_MEM_FENCE); }
|
||||
if (size >= 4) { if (tid < 2) smem[tid] = sum = sum + smem[tid + 2];
|
||||
barrier(CLK_LOCAL_MEM_FENCE); }
|
||||
if (size >= 2) { if (tid < 1) smem[tid] = sum = sum + smem[tid + 1];
|
||||
barrier(CLK_LOCAL_MEM_FENCE); }
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
__kernel void normalize_hists_kernel(
|
||||
const int nthreads, const int block_hist_size, const int img_block_width,
|
||||
__global float* block_hists, const float threshold, __local float *squares)
|
||||
{
|
||||
const int tid = get_local_id(0);
|
||||
const int gidX = get_group_id(0);
|
||||
const int gidY = get_group_id(1);
|
||||
|
||||
__global float* hist = block_hists + (gidY * img_block_width + gidX) *
|
||||
block_hist_size + tid;
|
||||
|
||||
float elem = 0.f;
|
||||
if (tid < block_hist_size)
|
||||
elem = hist[0];
|
||||
|
||||
squares[tid] = elem * elem;
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
float sum = reduce_smem(squares, nthreads);
|
||||
|
||||
float scale = 1.0f / (sqrt(sum) + 0.1f * block_hist_size);
|
||||
elem = min(elem * scale, threshold);
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
squares[tid] = elem * elem;
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
sum = reduce_smem(squares, nthreads);
|
||||
scale = 1.0f / (sqrt(sum) + 1e-3f);
|
||||
|
||||
if (tid < block_hist_size)
|
||||
hist[0] = elem * scale;
|
||||
}
|
||||
|
||||
#define reduce_with_sync(target, sharedMemory, localMemory, tid, offset) \
|
||||
if (tid < target) sharedMemory[tid] = localMemory = localMemory + sharedMemory[tid + offset]; \
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Linear SVM based classification
|
||||
// 48x96 window, 9 bins and default parameters
|
||||
// 180 threads, each thread corresponds to a bin in a row
|
||||
__kernel void classify_hists_180_kernel(
|
||||
const int cdescr_width, const int cdescr_height, const int cblock_hist_size,
|
||||
const int img_win_width, const int img_block_width,
|
||||
const int win_block_stride_x, const int win_block_stride_y,
|
||||
__global const float * block_hists, __global const float* coefs,
|
||||
float free_coef, float threshold, __global uchar* labels)
|
||||
{
|
||||
const int tid = get_local_id(0);
|
||||
const int gidX = get_group_id(0);
|
||||
const int gidY = get_group_id(1);
|
||||
|
||||
__global const float* hist = block_hists + (gidY * win_block_stride_y *
|
||||
img_block_width + gidX * win_block_stride_x) * cblock_hist_size;
|
||||
|
||||
float product = 0.f;
|
||||
|
||||
for (int i = 0; i < cdescr_height; i++)
|
||||
{
|
||||
product += coefs[i * cdescr_width + tid] *
|
||||
hist[i * img_block_width * cblock_hist_size + tid];
|
||||
}
|
||||
|
||||
__local float products[180];
|
||||
|
||||
products[tid] = product;
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
reduce_with_sync(90, products, product, tid, 90);
|
||||
reduce_with_sync(45, products, product, tid, 45);
|
||||
reduce_with_sync(13, products, product, tid, 32); // 13 is not typo
|
||||
reduce_with_sync(16, products, product, tid, 16);
|
||||
reduce_with_sync(8, products, product, tid, 8);
|
||||
reduce_with_sync(4, products, product, tid, 4);
|
||||
reduce_with_sync(2, products, product, tid, 2);
|
||||
|
||||
if (tid == 0){
|
||||
product = product + products[tid + 1];
|
||||
labels[gidY * img_win_width + gidX] = (product + free_coef >= threshold);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Linear SVM based classification
|
||||
// 64x128 window, 9 bins and default parameters
|
||||
// 256 threads, 252 of them are used
|
||||
__kernel void classify_hists_252_kernel(
|
||||
const int cdescr_width, const int cdescr_height, const int cblock_hist_size,
|
||||
const int img_win_width, const int img_block_width,
|
||||
const int win_block_stride_x, const int win_block_stride_y,
|
||||
__global const float * block_hists, __global const float* coefs,
|
||||
float free_coef, float threshold, __global uchar* labels)
|
||||
{
|
||||
const int tid = get_local_id(0);
|
||||
const int gidX = get_group_id(0);
|
||||
const int gidY = get_group_id(1);
|
||||
|
||||
__global const float* hist = block_hists + (gidY * win_block_stride_y *
|
||||
img_block_width + gidX * win_block_stride_x) * cblock_hist_size;
|
||||
|
||||
float product = 0.f;
|
||||
if (tid < cdescr_width)
|
||||
{
|
||||
for (int i = 0; i < cdescr_height; i++)
|
||||
product += coefs[i * cdescr_width + tid] *
|
||||
hist[i * img_block_width * cblock_hist_size + tid];
|
||||
}
|
||||
|
||||
__local float products[NTHREADS];
|
||||
|
||||
products[tid] = product;
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
reduce_with_sync(128, products, product, tid, 128);
|
||||
reduce_with_sync(64, products, product, tid, 64);
|
||||
reduce_with_sync(32, products, product, tid, 32);
|
||||
reduce_with_sync(16, products, product, tid, 16);
|
||||
reduce_with_sync(8, products, product, tid, 8);
|
||||
reduce_with_sync(4, products, product, tid, 4);
|
||||
reduce_with_sync(2, products, product, tid, 2);
|
||||
|
||||
if (tid == 0){
|
||||
product = product + products[tid + 1];
|
||||
labels[gidY * img_win_width + gidX] = (product + free_coef >= threshold);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Linear SVM based classification
|
||||
// 256 threads
|
||||
__kernel void classify_hists_kernel(
|
||||
const int cdescr_size, const int cdescr_width, const int cblock_hist_size,
|
||||
const int img_win_width, const int img_block_width,
|
||||
const int win_block_stride_x, const int win_block_stride_y,
|
||||
__global const float * block_hists, __global const float* coefs,
|
||||
float free_coef, float threshold, __global uchar* labels)
|
||||
{
|
||||
const int tid = get_local_id(0);
|
||||
const int gidX = get_group_id(0);
|
||||
const int gidY = get_group_id(1);
|
||||
|
||||
__global const float* hist = block_hists + (gidY * win_block_stride_y *
|
||||
img_block_width + gidX * win_block_stride_x) * cblock_hist_size;
|
||||
|
||||
float product = 0.f;
|
||||
for (int i = tid; i < cdescr_size; i += NTHREADS)
|
||||
{
|
||||
int offset_y = i / cdescr_width;
|
||||
int offset_x = i - offset_y * cdescr_width;
|
||||
product += coefs[i] *
|
||||
hist[offset_y * img_block_width * cblock_hist_size + offset_x];
|
||||
}
|
||||
|
||||
__local float products[NTHREADS];
|
||||
|
||||
products[tid] = product;
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
reduce_with_sync(128, products, product, tid, 128);
|
||||
reduce_with_sync(64, products, product, tid, 64);
|
||||
reduce_with_sync(32, products, product, tid, 32);
|
||||
reduce_with_sync(16, products, product, tid, 16);
|
||||
reduce_with_sync(8, products, product, tid, 8);
|
||||
reduce_with_sync(4, products, product, tid, 4);
|
||||
reduce_with_sync(2, products, product, tid, 2);
|
||||
|
||||
if (tid == 0){
|
||||
products[tid] = product = product + products[tid + 1];
|
||||
labels[gidY * img_win_width + gidX] = (product + free_coef >= threshold);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Extract descriptors
|
||||
|
||||
__kernel void extract_descrs_by_rows_kernel(
|
||||
const int cblock_hist_size, const int descriptors_quadstep,
|
||||
const int cdescr_size, const int cdescr_width, const int img_block_width,
|
||||
const int win_block_stride_x, const int win_block_stride_y,
|
||||
__global const float* block_hists, __global float* descriptors)
|
||||
{
|
||||
int tid = get_local_id(0);
|
||||
int gidX = get_group_id(0);
|
||||
int gidY = get_group_id(1);
|
||||
|
||||
// Get left top corner of the window in src
|
||||
__global const float* hist = block_hists + (gidY * win_block_stride_y *
|
||||
img_block_width + gidX * win_block_stride_x) * cblock_hist_size;
|
||||
|
||||
// Get left top corner of the window in dst
|
||||
__global float* descriptor = descriptors +
|
||||
(gidY * get_num_groups(0) + gidX) * descriptors_quadstep;
|
||||
|
||||
// Copy elements from src to dst
|
||||
for (int i = tid; i < cdescr_size; i += NTHREADS)
|
||||
{
|
||||
int offset_y = i / cdescr_width;
|
||||
int offset_x = i - offset_y * cdescr_width;
|
||||
descriptor[i] = hist[offset_y * img_block_width * cblock_hist_size + offset_x];
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void extract_descrs_by_cols_kernel(
|
||||
const int cblock_hist_size, const int descriptors_quadstep, const int cdescr_size,
|
||||
const int cnblocks_win_x, const int cnblocks_win_y, const int img_block_width,
|
||||
const int win_block_stride_x, const int win_block_stride_y,
|
||||
__global const float* block_hists, __global float* descriptors)
|
||||
{
|
||||
int tid = get_local_id(0);
|
||||
int gidX = get_group_id(0);
|
||||
int gidY = get_group_id(1);
|
||||
|
||||
// Get left top corner of the window in src
|
||||
__global const float* hist = block_hists + (gidY * win_block_stride_y *
|
||||
img_block_width + gidX * win_block_stride_x) * cblock_hist_size;
|
||||
|
||||
// Get left top corner of the window in dst
|
||||
__global float* descriptor = descriptors +
|
||||
(gidY * get_num_groups(0) + gidX) * descriptors_quadstep;
|
||||
|
||||
// Copy elements from src to dst
|
||||
for (int i = tid; i < cdescr_size; i += NTHREADS)
|
||||
{
|
||||
int block_idx = i / cblock_hist_size;
|
||||
int idx_in_block = i - block_idx * cblock_hist_size;
|
||||
|
||||
int y = block_idx / cnblocks_win_x;
|
||||
int x = block_idx - y * cnblocks_win_x;
|
||||
|
||||
descriptor[(x * cnblocks_win_y + y) * cblock_hist_size + idx_in_block] =
|
||||
hist[(y * img_block_width + x) * cblock_hist_size + idx_in_block];
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Gradients computation
|
||||
|
||||
__kernel void compute_gradients_8UC4_kernel(
|
||||
const int height, const int width,
|
||||
const int img_step, const int grad_quadstep, const int qangle_step,
|
||||
const __global uchar4 * img, __global float * grad, __global QANGLE_TYPE * qangle,
|
||||
const float angle_scale, const char correct_gamma, const int cnbins)
|
||||
{
|
||||
const int x = get_global_id(0);
|
||||
const int tid = get_local_id(0);
|
||||
const int gSizeX = get_local_size(0);
|
||||
const int gidY = get_group_id(1);
|
||||
|
||||
__global const uchar4* row = img + gidY * img_step;
|
||||
|
||||
__local float sh_row[(NTHREADS + 2) * 3];
|
||||
|
||||
uchar4 val;
|
||||
if (x < width)
|
||||
val = row[x];
|
||||
else
|
||||
val = row[width - 2];
|
||||
|
||||
sh_row[tid + 1] = val.x;
|
||||
sh_row[tid + 1 + (NTHREADS + 2)] = val.y;
|
||||
sh_row[tid + 1 + 2 * (NTHREADS + 2)] = val.z;
|
||||
|
||||
if (tid == 0)
|
||||
{
|
||||
val = row[max(x - 1, 1)];
|
||||
sh_row[0] = val.x;
|
||||
sh_row[(NTHREADS + 2)] = val.y;
|
||||
sh_row[2 * (NTHREADS + 2)] = val.z;
|
||||
}
|
||||
|
||||
if (tid == gSizeX - 1)
|
||||
{
|
||||
val = row[min(x + 1, width - 2)];
|
||||
sh_row[gSizeX + 1] = val.x;
|
||||
sh_row[gSizeX + 1 + (NTHREADS + 2)] = val.y;
|
||||
sh_row[gSizeX + 1 + 2 * (NTHREADS + 2)] = val.z;
|
||||
}
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if (x < width)
|
||||
{
|
||||
float4 a = (float4) (sh_row[tid], sh_row[tid + (NTHREADS + 2)],
|
||||
sh_row[tid + 2 * (NTHREADS + 2)], 0);
|
||||
float4 b = (float4) (sh_row[tid + 2], sh_row[tid + 2 + (NTHREADS + 2)],
|
||||
sh_row[tid + 2 + 2 * (NTHREADS + 2)], 0);
|
||||
|
||||
float4 dx;
|
||||
if (correct_gamma == 1)
|
||||
dx = sqrt(b) - sqrt(a);
|
||||
else
|
||||
dx = b - a;
|
||||
|
||||
float4 dy = (float4) 0.f;
|
||||
|
||||
if (gidY > 0 && gidY < height - 1)
|
||||
{
|
||||
a = convert_float4(img[(gidY - 1) * img_step + x].xyzw);
|
||||
b = convert_float4(img[(gidY + 1) * img_step + x].xyzw);
|
||||
|
||||
if (correct_gamma == 1)
|
||||
dy = sqrt(b) - sqrt(a);
|
||||
else
|
||||
dy = b - a;
|
||||
}
|
||||
|
||||
float4 mag = hypot(dx, dy);
|
||||
float best_dx = dx.x;
|
||||
float best_dy = dy.x;
|
||||
|
||||
float mag0 = mag.x;
|
||||
if (mag0 < mag.y)
|
||||
{
|
||||
best_dx = dx.y;
|
||||
best_dy = dy.y;
|
||||
mag0 = mag.y;
|
||||
}
|
||||
|
||||
if (mag0 < mag.z)
|
||||
{
|
||||
best_dx = dx.z;
|
||||
best_dy = dy.z;
|
||||
mag0 = mag.z;
|
||||
}
|
||||
|
||||
float ang = (atan2(best_dy, best_dx) + CV_PI_F) * angle_scale - 0.5f;
|
||||
int hidx = (int)floor(ang);
|
||||
ang -= hidx;
|
||||
hidx = (hidx + cnbins) % cnbins;
|
||||
|
||||
qangle[(gidY * qangle_step + x) << 1] = hidx;
|
||||
qangle[((gidY * qangle_step + x) << 1) + 1] = (hidx + 1) % cnbins;
|
||||
grad[(gidY * grad_quadstep + x) << 1] = mag0 * (1.f - ang);
|
||||
grad[((gidY * grad_quadstep + x) << 1) + 1] = mag0 * ang;
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void compute_gradients_8UC1_kernel(
|
||||
const int height, const int width,
|
||||
const int img_step, const int grad_quadstep, const int qangle_step,
|
||||
__global const uchar * img, __global float * grad, __global QANGLE_TYPE * qangle,
|
||||
const float angle_scale, const char correct_gamma, const int cnbins)
|
||||
{
|
||||
const int x = get_global_id(0);
|
||||
const int tid = get_local_id(0);
|
||||
const int gSizeX = get_local_size(0);
|
||||
const int gidY = get_group_id(1);
|
||||
|
||||
__global const uchar* row = img + gidY * img_step;
|
||||
|
||||
__local float sh_row[NTHREADS + 2];
|
||||
|
||||
if (x < width)
|
||||
sh_row[tid + 1] = row[x];
|
||||
else
|
||||
sh_row[tid + 1] = row[width - 2];
|
||||
|
||||
if (tid == 0)
|
||||
sh_row[0] = row[max(x - 1, 1)];
|
||||
|
||||
if (tid == gSizeX - 1)
|
||||
sh_row[gSizeX + 1] = row[min(x + 1, width - 2)];
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if (x < width)
|
||||
{
|
||||
float dx;
|
||||
|
||||
if (correct_gamma == 1)
|
||||
dx = sqrt(sh_row[tid + 2]) - sqrt(sh_row[tid]);
|
||||
else
|
||||
dx = sh_row[tid + 2] - sh_row[tid];
|
||||
|
||||
float dy = 0.f;
|
||||
if (gidY > 0 && gidY < height - 1)
|
||||
{
|
||||
float a = (float) img[ (gidY + 1) * img_step + x ];
|
||||
float b = (float) img[ (gidY - 1) * img_step + x ];
|
||||
if (correct_gamma == 1)
|
||||
dy = sqrt(a) - sqrt(b);
|
||||
else
|
||||
dy = a - b;
|
||||
}
|
||||
float mag = hypot(dx, dy);
|
||||
|
||||
float ang = (atan2(dy, dx) + CV_PI_F) * angle_scale - 0.5f;
|
||||
int hidx = (int)floor(ang);
|
||||
ang -= hidx;
|
||||
hidx = (hidx + cnbins) % cnbins;
|
||||
|
||||
qangle[ (gidY * qangle_step + x) << 1 ] = hidx;
|
||||
qangle[ ((gidY * qangle_step + x) << 1) + 1 ] = (hidx + 1) % cnbins;
|
||||
grad[ (gidY * grad_quadstep + x) << 1 ] = mag * (1.f - ang);
|
||||
grad[ ((gidY * grad_quadstep + x) << 1) + 1 ] = mag * ang;
|
||||
}
|
||||
}
|
53
3rdparty/opencv-4.5.4/modules/objdetect/src/precomp.hpp
vendored
Normal file
53
3rdparty/opencv-4.5.4/modules/objdetect/src/precomp.hpp
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
/*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*/
|
||||
|
||||
#ifndef __OPENCV_PRECOMP_H__
|
||||
#define __OPENCV_PRECOMP_H__
|
||||
|
||||
#include "opencv2/objdetect.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
|
||||
#include "opencv2/core/utility.hpp"
|
||||
#include "opencv2/core/ocl.hpp"
|
||||
#include "opencv2/core/private.hpp"
|
||||
|
||||
#endif
|
3673
3rdparty/opencv-4.5.4/modules/objdetect/src/qrcode.cpp
vendored
Normal file
3673
3rdparty/opencv-4.5.4/modules/objdetect/src/qrcode.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
140
3rdparty/opencv-4.5.4/modules/objdetect/test/opencl/test_hogdetector.cpp
vendored
Normal file
140
3rdparty/opencv-4.5.4/modules/objdetect/test/opencl/test_hogdetector.cpp
vendored
Normal file
@ -0,0 +1,140 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Niko Li, newlife20080214@gmail.com
|
||||
// Jia Haipeng, jiahaipeng95@gmail.com
|
||||
// Shengen Yan, yanshengen@gmail.com
|
||||
// Jiang Liyuan,jlyuan001.good@163.com
|
||||
// Rock Li, Rock.Li@amd.com
|
||||
// Zailong Wu, bullet@yeah.net
|
||||
// Yao Wang, bitwangyaoyao@gmail.com
|
||||
//
|
||||
// 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 "opencv2/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
|
||||
///////////////////// HOG /////////////////////////////
|
||||
PARAM_TEST_CASE(HOG, Size, MatType)
|
||||
{
|
||||
Size winSize;
|
||||
int type;
|
||||
Mat img;
|
||||
UMat uimg;
|
||||
virtual void SetUp()
|
||||
{
|
||||
winSize = GET_PARAM(0);
|
||||
type = GET_PARAM(1);
|
||||
img = readImage("cascadeandhog/images/image_00000000_0.png", IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(img.empty());
|
||||
img.copyTo(uimg);
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(HOG, GetDescriptors)
|
||||
{
|
||||
HOGDescriptor hog;
|
||||
hog.gammaCorrection = true;
|
||||
|
||||
hog.setSVMDetector(hog.getDefaultPeopleDetector());
|
||||
|
||||
std::vector<float> cpu_descriptors;
|
||||
std::vector<float> gpu_descriptors;
|
||||
|
||||
OCL_OFF(hog.compute(img, cpu_descriptors, hog.winSize));
|
||||
OCL_ON(hog.compute(uimg, gpu_descriptors, hog.winSize));
|
||||
|
||||
Mat cpu_desc(cpu_descriptors), gpu_desc(gpu_descriptors);
|
||||
|
||||
EXPECT_MAT_SIMILAR(cpu_desc, gpu_desc, 1e-1);
|
||||
}
|
||||
|
||||
OCL_TEST_P(HOG, SVMDetector)
|
||||
{
|
||||
HOGDescriptor hog_first, hog_second;
|
||||
|
||||
// empty -> empty
|
||||
hog_first.copyTo(hog_second);
|
||||
|
||||
// first -> both
|
||||
hog_first.setSVMDetector(hog_first.getDefaultPeopleDetector());
|
||||
hog_first.copyTo(hog_second);
|
||||
|
||||
// both -> both
|
||||
hog_first.copyTo(hog_second);
|
||||
|
||||
// second -> empty
|
||||
hog_first.setSVMDetector(cv::noArray());
|
||||
hog_first.copyTo(hog_second);
|
||||
}
|
||||
|
||||
OCL_TEST_P(HOG, Detect)
|
||||
{
|
||||
HOGDescriptor hog;
|
||||
hog.winSize = winSize;
|
||||
hog.gammaCorrection = true;
|
||||
|
||||
if (winSize.width == 48 && winSize.height == 96)
|
||||
hog.setSVMDetector(hog.getDaimlerPeopleDetector());
|
||||
else
|
||||
hog.setSVMDetector(hog.getDefaultPeopleDetector());
|
||||
|
||||
std::vector<Rect> cpu_found;
|
||||
std::vector<Rect> gpu_found;
|
||||
|
||||
OCL_OFF(hog.detectMultiScale(img, cpu_found, 0, Size(8, 8), Size(0, 0), 1.05, 6));
|
||||
OCL_ON(hog.detectMultiScale(uimg, gpu_found, 0, Size(8, 8), Size(0, 0), 1.05, 6));
|
||||
|
||||
EXPECT_LT(checkRectSimilarity(img.size(), cpu_found, gpu_found), 0.05);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(OCL_ObjDetect, HOG, testing::Combine(
|
||||
testing::Values(Size(64, 128), Size(48, 96)),
|
||||
testing::Values( MatType(CV_8UC1) ) ) );
|
||||
|
||||
}} // namespace
|
||||
#endif
|
1366
3rdparty/opencv-4.5.4/modules/objdetect/test/test_cascadeandhog.cpp
vendored
Normal file
1366
3rdparty/opencv-4.5.4/modules/objdetect/test/test_cascadeandhog.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
219
3rdparty/opencv-4.5.4/modules/objdetect/test/test_face.cpp
vendored
Normal file
219
3rdparty/opencv-4.5.4/modules/objdetect/test/test_face.cpp
vendored
Normal file
@ -0,0 +1,219 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
// label format:
|
||||
// image_name
|
||||
// num_face
|
||||
// face_1
|
||||
// face_..
|
||||
// face_num
|
||||
std::map<std::string, Mat> blobFromTXT(const std::string& path, int numCoords)
|
||||
{
|
||||
std::ifstream ifs(path.c_str());
|
||||
CV_Assert(ifs.is_open());
|
||||
|
||||
std::map<std::string, Mat> gt;
|
||||
|
||||
Mat faces;
|
||||
int faceNum = -1;
|
||||
int faceCount = 0;
|
||||
for (std::string line, key; getline(ifs, line); )
|
||||
{
|
||||
std::istringstream iss(line);
|
||||
if (line.find(".png") != std::string::npos)
|
||||
{
|
||||
// Get filename
|
||||
iss >> key;
|
||||
}
|
||||
else if (line.find(" ") == std::string::npos)
|
||||
{
|
||||
// Get the number of faces
|
||||
iss >> faceNum;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get faces
|
||||
Mat face(1, numCoords, CV_32FC1);
|
||||
for (int j = 0; j < numCoords; j++)
|
||||
{
|
||||
iss >> face.at<float>(0, j);
|
||||
}
|
||||
faces.push_back(face);
|
||||
faceCount++;
|
||||
}
|
||||
|
||||
if (faceCount == faceNum)
|
||||
{
|
||||
// Store faces
|
||||
gt[key] = faces;
|
||||
|
||||
faces.release();
|
||||
faceNum = -1;
|
||||
faceCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return gt;
|
||||
}
|
||||
|
||||
TEST(Objdetect_face_detection, regression)
|
||||
{
|
||||
// Pre-set params
|
||||
float scoreThreshold = 0.7f;
|
||||
float matchThreshold = 0.9f;
|
||||
float l2disThreshold = 5.0f;
|
||||
int numLM = 5;
|
||||
int numCoords = 4 + 2 * numLM;
|
||||
|
||||
// Load ground truth labels
|
||||
std::map<std::string, Mat> gt = blobFromTXT(findDataFile("dnn_face/detection/cascades_labels.txt"), numCoords);
|
||||
// for (auto item: gt)
|
||||
// {
|
||||
// std::cout << item.first << " " << item.second.size() << std::endl;
|
||||
// }
|
||||
|
||||
// Initialize detector
|
||||
std::string model = findDataFile("dnn/onnx/models/yunet-202109.onnx", false);
|
||||
Ptr<FaceDetectorYN> faceDetector = FaceDetectorYN::create(model, "", Size(300, 300));
|
||||
faceDetector->setScoreThreshold(0.7f);
|
||||
|
||||
// Detect and match
|
||||
for (auto item: gt)
|
||||
{
|
||||
std::string imagePath = findDataFile("cascadeandhog/images/" + item.first);
|
||||
Mat image = imread(imagePath);
|
||||
|
||||
// Set input size
|
||||
faceDetector->setInputSize(image.size());
|
||||
|
||||
// Run detection
|
||||
Mat faces;
|
||||
faceDetector->detect(image, faces);
|
||||
// std::cout << item.first << " " << item.second.rows << " " << faces.rows << std::endl;
|
||||
|
||||
// Match bboxes and landmarks
|
||||
std::vector<bool> matchedItem(item.second.rows, false);
|
||||
for (int i = 0; i < faces.rows; i++)
|
||||
{
|
||||
if (faces.at<float>(i, numCoords) < scoreThreshold)
|
||||
continue;
|
||||
|
||||
bool boxMatched = false;
|
||||
std::vector<bool> lmMatched(numLM, false);
|
||||
cv::Rect2f resBox(faces.at<float>(i, 0), faces.at<float>(i, 1), faces.at<float>(i, 2), faces.at<float>(i, 3));
|
||||
for (int j = 0; j < item.second.rows && !boxMatched; j++)
|
||||
{
|
||||
if (matchedItem[j])
|
||||
continue;
|
||||
|
||||
// Retrieve bbox and compare IoU
|
||||
cv::Rect2f gtBox(item.second.at<float>(j, 0), item.second.at<float>(j, 1), item.second.at<float>(j, 2), item.second.at<float>(j, 3));
|
||||
double interArea = (resBox & gtBox).area();
|
||||
double iou = interArea / (resBox.area() + gtBox.area() - interArea);
|
||||
if (iou >= matchThreshold)
|
||||
{
|
||||
boxMatched = true;
|
||||
matchedItem[j] = true;
|
||||
}
|
||||
|
||||
// Match landmarks if bbox is matched
|
||||
if (!boxMatched)
|
||||
continue;
|
||||
for (int lmIdx = 0; lmIdx < numLM; lmIdx++)
|
||||
{
|
||||
float gtX = item.second.at<float>(j, 4 + 2 * lmIdx);
|
||||
float gtY = item.second.at<float>(j, 4 + 2 * lmIdx + 1);
|
||||
float resX = faces.at<float>(i, 4 + 2 * lmIdx);
|
||||
float resY = faces.at<float>(i, 4 + 2 * lmIdx + 1);
|
||||
float l2dis = cv::sqrt((gtX - resX) * (gtX - resX) + (gtY - resY) * (gtY - resY));
|
||||
|
||||
if (l2dis <= l2disThreshold)
|
||||
{
|
||||
lmMatched[lmIdx] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPECT_TRUE(boxMatched) << "In image " << item.first << ", cannot match resBox " << resBox << " with any ground truth.";
|
||||
if (boxMatched)
|
||||
{
|
||||
EXPECT_TRUE(std::all_of(lmMatched.begin(), lmMatched.end(), [](bool v) { return v; })) << "In image " << item.first << ", resBox " << resBox << " matched but its landmarks failed to match.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Objdetect_face_recognition, regression)
|
||||
{
|
||||
// Pre-set params
|
||||
float score_thresh = 0.9f;
|
||||
float nms_thresh = 0.3f;
|
||||
double cosine_similar_thresh = 0.363;
|
||||
double l2norm_similar_thresh = 1.128;
|
||||
|
||||
// Load ground truth labels
|
||||
std::ifstream ifs(findDataFile("dnn_face/recognition/cascades_label.txt").c_str());
|
||||
CV_Assert(ifs.is_open());
|
||||
|
||||
std::set<std::string> fSet;
|
||||
std::map<std::string, Mat> featureMap;
|
||||
std::map<std::pair<std::string, std::string>, int> gtMap;
|
||||
|
||||
|
||||
for (std::string line, key; getline(ifs, line);)
|
||||
{
|
||||
std::string fname1, fname2;
|
||||
int label;
|
||||
std::istringstream iss(line);
|
||||
iss>>fname1>>fname2>>label;
|
||||
// std::cout<<fname1<<" "<<fname2<<" "<<label<<std::endl;
|
||||
|
||||
fSet.insert(fname1);
|
||||
fSet.insert(fname2);
|
||||
gtMap[std::make_pair(fname1, fname2)] = label;
|
||||
}
|
||||
|
||||
// Initialize detector
|
||||
std::string detect_model = findDataFile("dnn/onnx/models/yunet-202109.onnx", false);
|
||||
Ptr<FaceDetectorYN> faceDetector = FaceDetectorYN::create(detect_model, "", Size(150, 150), score_thresh, nms_thresh);
|
||||
|
||||
std::string recog_model = findDataFile("dnn/onnx/models/face_recognizer_fast.onnx", false);
|
||||
Ptr<FaceRecognizerSF> faceRecognizer = FaceRecognizerSF::create(recog_model, "");
|
||||
|
||||
// Detect and match
|
||||
for (auto fname: fSet)
|
||||
{
|
||||
std::string imagePath = findDataFile("dnn_face/recognition/" + fname);
|
||||
Mat image = imread(imagePath);
|
||||
|
||||
Mat faces;
|
||||
faceDetector->detect(image, faces);
|
||||
|
||||
Mat aligned_face;
|
||||
faceRecognizer->alignCrop(image, faces.row(0), aligned_face);
|
||||
|
||||
Mat feature;
|
||||
faceRecognizer->feature(aligned_face, feature);
|
||||
|
||||
featureMap[fname] = feature.clone();
|
||||
}
|
||||
|
||||
for (auto item: gtMap)
|
||||
{
|
||||
Mat feature1 = featureMap[item.first.first];
|
||||
Mat feature2 = featureMap[item.first.second];
|
||||
int label = item.second;
|
||||
|
||||
double cos_score = faceRecognizer->match(feature1, feature2, FaceRecognizerSF::DisType::FR_COSINE);
|
||||
double L2_score = faceRecognizer->match(feature1, feature2, FaceRecognizerSF::DisType::FR_NORM_L2);
|
||||
|
||||
EXPECT_TRUE(label == 0 ? cos_score <= cosine_similar_thresh : cos_score > cosine_similar_thresh) << "Cosine match result of images " << item.first.first << " and " << item.first.second << " is different from ground truth (score: "<< cos_score <<";Thresh: "<< cosine_similar_thresh <<").";
|
||||
EXPECT_TRUE(label == 0 ? L2_score > l2norm_similar_thresh : L2_score <= l2norm_similar_thresh) << "L2norm match result of images " << item.first.first << " and " << item.first.second << " is different from ground truth (score: "<< L2_score <<";Thresh: "<< l2norm_similar_thresh <<").";
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace
|
25
3rdparty/opencv-4.5.4/modules/objdetect/test/test_main.cpp
vendored
Normal file
25
3rdparty/opencv-4.5.4/modules/objdetect/test/test_main.cpp
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
#if defined(HAVE_HPX)
|
||||
#include <hpx/hpx_main.hpp>
|
||||
#endif
|
||||
|
||||
static
|
||||
void initTests()
|
||||
{
|
||||
#ifdef HAVE_OPENCV_DNN
|
||||
const char* extraTestDataPath =
|
||||
#ifdef WINRT
|
||||
NULL;
|
||||
#else
|
||||
getenv("OPENCV_DNN_TEST_DATA_PATH");
|
||||
#endif
|
||||
if (extraTestDataPath)
|
||||
cvtest::addDataSearchPath(extraTestDataPath);
|
||||
#endif // HAVE_OPENCV_DNN
|
||||
}
|
||||
|
||||
CV_TEST_MAIN("cv", initTests())
|
10
3rdparty/opencv-4.5.4/modules/objdetect/test/test_precomp.hpp
vendored
Normal file
10
3rdparty/opencv-4.5.4/modules/objdetect/test/test_precomp.hpp
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#ifndef __OPENCV_TEST_PRECOMP_HPP__
|
||||
#define __OPENCV_TEST_PRECOMP_HPP__
|
||||
|
||||
#include "opencv2/ts.hpp"
|
||||
#include "opencv2/objdetect.hpp"
|
||||
|
||||
#endif
|
670
3rdparty/opencv-4.5.4/modules/objdetect/test/test_qrcode.cpp
vendored
Normal file
670
3rdparty/opencv-4.5.4/modules/objdetect/test/test_qrcode.cpp
vendored
Normal file
@ -0,0 +1,670 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
std::string qrcode_images_name[] = {
|
||||
"version_1_down.jpg", "version_1_left.jpg", "version_1_right.jpg", "version_1_up.jpg", "version_1_top.jpg",
|
||||
"version_2_down.jpg", "version_2_left.jpg", "version_2_right.jpg", "version_2_up.jpg", "version_2_top.jpg",
|
||||
"version_3_down.jpg", "version_3_left.jpg", "version_3_right.jpg", "version_3_up.jpg", "version_3_top.jpg",
|
||||
"version_4_down.jpg", "version_4_left.jpg", "version_4_right.jpg", "version_4_up.jpg", "version_4_top.jpg",
|
||||
"version_5_down.jpg", "version_5_left.jpg", "version_5_right.jpg", "version_5_up.jpg", "version_5_top.jpg",
|
||||
"russian.jpg", "kanji.jpg", "link_github_ocv.jpg", "link_ocv.jpg", "link_wiki_cv.jpg"
|
||||
};
|
||||
|
||||
std::string qrcode_images_close[] = {
|
||||
"close_1.png", "close_2.png", "close_3.png", "close_4.png", "close_5.png"
|
||||
};
|
||||
std::string qrcode_images_monitor[] = {
|
||||
"monitor_1.png", "monitor_2.png", "monitor_3.png", "monitor_4.png", "monitor_5.png"
|
||||
};
|
||||
std::string qrcode_images_curved[] = {
|
||||
"curved_1.jpg", "curved_2.jpg", "curved_3.jpg", "curved_4.jpg", "curved_5.jpg", "curved_6.jpg", "curved_7.jpg", "curved_8.jpg"
|
||||
};
|
||||
std::string qrcode_images_multiple[] = {
|
||||
"2_qrcodes.png", "3_close_qrcodes.png", "3_qrcodes.png", "4_qrcodes.png",
|
||||
"5_qrcodes.png", "6_qrcodes.png", "7_qrcodes.png", "8_close_qrcodes.png"
|
||||
};
|
||||
//#define UPDATE_QRCODE_TEST_DATA
|
||||
#ifdef UPDATE_QRCODE_TEST_DATA
|
||||
|
||||
TEST(Objdetect_QRCode, generate_test_data)
|
||||
{
|
||||
const std::string root = "qrcode/";
|
||||
const std::string dataset_config = findDataFile(root + "dataset_config.json");
|
||||
FileStorage file_config(dataset_config, FileStorage::WRITE);
|
||||
|
||||
file_config << "test_images" << "[";
|
||||
size_t images_count = sizeof(qrcode_images_name) / sizeof(qrcode_images_name[0]);
|
||||
for (size_t i = 0; i < images_count; i++)
|
||||
{
|
||||
file_config << "{:" << "image_name" << qrcode_images_name[i];
|
||||
std::string image_path = findDataFile(root + qrcode_images_name[i]);
|
||||
std::vector<Point> corners;
|
||||
Mat src = imread(image_path, IMREAD_GRAYSCALE), straight_barcode;
|
||||
std::string decoded_info;
|
||||
ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path;
|
||||
EXPECT_TRUE(detectQRCode(src, corners));
|
||||
#ifdef HAVE_QUIRC
|
||||
EXPECT_TRUE(decodeQRCode(src, corners, decoded_info, straight_barcode));
|
||||
#endif
|
||||
file_config << "x" << "[:";
|
||||
for (size_t j = 0; j < corners.size(); j++) { file_config << corners[j].x; }
|
||||
file_config << "]";
|
||||
file_config << "y" << "[:";
|
||||
for (size_t j = 0; j < corners.size(); j++) { file_config << corners[j].y; }
|
||||
file_config << "]";
|
||||
file_config << "info" << decoded_info;
|
||||
file_config << "}";
|
||||
}
|
||||
file_config << "]";
|
||||
file_config.release();
|
||||
}
|
||||
|
||||
TEST(Objdetect_QRCode_Close, generate_test_data)
|
||||
{
|
||||
const std::string root = "qrcode/close/";
|
||||
const std::string dataset_config = findDataFile(root + "dataset_config.json");
|
||||
FileStorage file_config(dataset_config, FileStorage::WRITE);
|
||||
|
||||
file_config << "close_images" << "[";
|
||||
size_t close_count = sizeof(qrcode_images_close) / sizeof(qrcode_images_close[0]);
|
||||
for (size_t i = 0; i < close_count; i++)
|
||||
{
|
||||
file_config << "{:" << "image_name" << qrcode_images_close[i];
|
||||
std::string image_path = findDataFile(root + qrcode_images_close[i]);
|
||||
std::vector<Point> corners;
|
||||
Mat src = imread(image_path, IMREAD_GRAYSCALE), barcode, straight_barcode;
|
||||
std::string decoded_info;
|
||||
ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path;
|
||||
const double min_side = std::min(src.size().width, src.size().height);
|
||||
double coeff_expansion = 1024.0 / min_side;
|
||||
const int width = cvRound(src.size().width * coeff_expansion);
|
||||
const int height = cvRound(src.size().height * coeff_expansion);
|
||||
Size new_size(width, height);
|
||||
resize(src, barcode, new_size, 0, 0, INTER_LINEAR);
|
||||
EXPECT_TRUE(detectQRCode(barcode, corners));
|
||||
#ifdef HAVE_QUIRC
|
||||
EXPECT_TRUE(decodeQRCode(barcode, corners, decoded_info, straight_barcode));
|
||||
#endif
|
||||
file_config << "x" << "[:";
|
||||
for (size_t j = 0; j < corners.size(); j++) { file_config << corners[j].x; }
|
||||
file_config << "]";
|
||||
file_config << "y" << "[:";
|
||||
for (size_t j = 0; j < corners.size(); j++) { file_config << corners[j].y; }
|
||||
file_config << "]";
|
||||
file_config << "info" << decoded_info;
|
||||
file_config << "}";
|
||||
}
|
||||
file_config << "]";
|
||||
file_config.release();
|
||||
}
|
||||
TEST(Objdetect_QRCode_Monitor, generate_test_data)
|
||||
{
|
||||
const std::string root = "qrcode/monitor/";
|
||||
const std::string dataset_config = findDataFile(root + "dataset_config.json");
|
||||
FileStorage file_config(dataset_config, FileStorage::WRITE);
|
||||
|
||||
file_config << "monitor_images" << "[";
|
||||
size_t monitor_count = sizeof(qrcode_images_monitor) / sizeof(qrcode_images_monitor[0]);
|
||||
for (size_t i = 0; i < monitor_count; i++)
|
||||
{
|
||||
file_config << "{:" << "image_name" << qrcode_images_monitor[i];
|
||||
std::string image_path = findDataFile(root + qrcode_images_monitor[i]);
|
||||
std::vector<Point> corners;
|
||||
Mat src = imread(image_path, IMREAD_GRAYSCALE), barcode, straight_barcode;
|
||||
std::string decoded_info;
|
||||
ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path;
|
||||
const double min_side = std::min(src.size().width, src.size().height);
|
||||
double coeff_expansion = 1024.0 / min_side;
|
||||
const int width = cvRound(src.size().width * coeff_expansion);
|
||||
const int height = cvRound(src.size().height * coeff_expansion);
|
||||
Size new_size(width, height);
|
||||
resize(src, barcode, new_size, 0, 0, INTER_LINEAR);
|
||||
EXPECT_TRUE(detectQRCode(barcode, corners));
|
||||
#ifdef HAVE_QUIRC
|
||||
EXPECT_TRUE(decodeQRCode(barcode, corners, decoded_info, straight_barcode));
|
||||
#endif
|
||||
file_config << "x" << "[:";
|
||||
for (size_t j = 0; j < corners.size(); j++) { file_config << corners[j].x; }
|
||||
file_config << "]";
|
||||
file_config << "y" << "[:";
|
||||
for (size_t j = 0; j < corners.size(); j++) { file_config << corners[j].y; }
|
||||
file_config << "]";
|
||||
file_config << "info" << decoded_info;
|
||||
file_config << "}";
|
||||
}
|
||||
file_config << "]";
|
||||
file_config.release();
|
||||
}
|
||||
TEST(Objdetect_QRCode_Curved, generate_test_data)
|
||||
{
|
||||
const std::string root = "qrcode/curved/";
|
||||
const std::string dataset_config = findDataFile(root + "dataset_config.json");
|
||||
FileStorage file_config(dataset_config, FileStorage::WRITE);
|
||||
|
||||
file_config << "test_images" << "[";
|
||||
size_t images_count = sizeof(qrcode_images_curved) / sizeof(qrcode_images_curved[0]);
|
||||
for (size_t i = 0; i < images_count; i++)
|
||||
{
|
||||
file_config << "{:" << "image_name" << qrcode_images_curved[i];
|
||||
std::string image_path = findDataFile(root + qrcode_images_curved[i]);
|
||||
std::vector<Point> corners;
|
||||
Mat src = imread(image_path, IMREAD_GRAYSCALE), straight_barcode;
|
||||
std::string decoded_info;
|
||||
ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path;
|
||||
EXPECT_TRUE(detectQRCode(src, corners));
|
||||
#ifdef HAVE_QUIRC
|
||||
EXPECT_TRUE(decodeCurvedQRCode(src, corners, decoded_info, straight_barcode));
|
||||
#endif
|
||||
file_config << "x" << "[:";
|
||||
for (size_t j = 0; j < corners.size(); j++) { file_config << corners[j].x; }
|
||||
file_config << "]";
|
||||
file_config << "y" << "[:";
|
||||
for (size_t j = 0; j < corners.size(); j++) { file_config << corners[j].y; }
|
||||
file_config << "]";
|
||||
file_config << "info" << decoded_info;
|
||||
file_config << "}";
|
||||
}
|
||||
file_config << "]";
|
||||
file_config.release();
|
||||
}
|
||||
TEST(Objdetect_QRCode_Multi, generate_test_data)
|
||||
{
|
||||
const std::string root = "qrcode/multiple/";
|
||||
const std::string dataset_config = findDataFile(root + "dataset_config.json");
|
||||
FileStorage file_config(dataset_config, FileStorage::WRITE);
|
||||
|
||||
file_config << "multiple_images" << "[:";
|
||||
size_t multiple_count = sizeof(qrcode_images_multiple) / sizeof(qrcode_images_multiple[0]);
|
||||
for (size_t i = 0; i < multiple_count; i++)
|
||||
{
|
||||
file_config << "{:" << "image_name" << qrcode_images_multiple[i];
|
||||
std::string image_path = findDataFile(root + qrcode_images_multiple[i]);
|
||||
Mat src = imread(image_path);
|
||||
|
||||
ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path;
|
||||
std::vector<Point> corners;
|
||||
QRCodeDetector qrcode;
|
||||
EXPECT_TRUE(qrcode.detectMulti(src, corners));
|
||||
#ifdef HAVE_QUIRC
|
||||
std::vector<cv::String> decoded_info;
|
||||
std::vector<Mat> straight_barcode;
|
||||
EXPECT_TRUE(qrcode.decodeMulti(src, corners, decoded_info, straight_barcode));
|
||||
#endif
|
||||
file_config << "x" << "[:";
|
||||
for(size_t j = 0; j < corners.size(); j += 4)
|
||||
{
|
||||
file_config << "[:";
|
||||
for (size_t k = 0; k < 4; k++)
|
||||
{
|
||||
file_config << corners[j + k].x;
|
||||
}
|
||||
file_config << "]";
|
||||
}
|
||||
file_config << "]";
|
||||
file_config << "y" << "[:";
|
||||
for(size_t j = 0; j < corners.size(); j += 4)
|
||||
{
|
||||
file_config << "[:";
|
||||
for (size_t k = 0; k < 4; k++)
|
||||
{
|
||||
file_config << corners[j + k].y;
|
||||
}
|
||||
file_config << "]";
|
||||
}
|
||||
file_config << "]";
|
||||
file_config << "info";
|
||||
file_config << "[:";
|
||||
|
||||
for(size_t j = 0; j < decoded_info.size(); j++)
|
||||
{
|
||||
file_config << decoded_info[j];
|
||||
}
|
||||
file_config << "]";
|
||||
file_config << "}";
|
||||
}
|
||||
|
||||
file_config << "]";
|
||||
file_config.release();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
typedef testing::TestWithParam< std::string > Objdetect_QRCode;
|
||||
TEST_P(Objdetect_QRCode, regression)
|
||||
{
|
||||
const std::string name_current_image = GetParam();
|
||||
const std::string root = "qrcode/";
|
||||
const int pixels_error = 3;
|
||||
|
||||
std::string image_path = findDataFile(root + name_current_image);
|
||||
Mat src = imread(image_path, IMREAD_GRAYSCALE), straight_barcode;
|
||||
ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path;
|
||||
|
||||
std::vector<Point> corners;
|
||||
std::string decoded_info;
|
||||
QRCodeDetector qrcode;
|
||||
#ifdef HAVE_QUIRC
|
||||
decoded_info = qrcode.detectAndDecode(src, corners, straight_barcode);
|
||||
ASSERT_FALSE(corners.empty());
|
||||
ASSERT_FALSE(decoded_info.empty());
|
||||
int expected_barcode_type = CV_8UC1;
|
||||
EXPECT_EQ(expected_barcode_type, straight_barcode.type());
|
||||
#else
|
||||
ASSERT_TRUE(qrcode.detect(src, corners));
|
||||
#endif
|
||||
|
||||
const std::string dataset_config = findDataFile(root + "dataset_config.json");
|
||||
FileStorage file_config(dataset_config, FileStorage::READ);
|
||||
ASSERT_TRUE(file_config.isOpened()) << "Can't read validation data: " << dataset_config;
|
||||
{
|
||||
FileNode images_list = file_config["test_images"];
|
||||
size_t images_count = static_cast<size_t>(images_list.size());
|
||||
ASSERT_GT(images_count, 0u) << "Can't find validation data entries in 'test_images': " << dataset_config;
|
||||
|
||||
for (size_t index = 0; index < images_count; index++)
|
||||
{
|
||||
FileNode config = images_list[(int)index];
|
||||
std::string name_test_image = config["image_name"];
|
||||
if (name_test_image == name_current_image)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int x = config["x"][i];
|
||||
int y = config["y"][i];
|
||||
EXPECT_NEAR(x, corners[i].x, pixels_error);
|
||||
EXPECT_NEAR(y, corners[i].y, pixels_error);
|
||||
}
|
||||
|
||||
#ifdef HAVE_QUIRC
|
||||
std::string original_info = config["info"];
|
||||
EXPECT_EQ(decoded_info, original_info);
|
||||
#endif
|
||||
|
||||
return; // done
|
||||
}
|
||||
}
|
||||
std::cerr
|
||||
<< "Not found results for '" << name_current_image
|
||||
<< "' image in config file:" << dataset_config << std::endl
|
||||
<< "Re-run tests with enabled UPDATE_QRCODE_TEST_DATA macro to update test data."
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam< std::string > Objdetect_QRCode_Close;
|
||||
TEST_P(Objdetect_QRCode_Close, regression)
|
||||
{
|
||||
const std::string name_current_image = GetParam();
|
||||
const std::string root = "qrcode/close/";
|
||||
const int pixels_error = 3;
|
||||
|
||||
std::string image_path = findDataFile(root + name_current_image);
|
||||
Mat src = imread(image_path, IMREAD_GRAYSCALE), barcode, straight_barcode;
|
||||
ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path;
|
||||
const double min_side = std::min(src.size().width, src.size().height);
|
||||
double coeff_expansion = 1024.0 / min_side;
|
||||
const int width = cvRound(src.size().width * coeff_expansion);
|
||||
const int height = cvRound(src.size().height * coeff_expansion);
|
||||
Size new_size(width, height);
|
||||
resize(src, barcode, new_size, 0, 0, INTER_LINEAR);
|
||||
std::vector<Point> corners;
|
||||
std::string decoded_info;
|
||||
QRCodeDetector qrcode;
|
||||
#ifdef HAVE_QUIRC
|
||||
decoded_info = qrcode.detectAndDecode(barcode, corners, straight_barcode);
|
||||
ASSERT_FALSE(corners.empty());
|
||||
ASSERT_FALSE(decoded_info.empty());
|
||||
int expected_barcode_type = CV_8UC1;
|
||||
EXPECT_EQ(expected_barcode_type, straight_barcode.type());
|
||||
#else
|
||||
ASSERT_TRUE(qrcode.detect(barcode, corners));
|
||||
#endif
|
||||
|
||||
const std::string dataset_config = findDataFile(root + "dataset_config.json");
|
||||
FileStorage file_config(dataset_config, FileStorage::READ);
|
||||
ASSERT_TRUE(file_config.isOpened()) << "Can't read validation data: " << dataset_config;
|
||||
{
|
||||
FileNode images_list = file_config["close_images"];
|
||||
size_t images_count = static_cast<size_t>(images_list.size());
|
||||
ASSERT_GT(images_count, 0u) << "Can't find validation data entries in 'test_images': " << dataset_config;
|
||||
|
||||
for (size_t index = 0; index < images_count; index++)
|
||||
{
|
||||
FileNode config = images_list[(int)index];
|
||||
std::string name_test_image = config["image_name"];
|
||||
if (name_test_image == name_current_image)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int x = config["x"][i];
|
||||
int y = config["y"][i];
|
||||
EXPECT_NEAR(x, corners[i].x, pixels_error);
|
||||
EXPECT_NEAR(y, corners[i].y, pixels_error);
|
||||
}
|
||||
|
||||
#ifdef HAVE_QUIRC
|
||||
std::string original_info = config["info"];
|
||||
EXPECT_EQ(decoded_info, original_info);
|
||||
#endif
|
||||
|
||||
return; // done
|
||||
}
|
||||
}
|
||||
std::cerr
|
||||
<< "Not found results for '" << name_current_image
|
||||
<< "' image in config file:" << dataset_config << std::endl
|
||||
<< "Re-run tests with enabled UPDATE_QRCODE_TEST_DATA macro to update test data."
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam< std::string > Objdetect_QRCode_Monitor;
|
||||
TEST_P(Objdetect_QRCode_Monitor, regression)
|
||||
{
|
||||
const std::string name_current_image = GetParam();
|
||||
const std::string root = "qrcode/monitor/";
|
||||
const int pixels_error = 3;
|
||||
|
||||
std::string image_path = findDataFile(root + name_current_image);
|
||||
Mat src = imread(image_path, IMREAD_GRAYSCALE), barcode, straight_barcode;
|
||||
ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path;
|
||||
const double min_side = std::min(src.size().width, src.size().height);
|
||||
double coeff_expansion = 1024.0 / min_side;
|
||||
const int width = cvRound(src.size().width * coeff_expansion);
|
||||
const int height = cvRound(src.size().height * coeff_expansion);
|
||||
Size new_size(width, height);
|
||||
resize(src, barcode, new_size, 0, 0, INTER_LINEAR);
|
||||
std::vector<Point> corners;
|
||||
std::string decoded_info;
|
||||
QRCodeDetector qrcode;
|
||||
#ifdef HAVE_QUIRC
|
||||
decoded_info = qrcode.detectAndDecode(barcode, corners, straight_barcode);
|
||||
ASSERT_FALSE(corners.empty());
|
||||
ASSERT_FALSE(decoded_info.empty());
|
||||
int expected_barcode_type = CV_8UC1;
|
||||
EXPECT_EQ(expected_barcode_type, straight_barcode.type());
|
||||
#else
|
||||
ASSERT_TRUE(qrcode.detect(barcode, corners));
|
||||
#endif
|
||||
|
||||
const std::string dataset_config = findDataFile(root + "dataset_config.json");
|
||||
FileStorage file_config(dataset_config, FileStorage::READ);
|
||||
ASSERT_TRUE(file_config.isOpened()) << "Can't read validation data: " << dataset_config;
|
||||
{
|
||||
FileNode images_list = file_config["monitor_images"];
|
||||
size_t images_count = static_cast<size_t>(images_list.size());
|
||||
ASSERT_GT(images_count, 0u) << "Can't find validation data entries in 'test_images': " << dataset_config;
|
||||
|
||||
for (size_t index = 0; index < images_count; index++)
|
||||
{
|
||||
FileNode config = images_list[(int)index];
|
||||
std::string name_test_image = config["image_name"];
|
||||
if (name_test_image == name_current_image)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int x = config["x"][i];
|
||||
int y = config["y"][i];
|
||||
EXPECT_NEAR(x, corners[i].x, pixels_error);
|
||||
EXPECT_NEAR(y, corners[i].y, pixels_error);
|
||||
}
|
||||
|
||||
#ifdef HAVE_QUIRC
|
||||
std::string original_info = config["info"];
|
||||
EXPECT_EQ(decoded_info, original_info);
|
||||
#endif
|
||||
|
||||
return; // done
|
||||
}
|
||||
}
|
||||
std::cerr
|
||||
<< "Not found results for '" << name_current_image
|
||||
<< "' image in config file:" << dataset_config << std::endl
|
||||
<< "Re-run tests with enabled UPDATE_QRCODE_TEST_DATA macro to update test data."
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam< std::string > Objdetect_QRCode_Curved;
|
||||
TEST_P(Objdetect_QRCode_Curved, regression)
|
||||
{
|
||||
const std::string name_current_image = GetParam();
|
||||
const std::string root = "qrcode/curved/";
|
||||
const int pixels_error = 3;
|
||||
|
||||
std::string image_path = findDataFile(root + name_current_image);
|
||||
Mat src = imread(image_path, IMREAD_GRAYSCALE), straight_barcode;
|
||||
ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path;
|
||||
|
||||
std::vector<Point> corners;
|
||||
std::string decoded_info;
|
||||
QRCodeDetector qrcode;
|
||||
#ifdef HAVE_QUIRC
|
||||
decoded_info = qrcode.detectAndDecodeCurved(src, corners, straight_barcode);
|
||||
ASSERT_FALSE(corners.empty());
|
||||
ASSERT_FALSE(decoded_info.empty());
|
||||
int expected_barcode_type = CV_8UC1;
|
||||
EXPECT_EQ(expected_barcode_type, straight_barcode.type());
|
||||
#else
|
||||
ASSERT_TRUE(qrcode.detect(src, corners));
|
||||
#endif
|
||||
|
||||
const std::string dataset_config = findDataFile(root + "dataset_config.json");
|
||||
FileStorage file_config(dataset_config, FileStorage::READ);
|
||||
ASSERT_TRUE(file_config.isOpened()) << "Can't read validation data: " << dataset_config;
|
||||
{
|
||||
FileNode images_list = file_config["test_images"];
|
||||
size_t images_count = static_cast<size_t>(images_list.size());
|
||||
ASSERT_GT(images_count, 0u) << "Can't find validation data entries in 'test_images': " << dataset_config;
|
||||
|
||||
for (size_t index = 0; index < images_count; index++)
|
||||
{
|
||||
FileNode config = images_list[(int)index];
|
||||
std::string name_test_image = config["image_name"];
|
||||
if (name_test_image == name_current_image)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int x = config["x"][i];
|
||||
int y = config["y"][i];
|
||||
EXPECT_NEAR(x, corners[i].x, pixels_error);
|
||||
EXPECT_NEAR(y, corners[i].y, pixels_error);
|
||||
}
|
||||
|
||||
#ifdef HAVE_QUIRC
|
||||
std::string original_info = config["info"];
|
||||
EXPECT_EQ(decoded_info, original_info);
|
||||
#endif
|
||||
|
||||
return; // done
|
||||
}
|
||||
}
|
||||
std::cerr
|
||||
<< "Not found results for '" << name_current_image
|
||||
<< "' image in config file:" << dataset_config << std::endl
|
||||
<< "Re-run tests with enabled UPDATE_QRCODE_TEST_DATA macro to update test data."
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam < std::string > Objdetect_QRCode_Multi;
|
||||
TEST_P(Objdetect_QRCode_Multi, regression)
|
||||
{
|
||||
const std::string name_current_image = GetParam();
|
||||
const std::string root = "qrcode/multiple/";
|
||||
const int pixels_error = 3;
|
||||
|
||||
std::string image_path = findDataFile(root + name_current_image);
|
||||
Mat src = imread(image_path);
|
||||
ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path;
|
||||
QRCodeDetector qrcode;
|
||||
std::vector<Point> corners;
|
||||
#ifdef HAVE_QUIRC
|
||||
std::vector<cv::String> decoded_info;
|
||||
std::vector<Mat> straight_barcode;
|
||||
EXPECT_TRUE(qrcode.detectAndDecodeMulti(src, decoded_info, corners, straight_barcode));
|
||||
ASSERT_FALSE(corners.empty());
|
||||
ASSERT_FALSE(decoded_info.empty());
|
||||
int expected_barcode_type = CV_8UC1;
|
||||
for(size_t i = 0; i < straight_barcode.size(); i++)
|
||||
EXPECT_EQ(expected_barcode_type, straight_barcode[i].type());
|
||||
#else
|
||||
ASSERT_TRUE(qrcode.detectMulti(src, corners));
|
||||
#endif
|
||||
|
||||
const std::string dataset_config = findDataFile(root + "dataset_config.json");
|
||||
FileStorage file_config(dataset_config, FileStorage::READ);
|
||||
ASSERT_TRUE(file_config.isOpened()) << "Can't read validation data: " << dataset_config;
|
||||
{
|
||||
FileNode images_list = file_config["multiple_images"];
|
||||
size_t images_count = static_cast<size_t>(images_list.size());
|
||||
ASSERT_GT(images_count, 0u) << "Can't find validation data entries in 'test_images': " << dataset_config;
|
||||
for (size_t index = 0; index < images_count; index++)
|
||||
{
|
||||
FileNode config = images_list[(int)index];
|
||||
std::string name_test_image = config["image_name"];
|
||||
if (name_test_image == name_current_image)
|
||||
{
|
||||
for(int j = 0; j < int(corners.size()); j += 4)
|
||||
{
|
||||
bool ok = false;
|
||||
for (int k = 0; k < int(corners.size() / 4); k++)
|
||||
{
|
||||
int count_eq_points = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int x = config["x"][k][i];
|
||||
int y = config["y"][k][i];
|
||||
if(((abs(corners[j + i].x - x)) <= pixels_error) && ((abs(corners[j + i].y - y)) <= pixels_error))
|
||||
count_eq_points++;
|
||||
}
|
||||
if (count_eq_points == 4)
|
||||
{
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPECT_TRUE(ok);
|
||||
}
|
||||
|
||||
#ifdef HAVE_QUIRC
|
||||
size_t count_eq_info = 0;
|
||||
for(int i = 0; i < int(decoded_info.size()); i++)
|
||||
{
|
||||
for(int j = 0; j < int(decoded_info.size()); j++)
|
||||
{
|
||||
std::string original_info = config["info"][j];
|
||||
if(original_info == decoded_info[i])
|
||||
{
|
||||
count_eq_info++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(decoded_info.size(), count_eq_info);
|
||||
#endif
|
||||
|
||||
return; // done
|
||||
}
|
||||
}
|
||||
std::cerr
|
||||
<< "Not found results for '" << name_current_image
|
||||
<< "' image in config file:" << dataset_config << std::endl
|
||||
<< "Re-run tests with enabled UPDATE_QRCODE_TEST_DATA macro to update test data."
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Objdetect_QRCode, testing::ValuesIn(qrcode_images_name));
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Objdetect_QRCode_Close, testing::ValuesIn(qrcode_images_close));
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Objdetect_QRCode_Monitor, testing::ValuesIn(qrcode_images_monitor));
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Objdetect_QRCode_Curved, testing::ValuesIn(qrcode_images_curved));
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Objdetect_QRCode_Multi, testing::ValuesIn(qrcode_images_multiple));
|
||||
|
||||
TEST(Objdetect_QRCode_decodeMulti, decode_regression_16491)
|
||||
{
|
||||
#ifdef HAVE_QUIRC
|
||||
Mat zero_image = Mat::zeros(256, 256, CV_8UC1);
|
||||
Point corners_[] = {Point(16, 16), Point(128, 16), Point(128, 128), Point(16, 128),
|
||||
Point(16, 16), Point(128, 16), Point(128, 128), Point(16, 128)};
|
||||
std::vector<Point> vec_corners;
|
||||
int array_size = 8;
|
||||
vec_corners.assign(corners_, corners_ + array_size);
|
||||
std::vector<cv::String> decoded_info;
|
||||
std::vector<Mat> straight_barcode;
|
||||
QRCodeDetector vec_qrcode;
|
||||
EXPECT_NO_THROW(vec_qrcode.decodeMulti(zero_image, vec_corners, decoded_info, straight_barcode));
|
||||
|
||||
Mat mat_corners(2, 4, CV_32SC2, (void*)&vec_corners[0]);
|
||||
QRCodeDetector mat_qrcode;
|
||||
EXPECT_NO_THROW(mat_qrcode.decodeMulti(zero_image, mat_corners, decoded_info, straight_barcode));
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Objdetect_QRCode_detectMulti, detect_regression_16961)
|
||||
{
|
||||
const std::string name_current_image = "9_qrcodes.jpg";
|
||||
const std::string root = "qrcode/multiple/";
|
||||
|
||||
std::string image_path = findDataFile(root + name_current_image);
|
||||
Mat src = imread(image_path);
|
||||
ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path;
|
||||
|
||||
QRCodeDetector qrcode;
|
||||
std::vector<Point> corners;
|
||||
EXPECT_TRUE(qrcode.detectMulti(src, corners));
|
||||
ASSERT_FALSE(corners.empty());
|
||||
size_t expect_corners_size = 36;
|
||||
EXPECT_EQ(corners.size(), expect_corners_size);
|
||||
}
|
||||
|
||||
TEST(Objdetect_QRCode_decodeMulti, check_output_parameters_type_19363)
|
||||
{
|
||||
const std::string name_current_image = "9_qrcodes.jpg";
|
||||
const std::string root = "qrcode/multiple/";
|
||||
|
||||
std::string image_path = findDataFile(root + name_current_image);
|
||||
Mat src = imread(image_path);
|
||||
ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path;
|
||||
#ifdef HAVE_QUIRC
|
||||
QRCodeDetector qrcode;
|
||||
std::vector<Point> corners;
|
||||
std::vector<cv::String> decoded_info;
|
||||
#if 0 // FIXIT: OutputArray::create() type check
|
||||
std::vector<Mat2b> straight_barcode_nchannels;
|
||||
EXPECT_ANY_THROW(qrcode.detectAndDecodeMulti(src, decoded_info, corners, straight_barcode_nchannels));
|
||||
#endif
|
||||
|
||||
int expected_barcode_type = CV_8UC1;
|
||||
std::vector<Mat1b> straight_barcode;
|
||||
EXPECT_TRUE(qrcode.detectAndDecodeMulti(src, decoded_info, corners, straight_barcode));
|
||||
ASSERT_FALSE(corners.empty());
|
||||
for(size_t i = 0; i < straight_barcode.size(); i++)
|
||||
EXPECT_EQ(expected_barcode_type, straight_barcode[i].type());
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Objdetect_QRCode_basic, not_found_qrcode)
|
||||
{
|
||||
std::vector<Point> corners;
|
||||
Mat straight_barcode;
|
||||
std::string decoded_info;
|
||||
Mat zero_image = Mat::zeros(256, 256, CV_8UC1);
|
||||
QRCodeDetector qrcode;
|
||||
EXPECT_FALSE(qrcode.detect(zero_image, corners));
|
||||
#ifdef HAVE_QUIRC
|
||||
corners = std::vector<Point>(4);
|
||||
EXPECT_ANY_THROW(qrcode.decode(zero_image, corners, straight_barcode));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif // UPDATE_QRCODE_TEST_DATA
|
||||
|
||||
}} // namespace
|
Reference in New Issue
Block a user