diff --git a/modules/objdetect/include/opencv2/objdetect/objdetect_c.h b/modules/objdetect/include/opencv2/objdetect/objdetect_c.h deleted file mode 100644 index 67dc2f4e66..0000000000 --- a/modules/objdetect/include/opencv2/objdetect/objdetect_c.h +++ /dev/null @@ -1,166 +0,0 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 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_C_H -#define OPENCV_OBJDETECT_C_H - -#include "opencv2/core/core_c.h" - -#ifdef __cplusplus -#include -#include - -extern "C" { -#endif - -/** @addtogroup objdetect_c - @{ - */ - -/****************************************************************************************\ -* Haar-like Object Detection functions * -\****************************************************************************************/ - -#define CV_HAAR_MAGIC_VAL 0x42500000 -#define CV_TYPE_NAME_HAAR "opencv-haar-classifier" - -#define CV_IS_HAAR_CLASSIFIER( haar ) \ - ((haar) != NULL && \ - (((const CvHaarClassifierCascade*)(haar))->flags & CV_MAGIC_MASK)==CV_HAAR_MAGIC_VAL) - -#define CV_HAAR_FEATURE_MAX 3 -#define CV_HAAR_STAGE_MAX 1000 - -typedef struct CvHaarFeature -{ - int tilted; - struct - { - CvRect r; - float weight; - } rect[CV_HAAR_FEATURE_MAX]; -} CvHaarFeature; - -typedef struct CvHaarClassifier -{ - int count; - CvHaarFeature* haar_feature; - float* threshold; - int* left; - int* right; - float* alpha; -} CvHaarClassifier; - -typedef struct CvHaarStageClassifier -{ - int count; - float threshold; - CvHaarClassifier* classifier; - - int next; - int child; - int parent; -} CvHaarStageClassifier; - -typedef struct CvHidHaarClassifierCascade CvHidHaarClassifierCascade; - -typedef struct CvHaarClassifierCascade -{ - int flags; - int count; - CvSize orig_window_size; - CvSize real_window_size; - double scale; - CvHaarStageClassifier* stage_classifier; - CvHidHaarClassifierCascade* hid_cascade; -} CvHaarClassifierCascade; - -typedef struct CvAvgComp -{ - CvRect rect; - int neighbors; -} CvAvgComp; - -/* Loads haar classifier cascade from a directory. - It is obsolete: convert your cascade to xml and use cvLoad instead */ -CVAPI(CvHaarClassifierCascade*) cvLoadHaarClassifierCascade( - const char* directory, CvSize orig_window_size); - -CVAPI(void) cvReleaseHaarClassifierCascade( CvHaarClassifierCascade** cascade ); - -#define CV_HAAR_DO_CANNY_PRUNING 1 -#define CV_HAAR_SCALE_IMAGE 2 -#define CV_HAAR_FIND_BIGGEST_OBJECT 4 -#define CV_HAAR_DO_ROUGH_SEARCH 8 - -CVAPI(CvSeq*) cvHaarDetectObjects( const CvArr* image, - CvHaarClassifierCascade* cascade, CvMemStorage* storage, - double scale_factor CV_DEFAULT(1.1), - int min_neighbors CV_DEFAULT(3), int flags CV_DEFAULT(0), - CvSize min_size CV_DEFAULT(cvSize(0,0)), CvSize max_size CV_DEFAULT(cvSize(0,0))); - -/* sets images for haar classifier cascade */ -CVAPI(void) cvSetImagesForHaarClassifierCascade( CvHaarClassifierCascade* cascade, - const CvArr* sum, const CvArr* sqsum, - const CvArr* tilted_sum, double scale ); - -/* runs the cascade on the specified window */ -CVAPI(int) cvRunHaarClassifierCascade( const CvHaarClassifierCascade* cascade, - CvPoint pt, int start_stage CV_DEFAULT(0)); - -/** @} objdetect_c */ - -#ifdef __cplusplus -} - -CV_EXPORTS CvSeq* cvHaarDetectObjectsForROC( const CvArr* image, - CvHaarClassifierCascade* cascade, CvMemStorage* storage, - std::vector& rejectLevels, std::vector& levelWeightds, - double scale_factor = 1.1, - int min_neighbors = 3, int flags = 0, - CvSize min_size = cvSize(0, 0), CvSize max_size = cvSize(0, 0), - bool outputRejectLevels = false ); - -#endif - -#endif /* OPENCV_OBJDETECT_C_H */ diff --git a/modules/objdetect/src/cascadedetect.cpp b/modules/objdetect/src/cascadedetect.cpp index c46c3e3875..a1865e9062 100644 --- a/modules/objdetect/src/cascadedetect.cpp +++ b/modules/objdetect/src/cascadedetect.cpp @@ -44,7 +44,6 @@ #include #include "cascadedetect.hpp" -#include "opencv2/objdetect/objdetect_c.h" #include "opencl_kernels_objdetect.hpp" namespace cv @@ -1071,9 +1070,6 @@ public: }; -struct getRect { Rect operator ()(const CvAvgComp& e) const { return e.rect; } }; -struct getNeighbors { int operator ()(const CvAvgComp& e) const { return e.neighbors; } }; - #ifdef HAVE_OPENCL bool CascadeClassifierImpl::ocl_detectMultiScaleNoGrouping( const std::vector& scales, std::vector& candidates ) @@ -1227,24 +1223,6 @@ void* CascadeClassifierImpl::getOldCascade() return oldCascade; } -static void detectMultiScaleOldFormat( const Mat& image, Ptr oldCascade, - std::vector& objects, - std::vector& rejectLevels, - std::vector& levelWeights, - std::vector& vecAvgComp, - double scaleFactor, int minNeighbors, - int flags, Size minObjectSize, Size maxObjectSize, - bool outputRejectLevels = false ) -{ - MemStorage storage(cvCreateMemStorage(0)); - CvMat _image = cvMat(image); - CvSeq* _objects = cvHaarDetectObjectsForROC( &_image, oldCascade, storage, rejectLevels, levelWeights, scaleFactor, - minNeighbors, flags, cvSize(minObjectSize), cvSize(maxObjectSize), outputRejectLevels ); - Seq(_objects).copyTo(vecAvgComp); - objects.resize(vecAvgComp.size()); - std::transform(vecAvgComp.begin(), vecAvgComp.end(), objects.begin(), getRect()); -} - void CascadeClassifierImpl::detectMultiScaleNoGrouping( InputArray _image, std::vector& candidates, std::vector& rejectLevels, std::vector& levelWeights, double scaleFactor, Size minObjectSize, Size maxObjectSize, @@ -1374,7 +1352,7 @@ void CascadeClassifierImpl::detectMultiScale( InputArray _image, std::vector& rejectLevels, std::vector& levelWeights, double scaleFactor, int minNeighbors, - int flags, Size minObjectSize, Size maxObjectSize, + int /*flags*/, Size minObjectSize, Size maxObjectSize, bool outputRejectLevels ) { CV_INSTRUMENT_REGION(); @@ -1384,26 +1362,16 @@ void CascadeClassifierImpl::detectMultiScale( InputArray _image, std::vector fakeVecAvgComp; - detectMultiScaleOldFormat( image, oldCascade, objects, rejectLevels, levelWeights, fakeVecAvgComp, scaleFactor, - minNeighbors, flags, minObjectSize, maxObjectSize, outputRejectLevels ); + groupRectangles( objects, rejectLevels, levelWeights, minNeighbors, GROUP_EPS ); } else { - detectMultiScaleNoGrouping( _image, objects, rejectLevels, levelWeights, scaleFactor, minObjectSize, maxObjectSize, - outputRejectLevels ); - const double GROUP_EPS = 0.2; - if( outputRejectLevels ) - { - groupRectangles( objects, rejectLevels, levelWeights, minNeighbors, GROUP_EPS ); - } - else - { - groupRectangles( objects, minNeighbors, GROUP_EPS ); - } + groupRectangles( objects, minNeighbors, GROUP_EPS ); } } @@ -1421,7 +1389,7 @@ void CascadeClassifierImpl::detectMultiScale( InputArray _image, std::vector& objects, std::vector& numDetections, double scaleFactor, - int minNeighbors, int flags, Size minObjectSize, + int minNeighbors, int /*flags*/, Size minObjectSize, Size maxObjectSize ) { CV_INSTRUMENT_REGION(); @@ -1434,20 +1402,10 @@ void CascadeClassifierImpl::detectMultiScale( InputArray _image, std::vector fakeLevels; std::vector fakeWeights; - if( isOldFormatCascade() ) - { - std::vector vecAvgComp; - detectMultiScaleOldFormat( image, oldCascade, objects, fakeLevels, fakeWeights, vecAvgComp, scaleFactor, - minNeighbors, flags, minObjectSize, maxObjectSize ); - numDetections.resize(vecAvgComp.size()); - std::transform(vecAvgComp.begin(), vecAvgComp.end(), numDetections.begin(), getNeighbors()); - } - else - { - detectMultiScaleNoGrouping( image, objects, fakeLevels, fakeWeights, scaleFactor, minObjectSize, maxObjectSize ); - const double GROUP_EPS = 0.2; - groupRectangles( objects, numDetections, minNeighbors, GROUP_EPS ); - } + + detectMultiScaleNoGrouping( image, objects, fakeLevels, fakeWeights, scaleFactor, minObjectSize, maxObjectSize ); + const double GROUP_EPS = 0.2; + groupRectangles( objects, numDetections, minNeighbors, GROUP_EPS ); } @@ -1613,9 +1571,6 @@ bool CascadeClassifierImpl::read_(const FileNode& root) return featureEvaluator->read(fn, data.origWinSize); } -void DefaultDeleter::operator ()(CvHaarClassifierCascade* obj) const { cvReleaseHaarClassifierCascade(&obj); } - - BaseCascadeClassifier::~BaseCascadeClassifier() { } diff --git a/modules/objdetect/src/haar.avx.cpp b/modules/objdetect/src/haar.avx.cpp deleted file mode 100644 index 23dddfa199..0000000000 --- a/modules/objdetect/src/haar.avx.cpp +++ /dev/null @@ -1,369 +0,0 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// Intel License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000, Intel Corporation, 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 "haar.hpp" - -namespace cv_haar_avx -{ - -// AVX version icvEvalHidHaarClassifier. Process 8 CvHidHaarClassifiers per call. Check AVX support before invocation!! -#if CV_HAAR_USE_AVX -double icvEvalHidHaarClassifierAVX(CvHidHaarClassifier* classifier, - double variance_norm_factor, size_t p_offset) -{ - int CV_DECL_ALIGNED(32) idxV[8] = { 0,0,0,0,0,0,0,0 }; - uchar flags[8] = { 0,0,0,0,0,0,0,0 }; - CvHidHaarTreeNode* nodes[8]; - double res = 0; - uchar exitConditionFlag = 0; - for (;;) - { - float CV_DECL_ALIGNED(32) tmp[8] = { 0,0,0,0,0,0,0,0 }; - nodes[0] = (classifier + 0)->node + idxV[0]; - nodes[1] = (classifier + 1)->node + idxV[1]; - nodes[2] = (classifier + 2)->node + idxV[2]; - nodes[3] = (classifier + 3)->node + idxV[3]; - nodes[4] = (classifier + 4)->node + idxV[4]; - nodes[5] = (classifier + 5)->node + idxV[5]; - nodes[6] = (classifier + 6)->node + idxV[6]; - nodes[7] = (classifier + 7)->node + idxV[7]; - - __m256 t = _mm256_set1_ps(static_cast(variance_norm_factor)); - - t = _mm256_mul_ps(t, _mm256_set_ps(nodes[7]->threshold, - nodes[6]->threshold, - nodes[5]->threshold, - nodes[4]->threshold, - nodes[3]->threshold, - nodes[2]->threshold, - nodes[1]->threshold, - nodes[0]->threshold)); - - __m256 offset = _mm256_set_ps(calc_sumf(nodes[7]->feature.rect[0], p_offset), - calc_sumf(nodes[6]->feature.rect[0], p_offset), - calc_sumf(nodes[5]->feature.rect[0], p_offset), - calc_sumf(nodes[4]->feature.rect[0], p_offset), - calc_sumf(nodes[3]->feature.rect[0], p_offset), - calc_sumf(nodes[2]->feature.rect[0], p_offset), - calc_sumf(nodes[1]->feature.rect[0], p_offset), - calc_sumf(nodes[0]->feature.rect[0], p_offset)); - - __m256 weight = _mm256_set_ps(nodes[7]->feature.rect[0].weight, - nodes[6]->feature.rect[0].weight, - nodes[5]->feature.rect[0].weight, - nodes[4]->feature.rect[0].weight, - nodes[3]->feature.rect[0].weight, - nodes[2]->feature.rect[0].weight, - nodes[1]->feature.rect[0].weight, - nodes[0]->feature.rect[0].weight); - - __m256 sum = _mm256_mul_ps(offset, weight); - - offset = _mm256_set_ps(calc_sumf(nodes[7]->feature.rect[1], p_offset), - calc_sumf(nodes[6]->feature.rect[1], p_offset), - calc_sumf(nodes[5]->feature.rect[1], p_offset), - calc_sumf(nodes[4]->feature.rect[1], p_offset), - calc_sumf(nodes[3]->feature.rect[1], p_offset), - calc_sumf(nodes[2]->feature.rect[1], p_offset), - calc_sumf(nodes[1]->feature.rect[1], p_offset), - calc_sumf(nodes[0]->feature.rect[1], p_offset)); - - weight = _mm256_set_ps(nodes[7]->feature.rect[1].weight, - nodes[6]->feature.rect[1].weight, - nodes[5]->feature.rect[1].weight, - nodes[4]->feature.rect[1].weight, - nodes[3]->feature.rect[1].weight, - nodes[2]->feature.rect[1].weight, - nodes[1]->feature.rect[1].weight, - nodes[0]->feature.rect[1].weight); - - sum = _mm256_add_ps(sum, _mm256_mul_ps(offset, weight)); - - if (nodes[0]->feature.rect[2].p0) - tmp[0] = calc_sumf(nodes[0]->feature.rect[2], p_offset) * nodes[0]->feature.rect[2].weight; - if (nodes[1]->feature.rect[2].p0) - tmp[1] = calc_sumf(nodes[1]->feature.rect[2], p_offset) * nodes[1]->feature.rect[2].weight; - if (nodes[2]->feature.rect[2].p0) - tmp[2] = calc_sumf(nodes[2]->feature.rect[2], p_offset) * nodes[2]->feature.rect[2].weight; - if (nodes[3]->feature.rect[2].p0) - tmp[3] = calc_sumf(nodes[3]->feature.rect[2], p_offset) * nodes[3]->feature.rect[2].weight; - if (nodes[4]->feature.rect[2].p0) - tmp[4] = calc_sumf(nodes[4]->feature.rect[2], p_offset) * nodes[4]->feature.rect[2].weight; - if (nodes[5]->feature.rect[2].p0) - tmp[5] = calc_sumf(nodes[5]->feature.rect[2], p_offset) * nodes[5]->feature.rect[2].weight; - if (nodes[6]->feature.rect[2].p0) - tmp[6] = calc_sumf(nodes[6]->feature.rect[2], p_offset) * nodes[6]->feature.rect[2].weight; - if (nodes[7]->feature.rect[2].p0) - tmp[7] = calc_sumf(nodes[7]->feature.rect[2], p_offset) * nodes[7]->feature.rect[2].weight; - - sum = _mm256_add_ps(sum, _mm256_load_ps(tmp)); - - __m256 left = _mm256_set_ps(static_cast(nodes[7]->left), static_cast(nodes[6]->left), - static_cast(nodes[5]->left), static_cast(nodes[4]->left), - static_cast(nodes[3]->left), static_cast(nodes[2]->left), - static_cast(nodes[1]->left), static_cast(nodes[0]->left)); - __m256 right = _mm256_set_ps(static_cast(nodes[7]->right), static_cast(nodes[6]->right), - static_cast(nodes[5]->right), static_cast(nodes[4]->right), - static_cast(nodes[3]->right), static_cast(nodes[2]->right), - static_cast(nodes[1]->right), static_cast(nodes[0]->right)); - - _mm256_store_si256((__m256i*)idxV, _mm256_cvttps_epi32(_mm256_blendv_ps(right, left, _mm256_cmp_ps(sum, t, _CMP_LT_OQ)))); - - for (int i = 0; i < 8; i++) - { - if (idxV[i] <= 0) - { - if (!flags[i]) - { - exitConditionFlag++; - flags[i] = 1; - res += (classifier + i)->alpha[-idxV[i]]; - } - idxV[i] = 0; - } - } - if (exitConditionFlag == 8) - return res; - } -} - -double icvEvalHidHaarStumpClassifierAVX(CvHidHaarClassifier* classifier, - double variance_norm_factor, size_t p_offset) -{ - float CV_DECL_ALIGNED(32) tmp[8] = { 0,0,0,0,0,0,0,0 }; - CvHidHaarTreeNode* nodes[8]; - - nodes[0] = classifier[0].node; - nodes[1] = classifier[1].node; - nodes[2] = classifier[2].node; - nodes[3] = classifier[3].node; - nodes[4] = classifier[4].node; - nodes[5] = classifier[5].node; - nodes[6] = classifier[6].node; - nodes[7] = classifier[7].node; - - __m256 t = _mm256_set1_ps(static_cast(variance_norm_factor)); - - t = _mm256_mul_ps(t, _mm256_set_ps(nodes[7]->threshold, - nodes[6]->threshold, - nodes[5]->threshold, - nodes[4]->threshold, - nodes[3]->threshold, - nodes[2]->threshold, - nodes[1]->threshold, - nodes[0]->threshold)); - - __m256 offset = _mm256_set_ps(calc_sumf(nodes[7]->feature.rect[0], p_offset), - calc_sumf(nodes[6]->feature.rect[0], p_offset), - calc_sumf(nodes[5]->feature.rect[0], p_offset), - calc_sumf(nodes[4]->feature.rect[0], p_offset), - calc_sumf(nodes[3]->feature.rect[0], p_offset), - calc_sumf(nodes[2]->feature.rect[0], p_offset), - calc_sumf(nodes[1]->feature.rect[0], p_offset), - calc_sumf(nodes[0]->feature.rect[0], p_offset)); - - __m256 weight = _mm256_set_ps(nodes[7]->feature.rect[0].weight, - nodes[6]->feature.rect[0].weight, - nodes[5]->feature.rect[0].weight, - nodes[4]->feature.rect[0].weight, - nodes[3]->feature.rect[0].weight, - nodes[2]->feature.rect[0].weight, - nodes[1]->feature.rect[0].weight, - nodes[0]->feature.rect[0].weight); - - __m256 sum = _mm256_mul_ps(offset, weight); - - offset = _mm256_set_ps(calc_sumf(nodes[7]->feature.rect[1], p_offset), - calc_sumf(nodes[6]->feature.rect[1], p_offset), - calc_sumf(nodes[5]->feature.rect[1], p_offset), - calc_sumf(nodes[4]->feature.rect[1], p_offset), - calc_sumf(nodes[3]->feature.rect[1], p_offset), - calc_sumf(nodes[2]->feature.rect[1], p_offset), - calc_sumf(nodes[1]->feature.rect[1], p_offset), - calc_sumf(nodes[0]->feature.rect[1], p_offset)); - - weight = _mm256_set_ps(nodes[7]->feature.rect[1].weight, - nodes[6]->feature.rect[1].weight, - nodes[5]->feature.rect[1].weight, - nodes[4]->feature.rect[1].weight, - nodes[3]->feature.rect[1].weight, - nodes[2]->feature.rect[1].weight, - nodes[1]->feature.rect[1].weight, - nodes[0]->feature.rect[1].weight); - - sum = _mm256_add_ps(sum, _mm256_mul_ps(offset, weight)); - - if (nodes[0]->feature.rect[2].p0) - tmp[0] = calc_sumf(nodes[0]->feature.rect[2], p_offset) * nodes[0]->feature.rect[2].weight; - if (nodes[1]->feature.rect[2].p0) - tmp[1] = calc_sumf(nodes[1]->feature.rect[2], p_offset) * nodes[1]->feature.rect[2].weight; - if (nodes[2]->feature.rect[2].p0) - tmp[2] = calc_sumf(nodes[2]->feature.rect[2], p_offset) * nodes[2]->feature.rect[2].weight; - if (nodes[3]->feature.rect[2].p0) - tmp[3] = calc_sumf(nodes[3]->feature.rect[2], p_offset) * nodes[3]->feature.rect[2].weight; - if (nodes[4]->feature.rect[2].p0) - tmp[4] = calc_sumf(nodes[4]->feature.rect[2], p_offset) * nodes[4]->feature.rect[2].weight; - if (nodes[5]->feature.rect[2].p0) - tmp[5] = calc_sumf(nodes[5]->feature.rect[2], p_offset) * nodes[5]->feature.rect[2].weight; - if (nodes[6]->feature.rect[2].p0) - tmp[6] = calc_sumf(nodes[6]->feature.rect[2], p_offset) * nodes[6]->feature.rect[2].weight; - if (nodes[7]->feature.rect[2].p0) - tmp[7] = calc_sumf(nodes[7]->feature.rect[2], p_offset) * nodes[7]->feature.rect[2].weight; - - sum = _mm256_add_ps(sum, _mm256_load_ps(tmp)); - - __m256 alpha0 = _mm256_set_ps(classifier[7].alpha[0], - classifier[6].alpha[0], - classifier[5].alpha[0], - classifier[4].alpha[0], - classifier[3].alpha[0], - classifier[2].alpha[0], - classifier[1].alpha[0], - classifier[0].alpha[0]); - __m256 alpha1 = _mm256_set_ps(classifier[7].alpha[1], - classifier[6].alpha[1], - classifier[5].alpha[1], - classifier[4].alpha[1], - classifier[3].alpha[1], - classifier[2].alpha[1], - classifier[1].alpha[1], - classifier[0].alpha[1]); - - __m256 outBuf = _mm256_blendv_ps(alpha0, alpha1, _mm256_cmp_ps(t, sum, _CMP_LE_OQ)); - outBuf = _mm256_hadd_ps(outBuf, outBuf); - outBuf = _mm256_hadd_ps(outBuf, outBuf); - _mm256_store_ps(tmp, outBuf); - return (tmp[0] + tmp[4]); -} - -double icvEvalHidHaarStumpClassifierTwoRectAVX(CvHidHaarClassifier* classifier, - double variance_norm_factor, size_t p_offset) -{ - float CV_DECL_ALIGNED(32) buf[8]; - CvHidHaarTreeNode* nodes[8]; - nodes[0] = classifier[0].node; - nodes[1] = classifier[1].node; - nodes[2] = classifier[2].node; - nodes[3] = classifier[3].node; - nodes[4] = classifier[4].node; - nodes[5] = classifier[5].node; - nodes[6] = classifier[6].node; - nodes[7] = classifier[7].node; - - __m256 t = _mm256_set1_ps(static_cast(variance_norm_factor)); - t = _mm256_mul_ps(t, _mm256_set_ps(nodes[7]->threshold, - nodes[6]->threshold, - nodes[5]->threshold, - nodes[4]->threshold, - nodes[3]->threshold, - nodes[2]->threshold, - nodes[1]->threshold, - nodes[0]->threshold)); - - __m256 offset = _mm256_set_ps(calc_sumf(nodes[7]->feature.rect[0], p_offset), - calc_sumf(nodes[6]->feature.rect[0], p_offset), - calc_sumf(nodes[5]->feature.rect[0], p_offset), - calc_sumf(nodes[4]->feature.rect[0], p_offset), - calc_sumf(nodes[3]->feature.rect[0], p_offset), - calc_sumf(nodes[2]->feature.rect[0], p_offset), - calc_sumf(nodes[1]->feature.rect[0], p_offset), - calc_sumf(nodes[0]->feature.rect[0], p_offset)); - - __m256 weight = _mm256_set_ps(nodes[7]->feature.rect[0].weight, - nodes[6]->feature.rect[0].weight, - nodes[5]->feature.rect[0].weight, - nodes[4]->feature.rect[0].weight, - nodes[3]->feature.rect[0].weight, - nodes[2]->feature.rect[0].weight, - nodes[1]->feature.rect[0].weight, - nodes[0]->feature.rect[0].weight); - - __m256 sum = _mm256_mul_ps(offset, weight); - - offset = _mm256_set_ps(calc_sumf(nodes[7]->feature.rect[1], p_offset), - calc_sumf(nodes[6]->feature.rect[1], p_offset), - calc_sumf(nodes[5]->feature.rect[1], p_offset), - calc_sumf(nodes[4]->feature.rect[1], p_offset), - calc_sumf(nodes[3]->feature.rect[1], p_offset), - calc_sumf(nodes[2]->feature.rect[1], p_offset), - calc_sumf(nodes[1]->feature.rect[1], p_offset), - calc_sumf(nodes[0]->feature.rect[1], p_offset)); - - weight = _mm256_set_ps(nodes[7]->feature.rect[1].weight, - nodes[6]->feature.rect[1].weight, - nodes[5]->feature.rect[1].weight, - nodes[4]->feature.rect[1].weight, - nodes[3]->feature.rect[1].weight, - nodes[2]->feature.rect[1].weight, - nodes[1]->feature.rect[1].weight, - nodes[0]->feature.rect[1].weight); - - sum = _mm256_add_ps(sum, _mm256_mul_ps(offset, weight)); - - __m256 alpha0 = _mm256_set_ps(classifier[7].alpha[0], - classifier[6].alpha[0], - classifier[5].alpha[0], - classifier[4].alpha[0], - classifier[3].alpha[0], - classifier[2].alpha[0], - classifier[1].alpha[0], - classifier[0].alpha[0]); - __m256 alpha1 = _mm256_set_ps(classifier[7].alpha[1], - classifier[6].alpha[1], - classifier[5].alpha[1], - classifier[4].alpha[1], - classifier[3].alpha[1], - classifier[2].alpha[1], - classifier[1].alpha[1], - classifier[0].alpha[1]); - - _mm256_store_ps(buf, _mm256_blendv_ps(alpha0, alpha1, _mm256_cmp_ps(t, sum, _CMP_LE_OQ))); - return (buf[0] + buf[1] + buf[2] + buf[3] + buf[4] + buf[5] + buf[6] + buf[7]); -} - -#endif //CV_HAAR_USE_AVX - -} - -/* End of file. */ diff --git a/modules/objdetect/src/haar.cpp b/modules/objdetect/src/haar.cpp deleted file mode 100644 index d0f09f8bf7..0000000000 --- a/modules/objdetect/src/haar.cpp +++ /dev/null @@ -1,2133 +0,0 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// Intel License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000, Intel Corporation, 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 "opencv2/imgproc/imgproc_c.h" -#include "opencv2/objdetect/objdetect_c.h" -#include -#include "haar.hpp" -#if CV_HAAR_FEATURE_MAX_LOCAL != CV_HAAR_FEATURE_MAX - #error CV_HAAR_FEATURE_MAX definition changed. Adjust CV_HAAR_FEATURE_MAX_LOCAL value please. -#endif - -#if CV_SSE2 -# if 1 /*!CV_SSE4_1 && !CV_SSE4_2*/ -# define _mm_blendv_pd(a, b, m) _mm_xor_pd(a, _mm_and_pd(_mm_xor_pd(b, a), m)) -# define _mm_blendv_ps(a, b, m) _mm_xor_ps(a, _mm_and_ps(_mm_xor_ps(b, a), m)) -# endif -#endif - -#if CV_HAAR_USE_AVX -# if defined _MSC_VER -# pragma warning( disable : 4752 ) -# endif -#else -# if CV_SSE2 -# define CV_HAAR_USE_SSE 1 -# endif -#endif - -/* these settings affect the quality of detection: change with care */ -#define CV_ADJUST_FEATURES 1 -#define CV_ADJUST_WEIGHTS 0 - -typedef struct CvHidHaarStageClassifier -{ - int count; - float threshold; - CvHidHaarClassifier* classifier; - int two_rects; - - struct CvHidHaarStageClassifier* next; - struct CvHidHaarStageClassifier* child; - struct CvHidHaarStageClassifier* parent; -} CvHidHaarStageClassifier; - - -typedef struct CvHidHaarClassifierCascade -{ - int count; - int has_tilted_features; - double inv_window_area; - CvMat sum, sqsum, tilted; - CvHidHaarStageClassifier* stage_classifier; - sqsumtype *pq0, *pq1, *pq2, *pq3; - sumtype *p0, *p1, *p2, *p3; - - bool is_tree; - bool isStumpBased; -} CvHidHaarClassifierCascade; - - -const int icv_object_win_border = 1; -const float icv_stage_threshold_bias = 0.0001f; - -static void -icvReleaseHidHaarClassifierCascade( CvHidHaarClassifierCascade** _cascade ) -{ - if( _cascade && *_cascade ) - { - cvFree( _cascade ); - } -} - -/* create more efficient internal representation of haar classifier cascade */ -static CvHidHaarClassifierCascade* -icvCreateHidHaarClassifierCascade( CvHaarClassifierCascade* cascade ) -{ - CvHidHaarClassifierCascade* out = 0; - - int i, j, k, l; - int datasize; - int total_classifiers = 0; - int total_nodes = 0; - char errorstr[1000]; - CvHidHaarClassifier* haar_classifier_ptr; - CvHidHaarTreeNode* haar_node_ptr; - cv::Size orig_window_size; - bool has_tilted_features = false; - int max_count = 0; - - if( !CV_IS_HAAR_CLASSIFIER(cascade) ) - CV_Error( !cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid classifier pointer" ); - - if( cascade->hid_cascade ) - CV_Error( CV_StsError, "hid_cascade has been already created" ); - - if( !cascade->stage_classifier ) - CV_Error( CV_StsNullPtr, "" ); - - if( cascade->count <= 0 ) - CV_Error( CV_StsOutOfRange, "Negative number of cascade stages" ); - - orig_window_size = cascade->orig_window_size; - - /* check input structure correctness and calculate total memory size needed for - internal representation of the classifier cascade */ - for( i = 0; i < cascade->count; i++ ) - { - CvHaarStageClassifier* stage_classifier = cascade->stage_classifier + i; - - if( !stage_classifier->classifier || - stage_classifier->count <= 0 ) - { - sprintf( errorstr, "header of the stage classifier #%d is invalid " - "(has null pointers or non-positive classfier count)", i ); - CV_Error( CV_StsError, errorstr ); - } - - max_count = MAX( max_count, stage_classifier->count ); - total_classifiers += stage_classifier->count; - - for( j = 0; j < stage_classifier->count; j++ ) - { - CvHaarClassifier* classifier = stage_classifier->classifier + j; - - total_nodes += classifier->count; - for( l = 0; l < classifier->count; l++ ) - { - for( k = 0; k < CV_HAAR_FEATURE_MAX; k++ ) - { - if( classifier->haar_feature[l].rect[k].r.width ) - { - CvRect r = classifier->haar_feature[l].rect[k].r; - int tilted = classifier->haar_feature[l].tilted; - has_tilted_features = has_tilted_features | (tilted != 0); - if( r.width < 0 || r.height < 0 || r.y < 0 || - r.x + r.width > orig_window_size.width - || - (!tilted && - (r.x < 0 || r.y + r.height > orig_window_size.height)) - || - (tilted && (r.x - r.height < 0 || - r.y + r.width + r.height > orig_window_size.height))) - { - sprintf( errorstr, "rectangle #%d of the classifier #%d of " - "the stage classifier #%d is not inside " - "the reference (original) cascade window", k, j, i ); - CV_Error( CV_StsNullPtr, errorstr ); - } - } - } - } - } - } - - // this is an upper boundary for the whole hidden cascade size - datasize = sizeof(CvHidHaarClassifierCascade) + - sizeof(CvHidHaarStageClassifier)*cascade->count + - sizeof(CvHidHaarClassifier) * total_classifiers + - sizeof(CvHidHaarTreeNode) * total_nodes + - sizeof(void*)*(total_nodes + total_classifiers); - - out = (CvHidHaarClassifierCascade*)cvAlloc( datasize ); - memset( out, 0, sizeof(*out) ); - - /* init header */ - out->count = cascade->count; - out->stage_classifier = (CvHidHaarStageClassifier*)(out + 1); - haar_classifier_ptr = (CvHidHaarClassifier*)(out->stage_classifier + cascade->count); - haar_node_ptr = (CvHidHaarTreeNode*)(haar_classifier_ptr + total_classifiers); - - out->isStumpBased = true; - out->has_tilted_features = has_tilted_features; - out->is_tree = false; - - /* initialize internal representation */ - for( i = 0; i < cascade->count; i++ ) - { - CvHaarStageClassifier* stage_classifier = cascade->stage_classifier + i; - CvHidHaarStageClassifier* hid_stage_classifier = out->stage_classifier + i; - - hid_stage_classifier->count = stage_classifier->count; - hid_stage_classifier->threshold = stage_classifier->threshold - icv_stage_threshold_bias; - hid_stage_classifier->classifier = haar_classifier_ptr; - hid_stage_classifier->two_rects = 1; - haar_classifier_ptr += stage_classifier->count; - - hid_stage_classifier->parent = (stage_classifier->parent == -1) - ? NULL : out->stage_classifier + stage_classifier->parent; - hid_stage_classifier->next = (stage_classifier->next == -1) - ? NULL : out->stage_classifier + stage_classifier->next; - hid_stage_classifier->child = (stage_classifier->child == -1) - ? NULL : out->stage_classifier + stage_classifier->child; - - out->is_tree = out->is_tree || (hid_stage_classifier->next != NULL); - - for( j = 0; j < stage_classifier->count; j++ ) - { - CvHaarClassifier* classifier = stage_classifier->classifier + j; - CvHidHaarClassifier* hid_classifier = hid_stage_classifier->classifier + j; - int node_count = classifier->count; - float* alpha_ptr = (float*)(haar_node_ptr + node_count); - - hid_classifier->count = node_count; - hid_classifier->node = haar_node_ptr; - hid_classifier->alpha = alpha_ptr; - - for( l = 0; l < node_count; l++ ) - { - CvHidHaarTreeNode* node = hid_classifier->node + l; - CvHaarFeature* feature = classifier->haar_feature + l; - memset( node, -1, sizeof(*node) ); - node->threshold = classifier->threshold[l]; - node->left = classifier->left[l]; - node->right = classifier->right[l]; - - if( fabs(feature->rect[2].weight) < DBL_EPSILON || - feature->rect[2].r.width == 0 || - feature->rect[2].r.height == 0 ) - memset( &(node->feature.rect[2]), 0, sizeof(node->feature.rect[2]) ); - else - hid_stage_classifier->two_rects = 0; - } - - memcpy( alpha_ptr, classifier->alpha, (node_count+1)*sizeof(alpha_ptr[0])); - haar_node_ptr = - (CvHidHaarTreeNode*)cvAlignPtr(alpha_ptr+node_count+1, sizeof(void*)); - - out->isStumpBased = out->isStumpBased && (node_count == 1); - } - } - - cascade->hid_cascade = out; - assert( (char*)haar_node_ptr - (char*)out <= datasize ); - - return out; -} - - -#define sum_elem_ptr(sum,row,col) \ - ((sumtype*)CV_MAT_ELEM_PTR_FAST((sum),(row),(col),sizeof(sumtype))) - -#define sqsum_elem_ptr(sqsum,row,col) \ - ((sqsumtype*)CV_MAT_ELEM_PTR_FAST((sqsum),(row),(col),sizeof(sqsumtype))) - -#define calc_sum(rect,offset) \ - ((rect).p0[offset] - (rect).p1[offset] - (rect).p2[offset] + (rect).p3[offset]) - -CV_IMPL void -cvSetImagesForHaarClassifierCascade( CvHaarClassifierCascade* _cascade, - const CvArr* _sum, - const CvArr* _sqsum, - const CvArr* _tilted_sum, - double scale ) -{ - CvMat sum_stub, *sum = (CvMat*)_sum; - CvMat sqsum_stub, *sqsum = (CvMat*)_sqsum; - CvMat tilted_stub, *tilted = (CvMat*)_tilted_sum; - CvHidHaarClassifierCascade* cascade; - int coi0 = 0, coi1 = 0; - int i; - cv::Rect equRect; - double weight_scale; - - if( !CV_IS_HAAR_CLASSIFIER(_cascade) ) - CV_Error( !_cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid classifier pointer" ); - - if( scale <= 0 ) - CV_Error( CV_StsOutOfRange, "Scale must be positive" ); - - sum = cvGetMat( sum, &sum_stub, &coi0 ); - sqsum = cvGetMat( sqsum, &sqsum_stub, &coi1 ); - - if( coi0 || coi1 ) - CV_Error( CV_BadCOI, "COI is not supported" ); - - if( !CV_ARE_SIZES_EQ( sum, sqsum )) - CV_Error( CV_StsUnmatchedSizes, "All integral images must have the same size" ); - - if( CV_MAT_TYPE(sqsum->type) != CV_64FC1 || - CV_MAT_TYPE(sum->type) != CV_32SC1 ) - CV_Error( CV_StsUnsupportedFormat, - "Only (32s, 64f, 32s) combination of (sum,sqsum,tilted_sum) formats is allowed" ); - - if( !_cascade->hid_cascade ) - icvCreateHidHaarClassifierCascade(_cascade); - - cascade = _cascade->hid_cascade; - - if( cascade->has_tilted_features ) - { - tilted = cvGetMat( tilted, &tilted_stub, &coi1 ); - - if( CV_MAT_TYPE(tilted->type) != CV_32SC1 ) - CV_Error( CV_StsUnsupportedFormat, - "Only (32s, 64f, 32s) combination of (sum,sqsum,tilted_sum) formats is allowed" ); - - if( sum->step != tilted->step ) - CV_Error( CV_StsUnmatchedSizes, - "Sum and tilted_sum must have the same stride (step, widthStep)" ); - - if( !CV_ARE_SIZES_EQ( sum, tilted )) - CV_Error( CV_StsUnmatchedSizes, "All integral images must have the same size" ); - cascade->tilted = *tilted; - } - - _cascade->scale = scale; - _cascade->real_window_size.width = cvRound( _cascade->orig_window_size.width * scale ); - _cascade->real_window_size.height = cvRound( _cascade->orig_window_size.height * scale ); - - cascade->sum = *sum; - cascade->sqsum = *sqsum; - - equRect.x = equRect.y = cvRound(scale); - equRect.width = cvRound((_cascade->orig_window_size.width-2)*scale); - equRect.height = cvRound((_cascade->orig_window_size.height-2)*scale); - weight_scale = 1./(equRect.width*equRect.height); - cascade->inv_window_area = weight_scale; - - cascade->p0 = sum_elem_ptr(*sum, equRect.y, equRect.x); - cascade->p1 = sum_elem_ptr(*sum, equRect.y, equRect.x + equRect.width ); - cascade->p2 = sum_elem_ptr(*sum, equRect.y + equRect.height, equRect.x ); - cascade->p3 = sum_elem_ptr(*sum, equRect.y + equRect.height, - equRect.x + equRect.width ); - - cascade->pq0 = sqsum_elem_ptr(*sqsum, equRect.y, equRect.x); - cascade->pq1 = sqsum_elem_ptr(*sqsum, equRect.y, equRect.x + equRect.width ); - cascade->pq2 = sqsum_elem_ptr(*sqsum, equRect.y + equRect.height, equRect.x ); - cascade->pq3 = sqsum_elem_ptr(*sqsum, equRect.y + equRect.height, - equRect.x + equRect.width ); - - /* init pointers in haar features according to real window size and - given image pointers */ - for( i = 0; i < _cascade->count; i++ ) - { - int j, k, l; - for( j = 0; j < cascade->stage_classifier[i].count; j++ ) - { - for( l = 0; l < cascade->stage_classifier[i].classifier[j].count; l++ ) - { - CvHaarFeature* feature = - &_cascade->stage_classifier[i].classifier[j].haar_feature[l]; - /* CvHidHaarClassifier* classifier = - cascade->stage_classifier[i].classifier + j; */ - CvHidHaarFeature* hidfeature = - &cascade->stage_classifier[i].classifier[j].node[l].feature; - double sum0 = 0, area0 = 0; - cv::Rect r[3]; - - int base_w = -1, base_h = -1; - int new_base_w = 0, new_base_h = 0; - int kx, ky; - int flagx = 0, flagy = 0; - int x0 = 0, y0 = 0; - int nr; - - /* align blocks */ - for( k = 0; k < CV_HAAR_FEATURE_MAX; k++ ) - { - if( !hidfeature->rect[k].p0 ) - break; - r[k] = feature->rect[k].r; - base_w = (int)CV_IMIN( (unsigned)base_w, (unsigned)(r[k].width-1) ); - base_w = (int)CV_IMIN( (unsigned)base_w, (unsigned)(r[k].x - r[0].x-1) ); - base_h = (int)CV_IMIN( (unsigned)base_h, (unsigned)(r[k].height-1) ); - base_h = (int)CV_IMIN( (unsigned)base_h, (unsigned)(r[k].y - r[0].y-1) ); - } - - nr = k; - - base_w += 1; - base_h += 1; - kx = r[0].width / base_w; - ky = r[0].height / base_h; - - if( kx <= 0 ) - { - flagx = 1; - new_base_w = cvRound( r[0].width * scale ) / kx; - x0 = cvRound( r[0].x * scale ); - } - - if( ky <= 0 ) - { - flagy = 1; - new_base_h = cvRound( r[0].height * scale ) / ky; - y0 = cvRound( r[0].y * scale ); - } - - for( k = 0; k < nr; k++ ) - { - cv::Rect tr; - double correction_ratio; - - if( flagx ) - { - tr.x = (r[k].x - r[0].x) * new_base_w / base_w + x0; - tr.width = r[k].width * new_base_w / base_w; - } - else - { - tr.x = cvRound( r[k].x * scale ); - tr.width = cvRound( r[k].width * scale ); - } - - if( flagy ) - { - tr.y = (r[k].y - r[0].y) * new_base_h / base_h + y0; - tr.height = r[k].height * new_base_h / base_h; - } - else - { - tr.y = cvRound( r[k].y * scale ); - tr.height = cvRound( r[k].height * scale ); - } - -#if CV_ADJUST_WEIGHTS - { - // RAINER START - const float orig_feature_size = (float)(feature->rect[k].r.width)*feature->rect[k].r.height; - const float orig_norm_size = (float)(_cascade->orig_window_size.width)*(_cascade->orig_window_size.height); - const float feature_size = float(tr.width*tr.height); - //const float normSize = float(equRect.width*equRect.height); - float target_ratio = orig_feature_size / orig_norm_size; - //float isRatio = featureSize / normSize; - //correctionRatio = targetRatio / isRatio / normSize; - correction_ratio = target_ratio / feature_size; - // RAINER END - } -#else - correction_ratio = weight_scale * (!feature->tilted ? 1 : 0.5); -#endif - - if( !feature->tilted ) - { - hidfeature->rect[k].p0 = sum_elem_ptr(*sum, tr.y, tr.x); - hidfeature->rect[k].p1 = sum_elem_ptr(*sum, tr.y, tr.x + tr.width); - hidfeature->rect[k].p2 = sum_elem_ptr(*sum, tr.y + tr.height, tr.x); - hidfeature->rect[k].p3 = sum_elem_ptr(*sum, tr.y + tr.height, tr.x + tr.width); - } - else - { - hidfeature->rect[k].p2 = sum_elem_ptr(*tilted, tr.y + tr.width, tr.x + tr.width); - hidfeature->rect[k].p3 = sum_elem_ptr(*tilted, tr.y + tr.width + tr.height, - tr.x + tr.width - tr.height); - hidfeature->rect[k].p0 = sum_elem_ptr(*tilted, tr.y, tr.x); - hidfeature->rect[k].p1 = sum_elem_ptr(*tilted, tr.y + tr.height, tr.x - tr.height); - } - - hidfeature->rect[k].weight = (float)(feature->rect[k].weight * correction_ratio); - - if( k == 0 ) - area0 = tr.width * tr.height; - else - sum0 += hidfeature->rect[k].weight * tr.width * tr.height; - } - CV_Assert(area0 > 0); - hidfeature->rect[0].weight = (float)(-sum0/area0); - } /* l */ - } /* j */ - } -} - - -CV_INLINE -double icvEvalHidHaarClassifier( CvHidHaarClassifier* classifier, - double variance_norm_factor, - size_t p_offset ) -{ - int idx = 0; - /*#if CV_HAAR_USE_SSE && !CV_HAAR_USE_AVX - if(cv::checkHardwareSupport(CV_CPU_SSE2))//based on old SSE variant. Works slow - { - double CV_DECL_ALIGNED(16) temp[2]; - __m128d zero = _mm_setzero_pd(); - do - { - CvHidHaarTreeNode* node = classifier->node + idx; - __m128d t = _mm_set1_pd((node->threshold)*variance_norm_factor); - __m128d left = _mm_set1_pd(node->left); - __m128d right = _mm_set1_pd(node->right); - - double _sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight; - _sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight; - if( node->feature.rect[2].p0 ) - _sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight; - - __m128d sum = _mm_set1_pd(_sum); - t = _mm_cmplt_sd(sum, t); - sum = _mm_blendv_pd(right, left, t); - - _mm_store_pd(temp, sum); - idx = (int)temp[0]; - } - while(idx > 0 ); - - } - else - #endif*/ - { - do - { - CvHidHaarTreeNode* node = classifier->node + idx; - double t = node->threshold * variance_norm_factor; - - double sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight; - sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight; - - if( node->feature.rect[2].p0 ) - sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight; - - idx = sum < t ? node->left : node->right; - } - while( idx > 0 ); - } - return classifier->alpha[-idx]; -} - - - -static int -cvRunHaarClassifierCascadeSum( const CvHaarClassifierCascade* _cascade, - CvPoint pt, double& stage_sum, int start_stage ) -{ -#if CV_HAAR_USE_AVX - bool haveAVX = CV_CPU_HAS_SUPPORT_AVX; -#else -# ifdef CV_HAAR_USE_SSE - bool haveSSE2 = cv::checkHardwareSupport(CV_CPU_SSE2); -# endif -#endif - - int p_offset, pq_offset; - int i, j; - double mean, variance_norm_factor; - CvHidHaarClassifierCascade* cascade; - - if( !CV_IS_HAAR_CLASSIFIER(_cascade) ) - CV_Error( !_cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid cascade pointer" ); - - cascade = _cascade->hid_cascade; - if( !cascade ) - CV_Error( CV_StsNullPtr, "Hidden cascade has not been created.\n" - "Use cvSetImagesForHaarClassifierCascade" ); - - if( pt.x < 0 || pt.y < 0 || - pt.x + _cascade->real_window_size.width >= cascade->sum.width || - pt.y + _cascade->real_window_size.height >= cascade->sum.height ) - return -1; - - p_offset = pt.y * (cascade->sum.step/sizeof(sumtype)) + pt.x; - pq_offset = pt.y * (cascade->sqsum.step/sizeof(sqsumtype)) + pt.x; - mean = calc_sum(*cascade,p_offset)*cascade->inv_window_area; - variance_norm_factor = cascade->pq0[pq_offset] - cascade->pq1[pq_offset] - - cascade->pq2[pq_offset] + cascade->pq3[pq_offset]; - variance_norm_factor = variance_norm_factor*cascade->inv_window_area - mean*mean; - if( variance_norm_factor >= 0. ) - variance_norm_factor = std::sqrt(variance_norm_factor); - else - variance_norm_factor = 1.; - - if( cascade->is_tree ) - { - CvHidHaarStageClassifier* ptr = cascade->stage_classifier; - assert( start_stage == 0 ); - - while( ptr ) - { - stage_sum = 0.0; - j = 0; - -#if CV_HAAR_USE_AVX - if(haveAVX) - { - for( ; j <= ptr->count - 8; j += 8 ) - { - stage_sum += cv_haar_avx::icvEvalHidHaarClassifierAVX( - ptr->classifier + j, - variance_norm_factor, p_offset ); - } - } -#endif - for( ; j < ptr->count; j++ ) - { - stage_sum += icvEvalHidHaarClassifier( ptr->classifier + j, variance_norm_factor, p_offset ); - } - - if( stage_sum >= ptr->threshold ) - { - ptr = ptr->child; - } - else - { - while( ptr && ptr->next == NULL ) ptr = ptr->parent; - if( ptr == NULL ) - return 0; - ptr = ptr->next; - } - } - } - else if( cascade->isStumpBased ) - { -#if CV_HAAR_USE_AVX - if(haveAVX) - { - for( i = start_stage; i < cascade->count; i++ ) - { - stage_sum = 0.0; - j = 0; - if( cascade->stage_classifier[i].two_rects ) - { - for( ; j <= cascade->stage_classifier[i].count - 8; j += 8 ) - { - stage_sum += cv_haar_avx::icvEvalHidHaarStumpClassifierTwoRectAVX( - cascade->stage_classifier[i].classifier + j, - variance_norm_factor, p_offset); - } - - for( ; j < cascade->stage_classifier[i].count; j++ ) - { - CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j; - CvHidHaarTreeNode* node = classifier->node; - - double t = node->threshold*variance_norm_factor; - double sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight; - sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight; - stage_sum += classifier->alpha[sum >= t]; - } - } - else - { - for( ; j <= (cascade->stage_classifier[i].count)-8; j+=8 ) - { - stage_sum += cv_haar_avx::icvEvalHidHaarStumpClassifierAVX( - cascade->stage_classifier[i].classifier + j, - variance_norm_factor, p_offset); - } - - for( ; j < cascade->stage_classifier[i].count; j++ ) - { - CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j; - CvHidHaarTreeNode* node = classifier->node; - - double t = node->threshold*variance_norm_factor; - double sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight; - sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight; - if( node->feature.rect[2].p0 ) - sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight; - stage_sum += classifier->alpha[sum >= t]; - } - } - if( stage_sum < cascade->stage_classifier[i].threshold ) - return -i; - } - } - else -#elif defined CV_HAAR_USE_SSE //old SSE optimization - if(haveSSE2) - { - for( i = start_stage; i < cascade->count; i++ ) - { - __m128d vstage_sum = _mm_setzero_pd(); - if( cascade->stage_classifier[i].two_rects ) - { - for( j = 0; j < cascade->stage_classifier[i].count; j++ ) - { - CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j; - CvHidHaarTreeNode* node = classifier->node; - - // ayasin - NHM perf optim. Avoid use of costly flaky jcc - __m128d t = _mm_set_sd(node->threshold*variance_norm_factor); - __m128d a = _mm_set_sd(classifier->alpha[0]); - __m128d b = _mm_set_sd(classifier->alpha[1]); - __m128d sum = _mm_set_sd(calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight + - calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight); - t = _mm_cmpgt_sd(t, sum); - vstage_sum = _mm_add_sd(vstage_sum, _mm_blendv_pd(b, a, t)); - } - } - else - { - for( j = 0; j < cascade->stage_classifier[i].count; j++ ) - { - CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j; - CvHidHaarTreeNode* node = classifier->node; - // ayasin - NHM perf optim. Avoid use of costly flaky jcc - __m128d t = _mm_set_sd(node->threshold*variance_norm_factor); - __m128d a = _mm_set_sd(classifier->alpha[0]); - __m128d b = _mm_set_sd(classifier->alpha[1]); - double _sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight; - _sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight; - if( node->feature.rect[2].p0 ) - _sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight; - __m128d sum = _mm_set_sd(_sum); - - t = _mm_cmpgt_sd(t, sum); - vstage_sum = _mm_add_sd(vstage_sum, _mm_blendv_pd(b, a, t)); - } - } - __m128d i_threshold = _mm_set1_pd(cascade->stage_classifier[i].threshold); - if( _mm_comilt_sd(vstage_sum, i_threshold) ) - return -i; - } - } - else -#endif // AVX or SSE - { - for( i = start_stage; i < cascade->count; i++ ) - { - stage_sum = 0.0; - if( cascade->stage_classifier[i].two_rects ) - { - for( j = 0; j < cascade->stage_classifier[i].count; j++ ) - { - CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j; - CvHidHaarTreeNode* node = classifier->node; - double t = node->threshold*variance_norm_factor; - double sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight; - sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight; - stage_sum += classifier->alpha[sum >= t]; - } - } - else - { - for( j = 0; j < cascade->stage_classifier[i].count; j++ ) - { - CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j; - CvHidHaarTreeNode* node = classifier->node; - double t = node->threshold*variance_norm_factor; - double sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight; - sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight; - if( node->feature.rect[2].p0 ) - sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight; - stage_sum += classifier->alpha[sum >= t]; - } - } - if( stage_sum < cascade->stage_classifier[i].threshold ) - return -i; - } - } - } - else - { - for( i = start_stage; i < cascade->count; i++ ) - { - stage_sum = 0.0; - int k = 0; - -#if CV_HAAR_USE_AVX - if(haveAVX) - { - for( ; k < cascade->stage_classifier[i].count - 8; k += 8 ) - { - stage_sum += cv_haar_avx::icvEvalHidHaarClassifierAVX( - cascade->stage_classifier[i].classifier + k, - variance_norm_factor, p_offset ); - } - } -#endif - for(; k < cascade->stage_classifier[i].count; k++ ) - { - - stage_sum += icvEvalHidHaarClassifier( - cascade->stage_classifier[i].classifier + k, - variance_norm_factor, p_offset ); - } - - if( stage_sum < cascade->stage_classifier[i].threshold ) - return -i; - } - } - return 1; -} - - -CV_IMPL int -cvRunHaarClassifierCascade( const CvHaarClassifierCascade* _cascade, - CvPoint pt, int start_stage ) -{ - CV_INSTRUMENT_REGION(); - - double stage_sum; - return cvRunHaarClassifierCascadeSum(_cascade, pt, stage_sum, start_stage); -} - -namespace cv -{ - -const size_t PARALLEL_LOOP_BATCH_SIZE = 100; - -class HaarDetectObjects_ScaleImage_Invoker : public ParallelLoopBody -{ -public: - HaarDetectObjects_ScaleImage_Invoker( const CvHaarClassifierCascade* _cascade, - int _stripSize, double _factor, - const Mat& _sum1, const Mat& _sqsum1, Mat* _norm1, - Mat* _mask1, Rect _equRect, std::vector& _vec, - std::vector& _levels, std::vector& _weights, - bool _outputLevels, Mutex *_mtx ) - { - cascade = _cascade; - stripSize = _stripSize; - factor = _factor; - sum1 = _sum1; - sqsum1 = _sqsum1; - norm1 = _norm1; - mask1 = _mask1; - equRect = _equRect; - vec = &_vec; - rejectLevels = _outputLevels ? &_levels : 0; - levelWeights = _outputLevels ? &_weights : 0; - mtx = _mtx; - } - - void operator()(const Range& range) const CV_OVERRIDE - { - CV_INSTRUMENT_REGION(); - - Size winSize0 = cascade->orig_window_size; - Size winSize(cvRound(winSize0.width*factor), cvRound(winSize0.height*factor)); - int y1 = range.start*stripSize, y2 = std::min(range.end*stripSize, sum1.rows - 1 - winSize0.height); - - if (y2 <= y1 || sum1.cols <= 1 + winSize0.width) - return; - - Size ssz(sum1.cols - 1 - winSize0.width, y2 - y1); - int x, y, ystep = factor > 2 ? 1 : 2; - - std::vector vecLocal; - std::vector rejectLevelsLocal; - std::vector levelWeightsLocal; - - for( y = y1; y < y2; y += ystep ) - for( x = 0; x < ssz.width; x += ystep ) - { - double gypWeight; - int result = cvRunHaarClassifierCascadeSum( cascade, cvPoint(x,y), gypWeight, 0 ); - if( rejectLevels ) - { - if( result == 1 ) - result = -1*cascade->count; - if( cascade->count + result < 4 ) - { - vecLocal.push_back(Rect(cvRound(x*factor), cvRound(y*factor), - winSize.width, winSize.height)); - rejectLevelsLocal.push_back(-result); - levelWeightsLocal.push_back(gypWeight); - - if (vecLocal.size() >= PARALLEL_LOOP_BATCH_SIZE) - { - mtx->lock(); - vec->insert(vec->end(), vecLocal.begin(), vecLocal.end()); - rejectLevels->insert(rejectLevels->end(), rejectLevelsLocal.begin(), rejectLevelsLocal.end()); - levelWeights->insert(levelWeights->end(), levelWeightsLocal.begin(), levelWeightsLocal.end()); - mtx->unlock(); - - vecLocal.clear(); - rejectLevelsLocal.clear(); - levelWeightsLocal.clear(); - } - } - } - else - { - if( result > 0 ) - { - vecLocal.push_back(Rect(cvRound(x*factor), cvRound(y*factor), - winSize.width, winSize.height)); - - if (vecLocal.size() >= PARALLEL_LOOP_BATCH_SIZE) - { - mtx->lock(); - vec->insert(vec->end(), vecLocal.begin(), vecLocal.end()); - mtx->unlock(); - - vecLocal.clear(); - } - } - } - } - - if (rejectLevelsLocal.size()) - { - mtx->lock(); - vec->insert(vec->end(), vecLocal.begin(), vecLocal.end()); - rejectLevels->insert(rejectLevels->end(), rejectLevelsLocal.begin(), rejectLevelsLocal.end()); - levelWeights->insert(levelWeights->end(), levelWeightsLocal.begin(), levelWeightsLocal.end()); - mtx->unlock(); - } - else - if (vecLocal.size()) - { - mtx->lock(); - vec->insert(vec->end(), vecLocal.begin(), vecLocal.end()); - mtx->unlock(); - } - } - - const CvHaarClassifierCascade* cascade; - int stripSize; - double factor; - Mat sum1, sqsum1, *norm1, *mask1; - Rect equRect; - std::vector* vec; - std::vector* rejectLevels; - std::vector* levelWeights; - Mutex* mtx; -}; - - -class HaarDetectObjects_ScaleCascade_Invoker : public ParallelLoopBody -{ -public: - HaarDetectObjects_ScaleCascade_Invoker( const CvHaarClassifierCascade* _cascade, - Size _winsize, const Range& _xrange, double _ystep, - size_t _sumstep, const int** _p, const int** _pq, - std::vector& _vec, Mutex* _mtx ) - { - cascade = _cascade; - winsize = _winsize; - xrange = _xrange; - ystep = _ystep; - sumstep = _sumstep; - p = _p; pq = _pq; - vec = &_vec; - mtx = _mtx; - } - - void operator()(const Range& range) const CV_OVERRIDE - { - CV_INSTRUMENT_REGION(); - - int iy, startY = range.start, endY = range.end; - const int *p0 = p[0], *p1 = p[1], *p2 = p[2], *p3 = p[3]; - const int *pq0 = pq[0], *pq1 = pq[1], *pq2 = pq[2], *pq3 = pq[3]; - bool doCannyPruning = p0 != 0; - int sstep = (int)(sumstep/sizeof(p0[0])); - - std::vector vecLocal; - - for( iy = startY; iy < endY; iy++ ) - { - int ix, y = cvRound(iy*ystep), ixstep = 1; - for( ix = xrange.start; ix < xrange.end; ix += ixstep ) - { - int x = cvRound(ix*ystep); // it should really be ystep, not ixstep - - if( doCannyPruning ) - { - int offset = y*sstep + x; - int s = p0[offset] - p1[offset] - p2[offset] + p3[offset]; - int sq = pq0[offset] - pq1[offset] - pq2[offset] + pq3[offset]; - if( s < 100 || sq < 20 ) - { - ixstep = 2; - continue; - } - } - - int result = cvRunHaarClassifierCascade( cascade, cvPoint(x, y), 0 ); - if( result > 0 ) - { - vecLocal.push_back(Rect(x, y, winsize.width, winsize.height)); - - if (vecLocal.size() >= PARALLEL_LOOP_BATCH_SIZE) - { - mtx->lock(); - vec->insert(vec->end(), vecLocal.begin(), vecLocal.end()); - mtx->unlock(); - - vecLocal.clear(); - } - } - ixstep = result != 0 ? 1 : 2; - } - } - - if (vecLocal.size()) - { - mtx->lock(); - vec->insert(vec->end(), vecLocal.begin(), vecLocal.end()); - mtx->unlock(); - } - } - - const CvHaarClassifierCascade* cascade; - double ystep; - size_t sumstep; - Size winsize; - Range xrange; - const int** p; - const int** pq; - std::vector* vec; - Mutex* mtx; -}; - - -} - -CvSeq* -cvHaarDetectObjectsForROC( const CvArr* _img, - CvHaarClassifierCascade* cascade, CvMemStorage* storage, - std::vector& rejectLevels, std::vector& levelWeights, - double scaleFactor, int minNeighbors, int flags, - CvSize minSize, CvSize maxSize, bool outputRejectLevels ) -{ - CV_INSTRUMENT_REGION(); - - const double GROUP_EPS = 0.2; - CvMat stub, *img = (CvMat*)_img; - cv::Ptr temp, sum, tilted, sqsum, normImg, sumcanny, imgSmall; - CvSeq* result_seq = 0; - cv::Ptr temp_storage; - - std::vector allCandidates; - std::vector rectList; - std::vector rweights; - double factor; - int coi; - bool doCannyPruning = (flags & CV_HAAR_DO_CANNY_PRUNING) != 0; - bool findBiggestObject = (flags & CV_HAAR_FIND_BIGGEST_OBJECT) != 0; - bool roughSearch = (flags & CV_HAAR_DO_ROUGH_SEARCH) != 0; - cv::Mutex mtx; - - if( !CV_IS_HAAR_CLASSIFIER(cascade) ) - CV_Error( !cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid classifier cascade" ); - - if( !storage ) - CV_Error( CV_StsNullPtr, "Null storage pointer" ); - - img = cvGetMat( img, &stub, &coi ); - if( coi ) - CV_Error( CV_BadCOI, "COI is not supported" ); - - if( CV_MAT_DEPTH(img->type) != CV_8U ) - CV_Error( CV_StsUnsupportedFormat, "Only 8-bit images are supported" ); - - if( scaleFactor <= 1 ) - CV_Error( CV_StsOutOfRange, "scale factor must be > 1" ); - - if( findBiggestObject ) - flags &= ~CV_HAAR_SCALE_IMAGE; - - if( maxSize.height == 0 || maxSize.width == 0 ) - { - maxSize.height = img->rows; - maxSize.width = img->cols; - } - - temp.reset(cvCreateMat( img->rows, img->cols, CV_8UC1 )); - sum.reset(cvCreateMat( img->rows + 1, img->cols + 1, CV_32SC1 )); - sqsum.reset(cvCreateMat( img->rows + 1, img->cols + 1, CV_64FC1 )); - - if( !cascade->hid_cascade ) - icvCreateHidHaarClassifierCascade(cascade); - - if( cascade->hid_cascade->has_tilted_features ) - tilted.reset(cvCreateMat( img->rows + 1, img->cols + 1, CV_32SC1 )); - - result_seq = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvAvgComp), storage ); - - if( CV_MAT_CN(img->type) > 1 ) - { - cvCvtColor( img, temp, CV_BGR2GRAY ); - img = temp; - } - - if( findBiggestObject ) - flags &= ~(CV_HAAR_SCALE_IMAGE|CV_HAAR_DO_CANNY_PRUNING); - - if( flags & CV_HAAR_SCALE_IMAGE ) - { - CvSize winSize0 = cascade->orig_window_size; - imgSmall.reset(cvCreateMat( img->rows + 1, img->cols + 1, CV_8UC1 )); - - for( factor = 1; ; factor *= scaleFactor ) - { - CvSize winSize = { cvRound(winSize0.width*factor), - cvRound(winSize0.height*factor) }; - CvSize sz = { cvRound(img->cols/factor), cvRound(img->rows/factor) }; - CvSize sz1 = { sz.width - winSize0.width + 1, sz.height - winSize0.height + 1 }; - - CvRect equRect = { icv_object_win_border, icv_object_win_border, - winSize0.width - icv_object_win_border*2, winSize0.height - icv_object_win_border*2 }; - - CvMat img1, sum1, sqsum1, norm1, tilted1, mask1; - CvMat* _tilted = 0; - - if( sz1.width <= 0 || sz1.height <= 0 ) - break; - if( winSize.width > maxSize.width || winSize.height > maxSize.height ) - break; - if( winSize.width < minSize.width || winSize.height < minSize.height ) - continue; - - img1 = cvMat( sz.height, sz.width, CV_8UC1, imgSmall->data.ptr ); - sum1 = cvMat( sz.height+1, sz.width+1, CV_32SC1, sum->data.ptr ); - sqsum1 = cvMat( sz.height+1, sz.width+1, CV_64FC1, sqsum->data.ptr ); - if( tilted ) - { - tilted1 = cvMat( sz.height+1, sz.width+1, CV_32SC1, tilted->data.ptr ); - _tilted = &tilted1; - } - norm1 = cvMat( sz1.height, sz1.width, CV_32FC1, normImg ? normImg->data.ptr : 0 ); - mask1 = cvMat( sz1.height, sz1.width, CV_8UC1, temp->data.ptr ); - - cvResize( img, &img1, cv::INTER_LINEAR_EXACT ); - cvIntegral( &img1, &sum1, &sqsum1, _tilted ); - - int ystep = factor > 2 ? 1 : 2; - const int LOCS_PER_THREAD = 1000; - int stripCount = ((sz1.width/ystep)*(sz1.height + ystep-1)/ystep + LOCS_PER_THREAD/2)/LOCS_PER_THREAD; - stripCount = std::min(std::max(stripCount, 1), 100); - - cvSetImagesForHaarClassifierCascade( cascade, &sum1, &sqsum1, _tilted, 1. ); - - cv::Mat _norm1 = cv::cvarrToMat(&norm1), _mask1 = cv::cvarrToMat(&mask1); - cv::parallel_for_(cv::Range(0, stripCount), - cv::HaarDetectObjects_ScaleImage_Invoker(cascade, - (((sz1.height + stripCount - 1)/stripCount + ystep-1)/ystep)*ystep, - factor, cv::cvarrToMat(&sum1), cv::cvarrToMat(&sqsum1), &_norm1, &_mask1, - cv::Rect(equRect), allCandidates, rejectLevels, levelWeights, outputRejectLevels, &mtx)); - } - } - else - { - int n_factors = 0; - cv::Rect scanROI; - - cvIntegral( img, sum, sqsum, tilted ); - - if( doCannyPruning ) - { - sumcanny.reset(cvCreateMat( img->rows + 1, img->cols + 1, CV_32SC1 )); - cvCanny( img, temp, 0, 50, 3 ); - cvIntegral( temp, sumcanny ); - } - - for( n_factors = 0, factor = 1; - factor*cascade->orig_window_size.width < img->cols - 10 && - factor*cascade->orig_window_size.height < img->rows - 10; - n_factors++, factor *= scaleFactor ) - ; - - if( findBiggestObject ) - { - scaleFactor = 1./scaleFactor; - factor *= scaleFactor; - } - else - factor = 1; - - for( ; n_factors-- > 0; factor *= scaleFactor ) - { - const double ystep = std::max( 2., factor ); - cv::Size winSize(cvRound(cascade->orig_window_size.width * factor), - cvRound(cascade->orig_window_size.height * factor)); - cv::Rect equRect; - int *p[4] = {0,0,0,0}; - int *pq[4] = {0,0,0,0}; - int startX = 0, startY = 0; - int endX = cvRound((img->cols - winSize.width) / ystep); - int endY = cvRound((img->rows - winSize.height) / ystep); - - if( winSize.width < minSize.width || winSize.height < minSize.height ) - { - if( findBiggestObject ) - break; - continue; - } - - if ( winSize.width > maxSize.width || winSize.height > maxSize.height ) - { - if( !findBiggestObject ) - break; - continue; - } - - cvSetImagesForHaarClassifierCascade( cascade, sum, sqsum, tilted, factor ); - cvZero( temp ); - - if( doCannyPruning ) - { - equRect.x = cvRound(winSize.width*0.15); - equRect.y = cvRound(winSize.height*0.15); - equRect.width = cvRound(winSize.width*0.7); - equRect.height = cvRound(winSize.height*0.7); - - p[0] = (int*)(sumcanny->data.ptr + equRect.y*sumcanny->step) + equRect.x; - p[1] = (int*)(sumcanny->data.ptr + equRect.y*sumcanny->step) - + equRect.x + equRect.width; - p[2] = (int*)(sumcanny->data.ptr + (equRect.y + equRect.height)*sumcanny->step) + equRect.x; - p[3] = (int*)(sumcanny->data.ptr + (equRect.y + equRect.height)*sumcanny->step) - + equRect.x + equRect.width; - - pq[0] = (int*)(sum->data.ptr + equRect.y*sum->step) + equRect.x; - pq[1] = (int*)(sum->data.ptr + equRect.y*sum->step) - + equRect.x + equRect.width; - pq[2] = (int*)(sum->data.ptr + (equRect.y + equRect.height)*sum->step) + equRect.x; - pq[3] = (int*)(sum->data.ptr + (equRect.y + equRect.height)*sum->step) - + equRect.x + equRect.width; - } - - if( !scanROI.empty() ) - { - //adjust start_height and stop_height - startY = cvRound(scanROI.y / ystep); - endY = cvRound((scanROI.y + scanROI.height - winSize.height) / ystep); - - startX = cvRound(scanROI.x / ystep); - endX = cvRound((scanROI.x + scanROI.width - winSize.width) / ystep); - } - - cv::parallel_for_(cv::Range(startY, endY), - cv::HaarDetectObjects_ScaleCascade_Invoker(cascade, winSize, cv::Range(startX, endX), - ystep, sum->step, (const int**)p, - (const int**)pq, allCandidates, &mtx )); - - if( findBiggestObject && !allCandidates.empty() && scanROI.empty() ) - { - rectList.resize(allCandidates.size()); - std::copy(allCandidates.begin(), allCandidates.end(), rectList.begin()); - - groupRectangles(rectList, std::max(minNeighbors, 1), GROUP_EPS); - - if( !rectList.empty() ) - { - size_t i, sz = rectList.size(); - cv::Rect maxRect; - - for( i = 0; i < sz; i++ ) - { - if( rectList[i].area() > maxRect.area() ) - maxRect = rectList[i]; - } - - allCandidates.push_back(maxRect); - - scanROI = maxRect; - int dx = cvRound(maxRect.width*GROUP_EPS); - int dy = cvRound(maxRect.height*GROUP_EPS); - scanROI.x = std::max(scanROI.x - dx, 0); - scanROI.y = std::max(scanROI.y - dy, 0); - scanROI.width = std::min(scanROI.width + dx*2, img->cols-1-scanROI.x); - scanROI.height = std::min(scanROI.height + dy*2, img->rows-1-scanROI.y); - - double minScale = roughSearch ? 0.6 : 0.4; - minSize.width = cvRound(maxRect.width*minScale); - minSize.height = cvRound(maxRect.height*minScale); - } - } - } - } - - rectList.resize(allCandidates.size()); - if(!allCandidates.empty()) - std::copy(allCandidates.begin(), allCandidates.end(), rectList.begin()); - - if( minNeighbors != 0 || findBiggestObject ) - { - if( outputRejectLevels ) - { - groupRectangles(rectList, rejectLevels, levelWeights, minNeighbors, GROUP_EPS ); - } - else - { - groupRectangles(rectList, rweights, std::max(minNeighbors, 1), GROUP_EPS); - } - } - else - rweights.resize(rectList.size(),0); - - if( findBiggestObject && rectList.size() ) - { - CvAvgComp result_comp = {{0, 0, 0, 0},0}; - - for( size_t i = 0; i < rectList.size(); i++ ) - { - cv::Rect r = rectList[i]; - if( r.area() > cv::Rect(result_comp.rect).area() ) - { - result_comp.rect = cvRect(r); - result_comp.neighbors = rweights[i]; - } - } - cvSeqPush( result_seq, &result_comp ); - } - else - { - for( size_t i = 0; i < rectList.size(); i++ ) - { - CvAvgComp c; - c.rect = cvRect(rectList[i]); - c.neighbors = !rweights.empty() ? rweights[i] : 0; - cvSeqPush( result_seq, &c ); - } - } - - return result_seq; -} - -CV_IMPL CvSeq* -cvHaarDetectObjects( const CvArr* _img, - CvHaarClassifierCascade* cascade, CvMemStorage* storage, - double scaleFactor, - int minNeighbors, int flags, CvSize minSize, CvSize maxSize ) -{ - std::vector fakeLevels; - std::vector fakeWeights; - return cvHaarDetectObjectsForROC( _img, cascade, storage, fakeLevels, fakeWeights, - scaleFactor, minNeighbors, flags, minSize, maxSize, false ); - -} - -CV_IMPL void -cvReleaseHaarClassifierCascade( CvHaarClassifierCascade** _cascade ) -{ - if( _cascade && *_cascade ) - { - int i, j; - CvHaarClassifierCascade* cascade = *_cascade; - - for( i = 0; i < cascade->count; i++ ) - { - for( j = 0; j < cascade->stage_classifier[i].count; j++ ) - cvFree( &cascade->stage_classifier[i].classifier[j].haar_feature ); - cvFree( &cascade->stage_classifier[i].classifier ); - } - icvReleaseHidHaarClassifierCascade( &cascade->hid_cascade ); - cvFree( _cascade ); - } -} - -CV_IMPL CvHaarClassifierCascade* -cvLoadHaarClassifierCascade( const char*, CvSize ) -{ - return 0; -} - -#if 0 - -static CvHaarClassifierCascade* -icvLoadCascadeCART( const char** input_cascade, int n, CvSize orig_window_size ) -{ - int i; - CvHaarClassifierCascade* cascade = icvCreateHaarClassifierCascade(n); - cascade->orig_window_size = orig_window_size; - - for( i = 0; i < n; i++ ) - { - int j, count, l; - float threshold = 0; - const char* stage = input_cascade[i]; - int dl = 0; - - /* tree links */ - int parent = -1; - int next = -1; - - sscanf( stage, "%d%n", &count, &dl ); - stage += dl; - - CV_Assert( count > 0 && count < CV_HAAR_STAGE_MAX); - cascade->stage_classifier[i].count = count; - cascade->stage_classifier[i].classifier = - (CvHaarClassifier*)cvAlloc( count*sizeof(cascade->stage_classifier[i].classifier[0])); - - for( j = 0; j < count; j++ ) - { - CvHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j; - int k, rects = 0; - char str[100]; - - sscanf( stage, "%d%n", &classifier->count, &dl ); - stage += dl; - - CV_Assert( classifier->count > 0 && classifier->count< CV_HAAR_STAGE_MAX); - classifier->haar_feature = (CvHaarFeature*) cvAlloc( - classifier->count * ( sizeof( *classifier->haar_feature ) + - sizeof( *classifier->threshold ) + - sizeof( *classifier->left ) + - sizeof( *classifier->right ) ) + - (classifier->count + 1) * sizeof( *classifier->alpha ) ); - classifier->threshold = (float*) (classifier->haar_feature+classifier->count); - classifier->left = (int*) (classifier->threshold + classifier->count); - classifier->right = (int*) (classifier->left + classifier->count); - classifier->alpha = (float*) (classifier->right + classifier->count); - - for( l = 0; l < classifier->count; l++ ) - { - sscanf( stage, "%d%n", &rects, &dl ); - stage += dl; - - CV_Assert( rects >= 2 && rects <= CV_HAAR_FEATURE_MAX ); - - for( k = 0; k < rects; k++ ) - { - cv::Rect r; - int band = 0; - sscanf( stage, "%d%d%d%d%d%f%n", - &r.x, &r.y, &r.width, &r.height, &band, - &(classifier->haar_feature[l].rect[k].weight), &dl ); - stage += dl; - classifier->haar_feature[l].rect[k].r = cvRect(r); - } - sscanf( stage, "%99s%n", str, &dl ); - stage += dl; - - classifier->haar_feature[l].tilted = strncmp( str, "tilted", 6 ) == 0; - - for( k = rects; k < CV_HAAR_FEATURE_MAX; k++ ) - { - memset( classifier->haar_feature[l].rect + k, 0, - sizeof(classifier->haar_feature[l].rect[k]) ); - } - - sscanf( stage, "%f%d%d%n", &(classifier->threshold[l]), - &(classifier->left[l]), - &(classifier->right[l]), &dl ); - stage += dl; - } - for( l = 0; l <= classifier->count; l++ ) - { - sscanf( stage, "%f%n", &(classifier->alpha[l]), &dl ); - stage += dl; - } - } - - sscanf( stage, "%f%n", &threshold, &dl ); - stage += dl; - - cascade->stage_classifier[i].threshold = threshold; - - /* load tree links */ - if( sscanf( stage, "%d%d%n", &parent, &next, &dl ) != 2 ) - { - parent = i - 1; - next = -1; - } - stage += dl; - - CV_Assert(parent >= 0 && parent < i); - cascade->stage_classifier[i].parent = parent; - cascade->stage_classifier[i].next = next; - cascade->stage_classifier[i].child = -1; - - if( parent != -1 && cascade->stage_classifier[parent].child == -1 ) - { - cascade->stage_classifier[parent].child = i; - } - } - - return cascade; -} - -#ifndef _MAX_PATH -#define _MAX_PATH 1024 -#endif - -CV_IMPL CvHaarClassifierCascade* -cvLoadHaarClassifierCascade( const char* directory, CvSize orig_window_size ) -{ - if( !directory ) - CV_Error( CV_StsNullPtr, "Null path is passed" ); - - char name[_MAX_PATH]; - - int n = (int)strlen(directory)-1; - const char* slash = directory[n] == '\\' || directory[n] == '/' ? "" : "/"; - int size = 0; - - /* try to read the classifier from directory */ - for( n = 0; ; n++ ) - { - sprintf( name, "%s%s%d/AdaBoostCARTHaarClassifier.txt", directory, slash, n ); - FILE* f = fopen( name, "rb" ); - if( !f ) - break; - fseek( f, 0, SEEK_END ); - size += ftell( f ) + 1; - fclose(f); - } - - if( n == 0 && slash[0] ) - return (CvHaarClassifierCascade*)cvLoad( directory ); - - if( n == 0 ) - CV_Error( CV_StsBadArg, "Invalid path" ); - - size += (n+1)*sizeof(char*); - const char** input_cascade = (const char**)cvAlloc( size ); - - if( !input_cascade ) - CV_Error( CV_StsNoMem, "Could not allocate memory for input_cascade" ); - - char* ptr = (char*)(input_cascade + n + 1); - - for( int i = 0; i < n; i++ ) - { - sprintf( name, "%s/%d/AdaBoostCARTHaarClassifier.txt", directory, i ); - FILE* f = fopen( name, "rb" ); - if( !f ) - CV_Error( CV_StsError, "" ); - fseek( f, 0, SEEK_END ); - size = (int)ftell( f ); - fseek( f, 0, SEEK_SET ); - size_t elements_read = fread( ptr, 1, size, f ); - CV_Assert(elements_read == (size_t)(size)); - fclose(f); - input_cascade[i] = ptr; - ptr += size; - *ptr++ = '\0'; - } - - input_cascade[n] = 0; - - CvHaarClassifierCascade* cascade = icvLoadCascadeCART( input_cascade, n, orig_window_size ); - - if( input_cascade ) - cvFree( &input_cascade ); - - return cascade; -} - -/****************************************************************************************\ -* Persistence functions * -\****************************************************************************************/ - -/* 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" - -static int -icvIsHaarClassifier( const void* struct_ptr ) -{ - return CV_IS_HAAR_CLASSIFIER( struct_ptr ); -} - -static CvHaarClassifierCascade* -icvCreateHaarClassifierCascade( int stage_count ) -{ - CvHaarClassifierCascade* cascade = 0; - - int block_size = sizeof(*cascade) + stage_count*sizeof(*cascade->stage_classifier); - - if( stage_count <= 0 ) - CV_Error( CV_StsOutOfRange, "Number of stages should be positive" ); - - cascade = (CvHaarClassifierCascade*)cvAlloc( block_size ); - memset( cascade, 0, block_size ); - - cascade->stage_classifier = (CvHaarStageClassifier*)(cascade + 1); - cascade->flags = CV_HAAR_MAGIC_VAL; - cascade->count = stage_count; - - return cascade; -} - -static void* -icvReadHaarClassifier( CvFileStorage* fs, CvFileNode* node ) -{ - CvHaarClassifierCascade* cascade = NULL; - - char buf[256]; - CvFileNode* seq_fn = NULL; /* sequence */ - CvFileNode* fn = NULL; - CvFileNode* stages_fn = NULL; - CvSeqReader stages_reader; - int n; - int i, j, k, l; - int parent, next; - - stages_fn = cvGetFileNodeByName( fs, node, ICV_HAAR_STAGES_NAME ); - if( !stages_fn || !CV_NODE_IS_SEQ( stages_fn->tag) ) - CV_Error( CV_StsError, "Invalid stages node" ); - - n = stages_fn->data.seq->total; - cascade = icvCreateHaarClassifierCascade(n); - - /* read size */ - seq_fn = cvGetFileNodeByName( fs, node, ICV_HAAR_SIZE_NAME ); - if( !seq_fn || !CV_NODE_IS_SEQ( seq_fn->tag ) || seq_fn->data.seq->total != 2 ) - CV_Error( CV_StsError, "size node is not a valid sequence." ); - fn = (CvFileNode*) cvGetSeqElem( seq_fn->data.seq, 0 ); - if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i <= 0 ) - CV_Error( CV_StsError, "Invalid size node: width must be positive integer" ); - cascade->orig_window_size.width = fn->data.i; - fn = (CvFileNode*) cvGetSeqElem( seq_fn->data.seq, 1 ); - if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i <= 0 ) - CV_Error( CV_StsError, "Invalid size node: height must be positive integer" ); - cascade->orig_window_size.height = fn->data.i; - - cvStartReadSeq( stages_fn->data.seq, &stages_reader ); - for( i = 0; i < n; ++i ) - { - CvFileNode* stage_fn; - CvFileNode* trees_fn; - CvSeqReader trees_reader; - - stage_fn = (CvFileNode*) stages_reader.ptr; - if( !CV_NODE_IS_MAP( stage_fn->tag ) ) - { - sprintf( buf, "Invalid stage %d", i ); - CV_Error( CV_StsError, buf ); - } - - trees_fn = cvGetFileNodeByName( fs, stage_fn, ICV_HAAR_TREES_NAME ); - if( !trees_fn || !CV_NODE_IS_SEQ( trees_fn->tag ) - || trees_fn->data.seq->total <= 0 ) - { - sprintf( buf, "Trees node is not a valid sequence. (stage %d)", i ); - CV_Error( CV_StsError, buf ); - } - - cascade->stage_classifier[i].classifier = - (CvHaarClassifier*) cvAlloc( trees_fn->data.seq->total - * sizeof( cascade->stage_classifier[i].classifier[0] ) ); - for( j = 0; j < trees_fn->data.seq->total; ++j ) - { - cascade->stage_classifier[i].classifier[j].haar_feature = NULL; - } - cascade->stage_classifier[i].count = trees_fn->data.seq->total; - - cvStartReadSeq( trees_fn->data.seq, &trees_reader ); - for( j = 0; j < trees_fn->data.seq->total; ++j ) - { - CvFileNode* tree_fn; - CvSeqReader tree_reader; - CvHaarClassifier* classifier; - int last_idx; - - classifier = &cascade->stage_classifier[i].classifier[j]; - tree_fn = (CvFileNode*) trees_reader.ptr; - if( !CV_NODE_IS_SEQ( tree_fn->tag ) || tree_fn->data.seq->total <= 0 ) - { - sprintf( buf, "Tree node is not a valid sequence." - " (stage %d, tree %d)", i, j ); - CV_Error( CV_StsError, buf ); - } - - classifier->count = tree_fn->data.seq->total; - classifier->haar_feature = (CvHaarFeature*) cvAlloc( - classifier->count * ( sizeof( *classifier->haar_feature ) + - sizeof( *classifier->threshold ) + - sizeof( *classifier->left ) + - sizeof( *classifier->right ) ) + - (classifier->count + 1) * sizeof( *classifier->alpha ) ); - classifier->threshold = (float*) (classifier->haar_feature+classifier->count); - classifier->left = (int*) (classifier->threshold + classifier->count); - classifier->right = (int*) (classifier->left + classifier->count); - classifier->alpha = (float*) (classifier->right + classifier->count); - - cvStartReadSeq( tree_fn->data.seq, &tree_reader ); - for( k = 0, last_idx = 0; k < tree_fn->data.seq->total; ++k ) - { - CvFileNode* node_fn; - CvFileNode* feature_fn; - CvFileNode* rects_fn; - CvSeqReader rects_reader; - - node_fn = (CvFileNode*) tree_reader.ptr; - if( !CV_NODE_IS_MAP( node_fn->tag ) ) - { - sprintf( buf, "Tree node %d is not a valid map. (stage %d, tree %d)", - k, i, j ); - CV_Error( CV_StsError, buf ); - } - feature_fn = cvGetFileNodeByName( fs, node_fn, ICV_HAAR_FEATURE_NAME ); - if( !feature_fn || !CV_NODE_IS_MAP( feature_fn->tag ) ) - { - sprintf( buf, "Feature node is not a valid map. " - "(stage %d, tree %d, node %d)", i, j, k ); - CV_Error( CV_StsError, buf ); - } - rects_fn = cvGetFileNodeByName( fs, feature_fn, ICV_HAAR_RECTS_NAME ); - if( !rects_fn || !CV_NODE_IS_SEQ( rects_fn->tag ) - || rects_fn->data.seq->total < 1 - || rects_fn->data.seq->total > CV_HAAR_FEATURE_MAX ) - { - sprintf( buf, "Rects node is not a valid sequence. " - "(stage %d, tree %d, node %d)", i, j, k ); - CV_Error( CV_StsError, buf ); - } - cvStartReadSeq( rects_fn->data.seq, &rects_reader ); - for( l = 0; l < rects_fn->data.seq->total; ++l ) - { - CvFileNode* rect_fn; - cv::Rect r; - - rect_fn = (CvFileNode*) rects_reader.ptr; - if( !CV_NODE_IS_SEQ( rect_fn->tag ) || rect_fn->data.seq->total != 5 ) - { - sprintf( buf, "Rect %d is not a valid sequence. " - "(stage %d, tree %d, node %d)", l, i, j, k ); - CV_Error( CV_StsError, buf ); - } - - fn = CV_SEQ_ELEM( rect_fn->data.seq, CvFileNode, 0 ); - if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i < 0 ) - { - sprintf( buf, "x coordinate must be non-negative integer. " - "(stage %d, tree %d, node %d, rect %d)", i, j, k, l ); - CV_Error( CV_StsError, buf ); - } - r.x = fn->data.i; - fn = CV_SEQ_ELEM( rect_fn->data.seq, CvFileNode, 1 ); - if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i < 0 ) - { - sprintf( buf, "y coordinate must be non-negative integer. " - "(stage %d, tree %d, node %d, rect %d)", i, j, k, l ); - CV_Error( CV_StsError, buf ); - } - r.y = fn->data.i; - fn = CV_SEQ_ELEM( rect_fn->data.seq, CvFileNode, 2 ); - if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i <= 0 - || r.x + fn->data.i > cascade->orig_window_size.width ) - { - sprintf( buf, "width must be positive integer and " - "(x + width) must not exceed window width. " - "(stage %d, tree %d, node %d, rect %d)", i, j, k, l ); - CV_Error( CV_StsError, buf ); - } - r.width = fn->data.i; - fn = CV_SEQ_ELEM( rect_fn->data.seq, CvFileNode, 3 ); - if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i <= 0 - || r.y + fn->data.i > cascade->orig_window_size.height ) - { - sprintf( buf, "height must be positive integer and " - "(y + height) must not exceed window height. " - "(stage %d, tree %d, node %d, rect %d)", i, j, k, l ); - CV_Error( CV_StsError, buf ); - } - r.height = fn->data.i; - fn = CV_SEQ_ELEM( rect_fn->data.seq, CvFileNode, 4 ); - if( !CV_NODE_IS_REAL( fn->tag ) ) - { - sprintf( buf, "weight must be real number. " - "(stage %d, tree %d, node %d, rect %d)", i, j, k, l ); - CV_Error( CV_StsError, buf ); - } - - classifier->haar_feature[k].rect[l].weight = (float) fn->data.f; - classifier->haar_feature[k].rect[l].r = cvRect(r); - - CV_NEXT_SEQ_ELEM( sizeof( *rect_fn ), rects_reader ); - } /* for each rect */ - for( l = rects_fn->data.seq->total; l < CV_HAAR_FEATURE_MAX; ++l ) - { - classifier->haar_feature[k].rect[l].weight = 0; - classifier->haar_feature[k].rect[l].r = cvRect( 0, 0, 0, 0 ); - } - - fn = cvGetFileNodeByName( fs, feature_fn, ICV_HAAR_TILTED_NAME); - if( !fn || !CV_NODE_IS_INT( fn->tag ) ) - { - sprintf( buf, "tilted must be 0 or 1. " - "(stage %d, tree %d, node %d)", i, j, k ); - CV_Error( CV_StsError, buf ); - } - classifier->haar_feature[k].tilted = ( fn->data.i != 0 ); - fn = cvGetFileNodeByName( fs, node_fn, ICV_HAAR_THRESHOLD_NAME); - if( !fn || !CV_NODE_IS_REAL( fn->tag ) ) - { - sprintf( buf, "threshold must be real number. " - "(stage %d, tree %d, node %d)", i, j, k ); - CV_Error( CV_StsError, buf ); - } - classifier->threshold[k] = (float) fn->data.f; - fn = cvGetFileNodeByName( fs, node_fn, ICV_HAAR_LEFT_NODE_NAME); - if( fn ) - { - if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i <= k - || fn->data.i >= tree_fn->data.seq->total ) - { - sprintf( buf, "left node must be valid node number. " - "(stage %d, tree %d, node %d)", i, j, k ); - CV_Error( CV_StsError, buf ); - } - /* left node */ - classifier->left[k] = fn->data.i; - } - else - { - fn = cvGetFileNodeByName( fs, node_fn, ICV_HAAR_LEFT_VAL_NAME ); - if( !fn ) - { - sprintf( buf, "left node or left value must be specified. " - "(stage %d, tree %d, node %d)", i, j, k ); - CV_Error( CV_StsError, buf ); - } - if( !CV_NODE_IS_REAL( fn->tag ) ) - { - sprintf( buf, "left value must be real number. " - "(stage %d, tree %d, node %d)", i, j, k ); - CV_Error( CV_StsError, buf ); - } - /* left value */ - if( last_idx >= classifier->count + 1 ) - { - sprintf( buf, "Tree structure is broken: too many values. " - "(stage %d, tree %d, node %d)", i, j, k ); - CV_Error( CV_StsError, buf ); - } - classifier->left[k] = -last_idx; - classifier->alpha[last_idx++] = (float) fn->data.f; - } - fn = cvGetFileNodeByName( fs, node_fn,ICV_HAAR_RIGHT_NODE_NAME); - if( fn ) - { - if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i <= k - || fn->data.i >= tree_fn->data.seq->total ) - { - sprintf( buf, "right node must be valid node number. " - "(stage %d, tree %d, node %d)", i, j, k ); - CV_Error( CV_StsError, buf ); - } - /* right node */ - classifier->right[k] = fn->data.i; - } - else - { - fn = cvGetFileNodeByName( fs, node_fn, ICV_HAAR_RIGHT_VAL_NAME ); - if( !fn ) - { - sprintf( buf, "right node or right value must be specified. " - "(stage %d, tree %d, node %d)", i, j, k ); - CV_Error( CV_StsError, buf ); - } - if( !CV_NODE_IS_REAL( fn->tag ) ) - { - sprintf( buf, "right value must be real number. " - "(stage %d, tree %d, node %d)", i, j, k ); - CV_Error( CV_StsError, buf ); - } - /* right value */ - if( last_idx >= classifier->count + 1 ) - { - sprintf( buf, "Tree structure is broken: too many values. " - "(stage %d, tree %d, node %d)", i, j, k ); - CV_Error( CV_StsError, buf ); - } - classifier->right[k] = -last_idx; - classifier->alpha[last_idx++] = (float) fn->data.f; - } - - CV_NEXT_SEQ_ELEM( sizeof( *node_fn ), tree_reader ); - } /* for each node */ - if( last_idx != classifier->count + 1 ) - { - sprintf( buf, "Tree structure is broken: too few values. " - "(stage %d, tree %d)", i, j ); - CV_Error( CV_StsError, buf ); - } - - CV_NEXT_SEQ_ELEM( sizeof( *tree_fn ), trees_reader ); - } /* for each tree */ - - fn = cvGetFileNodeByName( fs, stage_fn, ICV_HAAR_STAGE_THRESHOLD_NAME); - if( !fn || !CV_NODE_IS_REAL( fn->tag ) ) - { - sprintf( buf, "stage threshold must be real number. (stage %d)", i ); - CV_Error( CV_StsError, buf ); - } - cascade->stage_classifier[i].threshold = (float) fn->data.f; - - parent = i - 1; - next = -1; - - fn = cvGetFileNodeByName( fs, stage_fn, ICV_HAAR_PARENT_NAME ); - if( !fn || !CV_NODE_IS_INT( fn->tag ) - || fn->data.i < -1 || fn->data.i >= cascade->count ) - { - sprintf( buf, "parent must be integer number. (stage %d)", i ); - CV_Error( CV_StsError, buf ); - } - parent = fn->data.i; - fn = cvGetFileNodeByName( fs, stage_fn, ICV_HAAR_NEXT_NAME ); - if( !fn || !CV_NODE_IS_INT( fn->tag ) - || fn->data.i < -1 || fn->data.i >= cascade->count ) - { - sprintf( buf, "next must be integer number. (stage %d)", i ); - CV_Error( CV_StsError, buf ); - } - next = fn->data.i; - - cascade->stage_classifier[i].parent = parent; - cascade->stage_classifier[i].next = next; - cascade->stage_classifier[i].child = -1; - - if( parent != -1 && cascade->stage_classifier[parent].child == -1 ) - { - cascade->stage_classifier[parent].child = i; - } - - CV_NEXT_SEQ_ELEM( sizeof( *stage_fn ), stages_reader ); - } /* for each stage */ - - return cascade; -} - -static void -icvWriteHaarClassifier( CvFileStorage* fs, const char* name, const void* struct_ptr, - CvAttrList attributes ) -{ - int i, j, k, l; - char buf[256]; - const CvHaarClassifierCascade* cascade = (const CvHaarClassifierCascade*) struct_ptr; - - /* TODO: parameters check */ - - cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_HAAR, attributes ); - - cvStartWriteStruct( fs, ICV_HAAR_SIZE_NAME, CV_NODE_SEQ | CV_NODE_FLOW ); - cvWriteInt( fs, NULL, cascade->orig_window_size.width ); - cvWriteInt( fs, NULL, cascade->orig_window_size.height ); - cvEndWriteStruct( fs ); /* size */ - - cvStartWriteStruct( fs, ICV_HAAR_STAGES_NAME, CV_NODE_SEQ ); - for( i = 0; i < cascade->count; ++i ) - { - cvStartWriteStruct( fs, NULL, CV_NODE_MAP ); - sprintf( buf, "stage %d", i ); - cvWriteComment( fs, buf, 1 ); - - cvStartWriteStruct( fs, ICV_HAAR_TREES_NAME, CV_NODE_SEQ ); - - for( j = 0; j < cascade->stage_classifier[i].count; ++j ) - { - CvHaarClassifier* tree = &cascade->stage_classifier[i].classifier[j]; - - cvStartWriteStruct( fs, NULL, CV_NODE_SEQ ); - sprintf( buf, "tree %d", j ); - cvWriteComment( fs, buf, 1 ); - - for( k = 0; k < tree->count; ++k ) - { - CvHaarFeature* feature = &tree->haar_feature[k]; - - cvStartWriteStruct( fs, NULL, CV_NODE_MAP ); - if( k ) - { - sprintf( buf, "node %d", k ); - } - else - { - sprintf( buf, "root node" ); - } - cvWriteComment( fs, buf, 1 ); - - cvStartWriteStruct( fs, ICV_HAAR_FEATURE_NAME, CV_NODE_MAP ); - - cvStartWriteStruct( fs, ICV_HAAR_RECTS_NAME, CV_NODE_SEQ ); - for( l = 0; l < CV_HAAR_FEATURE_MAX && feature->rect[l].r.width != 0; ++l ) - { - cvStartWriteStruct( fs, NULL, CV_NODE_SEQ | CV_NODE_FLOW ); - cvWriteInt( fs, NULL, feature->rect[l].r.x ); - cvWriteInt( fs, NULL, feature->rect[l].r.y ); - cvWriteInt( fs, NULL, feature->rect[l].r.width ); - cvWriteInt( fs, NULL, feature->rect[l].r.height ); - cvWriteReal( fs, NULL, feature->rect[l].weight ); - cvEndWriteStruct( fs ); /* rect */ - } - cvEndWriteStruct( fs ); /* rects */ - cvWriteInt( fs, ICV_HAAR_TILTED_NAME, feature->tilted ); - cvEndWriteStruct( fs ); /* feature */ - - cvWriteReal( fs, ICV_HAAR_THRESHOLD_NAME, tree->threshold[k]); - - if( tree->left[k] > 0 ) - { - cvWriteInt( fs, ICV_HAAR_LEFT_NODE_NAME, tree->left[k] ); - } - else - { - cvWriteReal( fs, ICV_HAAR_LEFT_VAL_NAME, - tree->alpha[-tree->left[k]] ); - } - - if( tree->right[k] > 0 ) - { - cvWriteInt( fs, ICV_HAAR_RIGHT_NODE_NAME, tree->right[k] ); - } - else - { - cvWriteReal( fs, ICV_HAAR_RIGHT_VAL_NAME, - tree->alpha[-tree->right[k]] ); - } - - cvEndWriteStruct( fs ); /* split */ - } - - cvEndWriteStruct( fs ); /* tree */ - } - - cvEndWriteStruct( fs ); /* trees */ - - cvWriteReal( fs, ICV_HAAR_STAGE_THRESHOLD_NAME, cascade->stage_classifier[i].threshold); - cvWriteInt( fs, ICV_HAAR_PARENT_NAME, cascade->stage_classifier[i].parent ); - cvWriteInt( fs, ICV_HAAR_NEXT_NAME, cascade->stage_classifier[i].next ); - - cvEndWriteStruct( fs ); /* stage */ - } /* for each stage */ - - cvEndWriteStruct( fs ); /* stages */ - cvEndWriteStruct( fs ); /* root */ -} - -static void* -icvCloneHaarClassifier( const void* struct_ptr ) -{ - CvHaarClassifierCascade* cascade = NULL; - - int i, j, k, n; - const CvHaarClassifierCascade* cascade_src = - (const CvHaarClassifierCascade*) struct_ptr; - - n = cascade_src->count; - cascade = icvCreateHaarClassifierCascade(n); - cascade->orig_window_size = cascade_src->orig_window_size; - - for( i = 0; i < n; ++i ) - { - cascade->stage_classifier[i].parent = cascade_src->stage_classifier[i].parent; - cascade->stage_classifier[i].next = cascade_src->stage_classifier[i].next; - cascade->stage_classifier[i].child = cascade_src->stage_classifier[i].child; - cascade->stage_classifier[i].threshold = cascade_src->stage_classifier[i].threshold; - - cascade->stage_classifier[i].count = 0; - cascade->stage_classifier[i].classifier = - (CvHaarClassifier*) cvAlloc( cascade_src->stage_classifier[i].count - * sizeof( cascade->stage_classifier[i].classifier[0] ) ); - - cascade->stage_classifier[i].count = cascade_src->stage_classifier[i].count; - - for( j = 0; j < cascade->stage_classifier[i].count; ++j ) - cascade->stage_classifier[i].classifier[j].haar_feature = NULL; - - for( j = 0; j < cascade->stage_classifier[i].count; ++j ) - { - const CvHaarClassifier* classifier_src = - &cascade_src->stage_classifier[i].classifier[j]; - CvHaarClassifier* classifier = - &cascade->stage_classifier[i].classifier[j]; - - classifier->count = classifier_src->count; - classifier->haar_feature = (CvHaarFeature*) cvAlloc( - classifier->count * ( sizeof( *classifier->haar_feature ) + - sizeof( *classifier->threshold ) + - sizeof( *classifier->left ) + - sizeof( *classifier->right ) ) + - (classifier->count + 1) * sizeof( *classifier->alpha ) ); - classifier->threshold = (float*) (classifier->haar_feature+classifier->count); - classifier->left = (int*) (classifier->threshold + classifier->count); - classifier->right = (int*) (classifier->left + classifier->count); - classifier->alpha = (float*) (classifier->right + classifier->count); - for( k = 0; k < classifier->count; ++k ) - { - classifier->haar_feature[k] = classifier_src->haar_feature[k]; - classifier->threshold[k] = classifier_src->threshold[k]; - classifier->left[k] = classifier_src->left[k]; - classifier->right[k] = classifier_src->right[k]; - classifier->alpha[k] = classifier_src->alpha[k]; - } - classifier->alpha[classifier->count] = - classifier_src->alpha[classifier->count]; - } - } - - return cascade; -} - - -CvType haar_type( CV_TYPE_NAME_HAAR, icvIsHaarClassifier, - (CvReleaseFunc)cvReleaseHaarClassifierCascade, - icvReadHaarClassifier, icvWriteHaarClassifier, - icvCloneHaarClassifier ); - -#endif - -/* End of file. */ diff --git a/modules/objdetect/src/haar.hpp b/modules/objdetect/src/haar.hpp deleted file mode 100644 index 72a0af451d..0000000000 --- a/modules/objdetect/src/haar.hpp +++ /dev/null @@ -1,101 +0,0 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// Intel License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000, Intel Corporation, 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 */ - -#ifndef OPENCV_OBJDETECT_HAAR_HPP -#define OPENCV_OBJDETECT_HAAR_HPP - -#define CV_HAAR_FEATURE_MAX_LOCAL 3 - -typedef int sumtype; -typedef double sqsumtype; - -typedef struct CvHidHaarFeature -{ - struct - { - sumtype *p0, *p1, *p2, *p3; - float weight; - } - rect[CV_HAAR_FEATURE_MAX_LOCAL]; -} CvHidHaarFeature; - - -typedef struct CvHidHaarTreeNode -{ - CvHidHaarFeature feature; - float threshold; - int left; - int right; -} CvHidHaarTreeNode; - - -typedef struct CvHidHaarClassifier -{ - int count; - //CvHaarFeature* orig_feature; - CvHidHaarTreeNode* node; - float* alpha; -} CvHidHaarClassifier; - -#define calc_sumf(rect,offset) \ - static_cast((rect).p0[offset] - (rect).p1[offset] - (rect).p2[offset] + (rect).p3[offset]) - -namespace cv_haar_avx -{ -#if 0 /*CV_TRY_AVX*/ - #define CV_HAAR_USE_AVX 1 -#else - #define CV_HAAR_USE_AVX 0 -#endif - -#if CV_HAAR_USE_AVX - // AVX version icvEvalHidHaarClassifier. Process 8 CvHidHaarClassifiers per call. Check AVX support before invocation!! - double icvEvalHidHaarClassifierAVX(CvHidHaarClassifier* classifier, double variance_norm_factor, size_t p_offset); - double icvEvalHidHaarStumpClassifierAVX(CvHidHaarClassifier* classifier, double variance_norm_factor, size_t p_offset); - double icvEvalHidHaarStumpClassifierTwoRectAVX(CvHidHaarClassifier* classifier, double variance_norm_factor, size_t p_offset); -#endif -} - -#endif - -/* End of file. */ diff --git a/modules/objdetect/test/test_cascadeandhog.cpp b/modules/objdetect/test/test_cascadeandhog.cpp index 8164614bb3..27a49620c4 100644 --- a/modules/objdetect/test/test_cascadeandhog.cpp +++ b/modules/objdetect/test/test_cascadeandhog.cpp @@ -404,7 +404,6 @@ protected: virtual void readDetector( const FileNode& fn ); virtual void writeDetector( FileStorage& fs, int di ); virtual int detectMultiScale( int di, const Mat& img, vector& objects ); - virtual int detectMultiScale_C( const string& filename, int di, const Mat& img, vector& objects ); vector flags; }; @@ -434,36 +433,6 @@ void CV_CascadeDetectorTest::writeDetector( FileStorage& fs, int di ) fs << C_SCALE_CASCADE << sc; } - -int CV_CascadeDetectorTest::detectMultiScale_C( const string& filename, - int di, const Mat& img, - vector& objects ) -{ - Ptr c_cascade(cvLoadHaarClassifierCascade(filename.c_str(), cvSize(0,0))); - Ptr storage(cvCreateMemStorage()); - - if( !c_cascade ) - { - ts->printf( cvtest::TS::LOG, "cascade %s can not be opened"); - return cvtest::TS::FAIL_INVALID_TEST_DATA; - } - Mat grayImg; - cvtColor( img, grayImg, COLOR_BGR2GRAY ); - equalizeHist( grayImg, grayImg ); - - CvMat c_gray = cvMat(grayImg); - CvSeq* rs = cvHaarDetectObjects(&c_gray, c_cascade, storage, 1.1, 3, flags[di] ); - - objects.clear(); - for( int i = 0; i < rs->total; i++ ) - { - Rect r = *(Rect*)cvGetSeqElem(rs, i); - objects.push_back(r); - } - - return cvtest::TS::OK; -} - int CV_CascadeDetectorTest::detectMultiScale( int di, const Mat& img, vector& objects) { @@ -471,11 +440,6 @@ int CV_CascadeDetectorTest::detectMultiScale( int di, const Mat& img, filename = dataPath + detectorFilenames[di]; const string pattern = "haarcascade_frontalface_default.xml"; - if( filename.size() >= pattern.size() && - strcmp(filename.c_str() + (filename.size() - pattern.size()), - pattern.c_str()) == 0 ) - return detectMultiScale_C(filename, di, img, objects); - CascadeClassifier cascade( filename ); if( cascade.empty() ) { diff --git a/modules/objdetect/test/test_precomp.hpp b/modules/objdetect/test/test_precomp.hpp index 4131b43995..c53b277aa1 100644 --- a/modules/objdetect/test/test_precomp.hpp +++ b/modules/objdetect/test/test_precomp.hpp @@ -6,6 +6,5 @@ #include "opencv2/ts.hpp" #include "opencv2/objdetect.hpp" -#include "opencv2/objdetect/objdetect_c.h" #endif