Path: blob/master/modules/objdetect/src/detection_based_tracker.cpp
16337 views
/*M///////////////////////////////////////////////////////////////////////////////////////1//2// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.3//4// By downloading, copying, installing or using the software you agree to this license.5// If you do not agree to this license, do not download, install,6// copy or use the software.7//8//9// License Agreement10// For Open Source Computer Vision Library11//12// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.13// Copyright (C) 2009, Willow Garage Inc., all rights reserved.14// Copyright (C) 2013, OpenCV Foundation, all rights reserved.15// Third party copyrights are property of their respective owners.16//17// Redistribution and use in source and binary forms, with or without modification,18// are permitted provided that the following conditions are met:19//20// * Redistribution's of source code must retain the above copyright notice,21// this list of conditions and the following disclaimer.22//23// * Redistribution's in binary form must reproduce the above copyright notice,24// this list of conditions and the following disclaimer in the documentation25// and/or other materials provided with the distribution.26//27// * The name of the copyright holders may not be used to endorse or promote products28// derived from this software without specific prior written permission.29//30// This software is provided by the copyright holders and contributors "as is" and31// any express or implied warranties, including, but not limited to, the implied32// warranties of merchantability and fitness for a particular purpose are disclaimed.33// In no event shall the Intel Corporation or contributors be liable for any direct,34// indirect, incidental, special, exemplary, or consequential damages35// (including, but not limited to, procurement of substitute goods or services;36// loss of use, data, or profits; or business interruption) however caused37// and on any theory of liability, whether in contract, strict liability,38// or tort (including negligence or otherwise) arising in any way out of39// the use of this software, even if advised of the possibility of such damage.40//41//M*/4243#include "precomp.hpp"4445#include "opencv2/core/utility.hpp"4647#include <thread>48#include <mutex>49#include <condition_variable>5051#if defined(DEBUG) || defined(_DEBUG)52#undef DEBUGLOGS53#define DEBUGLOGS 154#endif5556#ifndef DEBUGLOGS57#define DEBUGLOGS 058#endif5960#ifdef __ANDROID__61#include <android/log.h>62#define LOG_TAG "OBJECT_DETECTOR"63#define LOGD0(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))64#define LOGI0(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))65#define LOGW0(...) ((void)__android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))66#define LOGE0(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))67#else6869#include <stdio.h>7071#define LOGD0(_str, ...) (printf(_str , ## __VA_ARGS__), printf("\n"), fflush(stdout))72#define LOGI0(_str, ...) (printf(_str , ## __VA_ARGS__), printf("\n"), fflush(stdout))73#define LOGW0(_str, ...) (printf(_str , ## __VA_ARGS__), printf("\n"), fflush(stdout))74#define LOGE0(_str, ...) (printf(_str , ## __VA_ARGS__), printf("\n"), fflush(stdout))75#endif //__ANDROID__7677#if DEBUGLOGS78#define LOGD(_str, ...) LOGD0(_str , ## __VA_ARGS__)79#define LOGI(_str, ...) LOGI0(_str , ## __VA_ARGS__)80#define LOGW(_str, ...) LOGW0(_str , ## __VA_ARGS__)81#define LOGE(_str, ...) LOGE0(_str , ## __VA_ARGS__)82#else83#define LOGD(...)84#define LOGI(...)85#define LOGW(...)86#define LOGE(...)87#endif //DEBUGLOGS888990using namespace cv;9192static inline cv::Point2f centerRect(const cv::Rect& r)93{94return cv::Point2f(r.x+((float)r.width)/2, r.y+((float)r.height)/2);95}9697static inline cv::Rect scale_rect(const cv::Rect& r, float scale)98{99cv::Point2f m=centerRect(r);100float width = r.width * scale;101float height = r.height * scale;102int x=cvRound(m.x - width/2);103int y=cvRound(m.y - height/2);104105return cv::Rect(x, y, cvRound(width), cvRound(height));106}107108namespace cv109{110void* workcycleObjectDetectorFunction(void* p);111}112113class cv::DetectionBasedTracker::SeparateDetectionWork114{115public:116SeparateDetectionWork(cv::DetectionBasedTracker& _detectionBasedTracker, cv::Ptr<DetectionBasedTracker::IDetector> _detector,117const cv::DetectionBasedTracker::Parameters& params);118virtual ~SeparateDetectionWork();119bool communicateWithDetectingThread(const Mat& imageGray, std::vector<Rect>& rectsWhereRegions);120bool run();121void stop();122void resetTracking();123124inline bool isWorking()125{126return (stateThread==STATE_THREAD_WORKING_SLEEPING) || (stateThread==STATE_THREAD_WORKING_WITH_IMAGE);127}128void setParameters(const cv::DetectionBasedTracker::Parameters& params)129{130std::unique_lock<std::mutex> mtx_lock(mtx);131parameters = params;132}133134inline void init()135{136std::unique_lock<std::mutex> mtx_lock(mtx);137stateThread = STATE_THREAD_STOPPED;138isObjectDetectingReady = false;139shouldObjectDetectingResultsBeForgot = false;140objectDetectorThreadStartStop.notify_one();141}142protected:143144DetectionBasedTracker& detectionBasedTracker;145cv::Ptr<DetectionBasedTracker::IDetector> cascadeInThread;146std::thread second_workthread;147std::mutex mtx;148std::condition_variable objectDetectorRun;149std::condition_variable objectDetectorThreadStartStop;150std::vector<cv::Rect> resultDetect;151volatile bool isObjectDetectingReady;152volatile bool shouldObjectDetectingResultsBeForgot;153154enum StateSeparatedThread {155STATE_THREAD_STOPPED=0,156STATE_THREAD_WORKING_SLEEPING,157STATE_THREAD_WORKING_WITH_IMAGE,158STATE_THREAD_WORKING,159STATE_THREAD_STOPPING160};161volatile StateSeparatedThread stateThread;162163cv::Mat imageSeparateDetecting;164165void workcycleObjectDetector();166friend void* workcycleObjectDetectorFunction(void* p);167168long long timeWhenDetectingThreadStartedWork;169cv::DetectionBasedTracker::Parameters parameters;170};171172cv::DetectionBasedTracker::SeparateDetectionWork::SeparateDetectionWork(DetectionBasedTracker& _detectionBasedTracker, cv::Ptr<DetectionBasedTracker::IDetector> _detector,173const cv::DetectionBasedTracker::Parameters& params)174:detectionBasedTracker(_detectionBasedTracker),175cascadeInThread(),176isObjectDetectingReady(false),177shouldObjectDetectingResultsBeForgot(false),178stateThread(STATE_THREAD_STOPPED),179timeWhenDetectingThreadStartedWork(-1),180parameters(params)181{182CV_Assert(_detector);183184cascadeInThread = _detector;185}186187cv::DetectionBasedTracker::SeparateDetectionWork::~SeparateDetectionWork()188{189if(stateThread!=STATE_THREAD_STOPPED) {190LOGE("\n\n\nATTENTION!!! dangerous algorithm error: destructor DetectionBasedTracker::DetectionBasedTracker::~SeparateDetectionWork is called before stopping the workthread");191}192second_workthread.join();193}194bool cv::DetectionBasedTracker::SeparateDetectionWork::run()195{196LOGD("DetectionBasedTracker::SeparateDetectionWork::run() --- start");197std::unique_lock<std::mutex> mtx_lock(mtx);198// unlocked when leaving scope199if (stateThread != STATE_THREAD_STOPPED) {200LOGE("DetectionBasedTracker::SeparateDetectionWork::run is called while the previous run is not stopped");201return false;202}203stateThread=STATE_THREAD_WORKING_SLEEPING;204second_workthread = std::thread(workcycleObjectDetectorFunction, (void*)this); //TODO: add attributes?205objectDetectorThreadStartStop.wait(mtx_lock);206LOGD("DetectionBasedTracker::SeparateDetectionWork::run --- end");207return true;208}209210#define CATCH_ALL_AND_LOG(_block) \211CV_TRY { \212_block; \213} \214CV_CATCH(cv::Exception, e) { \215LOGE0("\n %s: ERROR: OpenCV Exception caught: \n'%s'\n\n", CV_Func, e.what()); \216} CV_CATCH(std::exception, e) { \217LOGE0("\n %s: ERROR: Exception caught: \n'%s'\n\n", CV_Func, e.what()); \218} CV_CATCH_ALL { \219LOGE0("\n %s: ERROR: UNKNOWN Exception caught\n\n", CV_Func); \220}221222void* cv::workcycleObjectDetectorFunction(void* p)223{224CATCH_ALL_AND_LOG({ ((cv::DetectionBasedTracker::SeparateDetectionWork*)p)->workcycleObjectDetector(); });225CV_TRY{226((cv::DetectionBasedTracker::SeparateDetectionWork*)p)->init();227} CV_CATCH_ALL {228LOGE0("DetectionBasedTracker: workcycleObjectDetectorFunction: ERROR concerning pointer, received as the function parameter");229}230return NULL;231}232233void cv::DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector()234{235static double freq = getTickFrequency();236LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- start");237std::vector<Rect> objects;238239CV_Assert(stateThread==STATE_THREAD_WORKING_SLEEPING);240std::unique_lock<std::mutex> mtx_lock(mtx);241{242objectDetectorThreadStartStop.notify_one();243LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- before waiting");244CV_Assert(stateThread==STATE_THREAD_WORKING_SLEEPING);245objectDetectorRun.wait(mtx_lock);246if (isWorking()) {247stateThread=STATE_THREAD_WORKING_WITH_IMAGE;248}249LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- after waiting");250}251mtx_lock.unlock();252253bool isFirstStep=true;254255isObjectDetectingReady=false;256257while(isWorking())258{259LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- next step");260261if (! isFirstStep) {262LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- before waiting");263CV_Assert(stateThread==STATE_THREAD_WORKING_SLEEPING);264mtx_lock.lock();265if (!isWorking()) {//it is a rare case, but may cause a crash266LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- go out from the workcycle from inner part of lock just before waiting");267mtx_lock.unlock();268break;269}270CV_Assert(stateThread==STATE_THREAD_WORKING_SLEEPING);271objectDetectorRun.wait(mtx_lock);272if (isWorking()) {273stateThread=STATE_THREAD_WORKING_WITH_IMAGE;274}275mtx_lock.unlock();276277LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- after waiting");278} else {279isFirstStep=false;280}281282if (!isWorking()) {283LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- go out from the workcycle just after waiting");284break;285}286287288if (imageSeparateDetecting.empty()) {289LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- imageSeparateDetecting is empty, continue");290continue;291}292LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- start handling imageSeparateDetecting, img.size=%dx%d, img.data=0x%p",293imageSeparateDetecting.size().width, imageSeparateDetecting.size().height, (void*)imageSeparateDetecting.data);294295296int64 t1_detect=getTickCount();297298cascadeInThread->detect(imageSeparateDetecting, objects);299300/*cascadeInThread.detectMultiScale( imageSeparateDetecting, objects,301detectionBasedTracker.parameters.scaleFactor, detectionBasedTracker.parameters.minNeighbors, 0302|CV_HAAR_SCALE_IMAGE303,304min_objectSize,305max_objectSize306);307*/308309LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- end handling imageSeparateDetecting");310311if (!isWorking()) {312LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- go out from the workcycle just after detecting");313break;314}315316int64 t2_detect = getTickCount();317int64 dt_detect = t2_detect-t1_detect;318double dt_detect_ms=((double)dt_detect)/freq * 1000.0;319(void)(dt_detect_ms);320321LOGI("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- objects num==%d, t_ms=%.4f", (int)objects.size(), dt_detect_ms);322mtx_lock.lock();323if (!shouldObjectDetectingResultsBeForgot) {324resultDetect=objects;325isObjectDetectingReady=true;326} else { //shouldObjectDetectingResultsBeForgot==true327resultDetect.clear();328isObjectDetectingReady=false;329shouldObjectDetectingResultsBeForgot=false;330}331if(isWorking()) {332stateThread=STATE_THREAD_WORKING_SLEEPING;333}334mtx_lock.unlock();335336objects.clear();337}// while(isWorking())338339LOGI("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector: Returning");340}341342void cv::DetectionBasedTracker::SeparateDetectionWork::stop()343{344//FIXME: TODO: should add quickStop functionality345std::unique_lock<std::mutex> mtx_lock(mtx);346if (!isWorking()) {347mtx_lock.unlock();348LOGE("SimpleHighguiDemoCore::stop is called but the SimpleHighguiDemoCore pthread is not active");349stateThread = STATE_THREAD_STOPPING;350return;351}352stateThread=STATE_THREAD_STOPPING;353LOGD("DetectionBasedTracker::SeparateDetectionWork::stop: before going to sleep to wait for the signal from the workthread");354objectDetectorRun.notify_one();355objectDetectorThreadStartStop.wait(mtx_lock);356LOGD("DetectionBasedTracker::SeparateDetectionWork::stop: after receiving the signal from the workthread, stateThread=%d", (int)stateThread);357mtx_lock.unlock();358}359360void cv::DetectionBasedTracker::SeparateDetectionWork::resetTracking()361{362LOGD("DetectionBasedTracker::SeparateDetectionWork::resetTracking");363std::unique_lock<std::mutex> mtx_lock(mtx);364365if (stateThread == STATE_THREAD_WORKING_WITH_IMAGE) {366LOGD("DetectionBasedTracker::SeparateDetectionWork::resetTracking: since workthread is detecting objects at the moment, we should make cascadeInThread stop detecting and forget the detecting results");367shouldObjectDetectingResultsBeForgot=true;368//cascadeInThread.setStopFlag();//FIXME: TODO: this feature also should be contributed to OpenCV369} else {370LOGD("DetectionBasedTracker::SeparateDetectionWork::resetTracking: since workthread is NOT detecting objects at the moment, we should NOT make any additional actions");371}372373resultDetect.clear();374isObjectDetectingReady=false;375376mtx_lock.unlock();377}378379bool cv::DetectionBasedTracker::SeparateDetectionWork::communicateWithDetectingThread(const Mat& imageGray, std::vector<Rect>& rectsWhereRegions)380{381static double freq = getTickFrequency();382383bool shouldCommunicateWithDetectingThread = (stateThread==STATE_THREAD_WORKING_SLEEPING);384LOGD("DetectionBasedTracker::SeparateDetectionWork::communicateWithDetectingThread: shouldCommunicateWithDetectingThread=%d", (shouldCommunicateWithDetectingThread?1:0));385386if (!shouldCommunicateWithDetectingThread) {387return false;388}389390bool shouldHandleResult = false;391392std::unique_lock<std::mutex> mtx_lock(mtx);393394if (isObjectDetectingReady) {395shouldHandleResult=true;396rectsWhereRegions = resultDetect;397isObjectDetectingReady=false;398399double lastBigDetectionDuration = 1000.0 * (((double)(getTickCount() - timeWhenDetectingThreadStartedWork )) / freq);400(void)(lastBigDetectionDuration);401LOGD("DetectionBasedTracker::SeparateDetectionWork::communicateWithDetectingThread: lastBigDetectionDuration=%f ms", (double)lastBigDetectionDuration);402}403404bool shouldSendNewDataToWorkThread = true;405if (timeWhenDetectingThreadStartedWork > 0) {406double time_from_previous_launch_in_ms=1000.0 * (((double)(getTickCount() - timeWhenDetectingThreadStartedWork )) / freq); //the same formula as for lastBigDetectionDuration407shouldSendNewDataToWorkThread = (time_from_previous_launch_in_ms >= detectionBasedTracker.parameters.minDetectionPeriod);408LOGD("DetectionBasedTracker::SeparateDetectionWork::communicateWithDetectingThread: shouldSendNewDataToWorkThread was 1, now it is %d, since time_from_previous_launch_in_ms=%.2f, minDetectionPeriod=%d",409(shouldSendNewDataToWorkThread?1:0), time_from_previous_launch_in_ms, detectionBasedTracker.parameters.minDetectionPeriod);410}411412if (shouldSendNewDataToWorkThread) {413414imageSeparateDetecting.create(imageGray.size(), CV_8UC1);415416imageGray.copyTo(imageSeparateDetecting);//may change imageSeparateDetecting ptr. But should not.417418419timeWhenDetectingThreadStartedWork = getTickCount() ;420421objectDetectorRun.notify_one();422}423424mtx_lock.unlock();425LOGD("DetectionBasedTracker::SeparateDetectionWork::communicateWithDetectingThread: result: shouldHandleResult=%d", (shouldHandleResult?1:0));426427return shouldHandleResult;428}429430cv::DetectionBasedTracker::Parameters::Parameters()431{432maxTrackLifetime = 5;433minDetectionPeriod = 0;434}435436cv::DetectionBasedTracker::InnerParameters::InnerParameters()437{438numLastPositionsToTrack=4;439numStepsToWaitBeforeFirstShow=6;440numStepsToTrackWithoutDetectingIfObjectHasNotBeenShown=3;441numStepsToShowWithoutDetecting=3;442443coeffTrackingWindowSize=2.0;444coeffObjectSizeToTrack=0.85f;445coeffObjectSpeedUsingInPrediction=0.8f;446447}448449cv::DetectionBasedTracker::DetectionBasedTracker(cv::Ptr<IDetector> mainDetector, cv::Ptr<IDetector> trackingDetector, const Parameters& params)450:separateDetectionWork(),451parameters(params),452innerParameters(),453numTrackedSteps(0),454cascadeForTracking(trackingDetector)455{456CV_Assert( (params.maxTrackLifetime >= 0)457// && mainDetector458&& trackingDetector );459460if (mainDetector) {461Ptr<SeparateDetectionWork> tmp(new SeparateDetectionWork(*this, mainDetector, params));462separateDetectionWork.swap(tmp);463}464465weightsPositionsSmoothing.push_back(1);466weightsSizesSmoothing.push_back(0.5);467weightsSizesSmoothing.push_back(0.3f);468weightsSizesSmoothing.push_back(0.2f);469}470471cv::DetectionBasedTracker::~DetectionBasedTracker()472{473}474475void DetectionBasedTracker::process(const Mat& imageGray)476{477CV_INSTRUMENT_REGION();478479CV_Assert(imageGray.type()==CV_8UC1);480481if ( separateDetectionWork && !separateDetectionWork->isWorking() ) {482separateDetectionWork->run();483}484485static double freq = getTickFrequency();486static long long time_when_last_call_started=getTickCount();487488{489double delta_time_from_prev_call=1000.0 * (((double)(getTickCount() - time_when_last_call_started)) / freq);490(void)(delta_time_from_prev_call);491LOGD("DetectionBasedTracker::process: time from the previous call is %f ms", (double)delta_time_from_prev_call);492time_when_last_call_started=getTickCount();493}494495Mat imageDetect=imageGray;496497std::vector<Rect> rectsWhereRegions;498bool shouldHandleResult=false;499if (separateDetectionWork) {500shouldHandleResult = separateDetectionWork->communicateWithDetectingThread(imageGray, rectsWhereRegions);501}502503if (shouldHandleResult) {504LOGD("DetectionBasedTracker::process: get _rectsWhereRegions were got from resultDetect");505} else {506LOGD("DetectionBasedTracker::process: get _rectsWhereRegions from previous positions");507for(size_t i = 0; i < trackedObjects.size(); i++) {508size_t n = trackedObjects[i].lastPositions.size();509CV_Assert(n > 0);510511Rect r = trackedObjects[i].lastPositions[n-1];512if(r.empty()) {513LOGE("DetectionBasedTracker::process: ERROR: ATTENTION: strange algorithm's behavior: trackedObjects[i].rect() is empty");514continue;515}516517//correction by speed of rectangle518if (n > 1) {519Point2f center = centerRect(r);520Point2f center_prev = centerRect(trackedObjects[i].lastPositions[n-2]);521Point2f shift = (center - center_prev) * innerParameters.coeffObjectSpeedUsingInPrediction;522523r.x += cvRound(shift.x);524r.y += cvRound(shift.y);525}526527528rectsWhereRegions.push_back(r);529}530}531LOGI("DetectionBasedTracker::process: tracked objects num==%d", (int)trackedObjects.size());532533std::vector<Rect> detectedObjectsInRegions;534535LOGD("DetectionBasedTracker::process: rectsWhereRegions.size()=%d", (int)rectsWhereRegions.size());536for(size_t i=0; i < rectsWhereRegions.size(); i++) {537Rect r = rectsWhereRegions[i];538539detectInRegion(imageDetect, r, detectedObjectsInRegions);540}541LOGD("DetectionBasedTracker::process: detectedObjectsInRegions.size()=%d", (int)detectedObjectsInRegions.size());542543updateTrackedObjects(detectedObjectsInRegions);544}545546void cv::DetectionBasedTracker::getObjects(std::vector<cv::Rect>& result) const547{548result.clear();549550for(size_t i=0; i < trackedObjects.size(); i++) {551Rect r=calcTrackedObjectPositionToShow((int)i);552if (r.empty()) {553continue;554}555result.push_back(r);556LOGD("DetectionBasedTracker::process: found a object with SIZE %d x %d, rect={%d, %d, %d x %d}", r.width, r.height, r.x, r.y, r.width, r.height);557}558}559560void cv::DetectionBasedTracker::getObjects(std::vector<Object>& result) const561{562result.clear();563564for(size_t i=0; i < trackedObjects.size(); i++) {565Rect r=calcTrackedObjectPositionToShow((int)i);566if (r.empty()) {567continue;568}569result.push_back(Object(r, trackedObjects[i].id));570LOGD("DetectionBasedTracker::process: found a object with SIZE %d x %d, rect={%d, %d, %d x %d}", r.width, r.height, r.x, r.y, r.width, r.height);571}572}573void cv::DetectionBasedTracker::getObjects(std::vector<ExtObject>& result) const574{575result.clear();576577for(size_t i=0; i < trackedObjects.size(); i++) {578ObjectStatus status;579Rect r=calcTrackedObjectPositionToShow((int)i, status);580result.push_back(ExtObject(trackedObjects[i].id, r, status));581LOGD("DetectionBasedTracker::process: found a object with SIZE %d x %d, rect={%d, %d, %d x %d}, status = %d", r.width, r.height, r.x, r.y, r.width, r.height, (int)status);582}583}584585bool cv::DetectionBasedTracker::run()586{587if (separateDetectionWork) {588return separateDetectionWork->run();589}590return false;591}592593void cv::DetectionBasedTracker::stop()594{595if (separateDetectionWork) {596separateDetectionWork->stop();597}598}599600void cv::DetectionBasedTracker::resetTracking()601{602if (separateDetectionWork) {603separateDetectionWork->resetTracking();604}605trackedObjects.clear();606}607608void cv::DetectionBasedTracker::updateTrackedObjects(const std::vector<Rect>& detectedObjects)609{610enum {611NEW_RECTANGLE=-1,612INTERSECTED_RECTANGLE=-2613};614615int N1=(int)trackedObjects.size();616int N2=(int)detectedObjects.size();617LOGD("DetectionBasedTracker::updateTrackedObjects: N1=%d, N2=%d", N1, N2);618619for(int i=0; i < N1; i++) {620trackedObjects[i].numDetectedFrames++;621}622623std::vector<int> correspondence(detectedObjects.size(), NEW_RECTANGLE);624correspondence.clear();625correspondence.resize(detectedObjects.size(), NEW_RECTANGLE);626627for(int i=0; i < N1; i++) {628LOGD("DetectionBasedTracker::updateTrackedObjects: i=%d", i);629TrackedObject& curObject=trackedObjects[i];630631int bestIndex=-1;632int bestArea=-1;633634int numpositions=(int)curObject.lastPositions.size();635CV_Assert(numpositions > 0);636Rect prevRect=curObject.lastPositions[numpositions-1];637LOGD("DetectionBasedTracker::updateTrackedObjects: prevRect[%d]={%d, %d, %d x %d}", i, prevRect.x, prevRect.y, prevRect.width, prevRect.height);638639for(int j=0; j < N2; j++) {640LOGD("DetectionBasedTracker::updateTrackedObjects: j=%d", j);641if (correspondence[j] >= 0) {642LOGD("DetectionBasedTracker::updateTrackedObjects: j=%d is rejected, because it has correspondence=%d", j, correspondence[j]);643continue;644}645if (correspondence[j] !=NEW_RECTANGLE) {646LOGD("DetectionBasedTracker::updateTrackedObjects: j=%d is rejected, because it is intersected with another rectangle", j);647continue;648}649LOGD("DetectionBasedTracker::updateTrackedObjects: detectedObjects[%d]={%d, %d, %d x %d}",650j, detectedObjects[j].x, detectedObjects[j].y, detectedObjects[j].width, detectedObjects[j].height);651652Rect r=prevRect & detectedObjects[j];653if ( (r.width > 0) && (r.height > 0) ) {654LOGD("DetectionBasedTracker::updateTrackedObjects: There is intersection between prevRect and detectedRect, r={%d, %d, %d x %d}",655r.x, r.y, r.width, r.height);656correspondence[j]=INTERSECTED_RECTANGLE;657658if ( r.area() > bestArea) {659LOGD("DetectionBasedTracker::updateTrackedObjects: The area of intersection is %d, it is better than bestArea=%d", r.area(), bestArea);660bestIndex=j;661bestArea=r.area();662}663}664}665if (bestIndex >= 0) {666LOGD("DetectionBasedTracker::updateTrackedObjects: The best correspondence for i=%d is j=%d", i, bestIndex);667correspondence[bestIndex]=i;668669for(int j=0; j < N2; j++) {670if (correspondence[j] >= 0)671continue;672673Rect r=detectedObjects[j] & detectedObjects[bestIndex];674if ( (r.width > 0) && (r.height > 0) ) {675LOGD("DetectionBasedTracker::updateTrackedObjects: Found intersection between "676"rectangles j=%d and bestIndex=%d, rectangle j=%d is marked as intersected", j, bestIndex, j);677correspondence[j]=INTERSECTED_RECTANGLE;678}679}680} else {681LOGD("DetectionBasedTracker::updateTrackedObjects: There is no correspondence for i=%d ", i);682curObject.numFramesNotDetected++;683}684}685686LOGD("DetectionBasedTracker::updateTrackedObjects: start second cycle");687for(int j=0; j < N2; j++) {688LOGD("DetectionBasedTracker::updateTrackedObjects: j=%d", j);689int i=correspondence[j];690if (i >= 0) {//add position691LOGD("DetectionBasedTracker::updateTrackedObjects: add position");692trackedObjects[i].lastPositions.push_back(detectedObjects[j]);693while ((int)trackedObjects[i].lastPositions.size() > (int) innerParameters.numLastPositionsToTrack) {694trackedObjects[i].lastPositions.erase(trackedObjects[i].lastPositions.begin());695}696trackedObjects[i].numFramesNotDetected=0;697} else if (i==NEW_RECTANGLE){ //new object698LOGD("DetectionBasedTracker::updateTrackedObjects: new object");699trackedObjects.push_back(detectedObjects[j]);700} else {701LOGD("DetectionBasedTracker::updateTrackedObjects: was auxiliary intersection");702}703}704705std::vector<TrackedObject>::iterator it=trackedObjects.begin();706while( it != trackedObjects.end() ) {707if ( (it->numFramesNotDetected > parameters.maxTrackLifetime)708||709(710(it->numDetectedFrames <= innerParameters.numStepsToWaitBeforeFirstShow)711&&712(it->numFramesNotDetected > innerParameters.numStepsToTrackWithoutDetectingIfObjectHasNotBeenShown)713)714)715{716int numpos=(int)it->lastPositions.size();717CV_Assert(numpos > 0);718Rect r = it->lastPositions[numpos-1];719(void)(r);720LOGD("DetectionBasedTracker::updateTrackedObjects: deleted object {%d, %d, %d x %d}",721r.x, r.y, r.width, r.height);722it=trackedObjects.erase(it);723} else {724it++;725}726}727}728729int cv::DetectionBasedTracker::addObject(const Rect& location)730{731LOGD("DetectionBasedTracker::addObject: new object {%d, %d %dx%d}",location.x, location.y, location.width, location.height);732trackedObjects.push_back(TrackedObject(location));733int newId = trackedObjects.back().id;734LOGD("DetectionBasedTracker::addObject: newId = %d", newId);735return newId;736}737738Rect cv::DetectionBasedTracker::calcTrackedObjectPositionToShow(int i) const739{740ObjectStatus status;741return calcTrackedObjectPositionToShow(i, status);742}743Rect cv::DetectionBasedTracker::calcTrackedObjectPositionToShow(int i, ObjectStatus& status) const744{745if ( (i < 0) || (i >= (int)trackedObjects.size()) ) {746LOGE("DetectionBasedTracker::calcTrackedObjectPositionToShow: ERROR: wrong i=%d", i);747status = WRONG_OBJECT;748return Rect();749}750if (trackedObjects[i].numDetectedFrames <= innerParameters.numStepsToWaitBeforeFirstShow){751LOGI("DetectionBasedTracker::calcTrackedObjectPositionToShow: trackedObjects[%d].numDetectedFrames=%d <= numStepsToWaitBeforeFirstShow=%d --- return empty Rect()",752i, trackedObjects[i].numDetectedFrames, innerParameters.numStepsToWaitBeforeFirstShow);753status = DETECTED_NOT_SHOWN_YET;754return Rect();755}756if (trackedObjects[i].numFramesNotDetected > innerParameters.numStepsToShowWithoutDetecting) {757status = DETECTED_TEMPORARY_LOST;758return Rect();759}760761const TrackedObject::PositionsVector& lastPositions=trackedObjects[i].lastPositions;762763int N=(int)lastPositions.size();764if (N<=0) {765LOGE("DetectionBasedTracker::calcTrackedObjectPositionToShow: ERROR: no positions for i=%d", i);766status = WRONG_OBJECT;767return Rect();768}769770int Nsize=std::min(N, (int)weightsSizesSmoothing.size());771int Ncenter= std::min(N, (int)weightsPositionsSmoothing.size());772773Point2f center;774double w=0, h=0;775if (Nsize > 0) {776double sum=0;777for(int j=0; j < Nsize; j++) {778int k=N-j-1;779w += lastPositions[k].width * weightsSizesSmoothing[j];780h += lastPositions[k].height * weightsSizesSmoothing[j];781sum+=weightsSizesSmoothing[j];782}783w /= sum;784h /= sum;785} else {786w=lastPositions[N-1].width;787h=lastPositions[N-1].height;788}789790if (Ncenter > 0) {791double sum=0;792for(int j=0; j < Ncenter; j++) {793int k=N-j-1;794Point tl(lastPositions[k].tl());795Point br(lastPositions[k].br());796Point2f c1;797c1=tl;798c1=c1* 0.5f;799Point2f c2;800c2=br;801c2=c2*0.5f;802c1=c1+c2;803804center=center+ (c1 * weightsPositionsSmoothing[j]);805sum+=weightsPositionsSmoothing[j];806}807center *= (float)(1 / sum);808} else {809int k=N-1;810Point tl(lastPositions[k].tl());811Point br(lastPositions[k].br());812Point2f c1;813c1=tl;814c1=c1* 0.5f;815Point2f c2;816c2=br;817c2=c2*0.5f;818819center=c1+c2;820}821Point2f tl=center-Point2f((float)w*0.5f,(float)h*0.5f);822Rect res(cvRound(tl.x), cvRound(tl.y), cvRound(w), cvRound(h));823LOGD("DetectionBasedTracker::calcTrackedObjectPositionToShow: Result for i=%d: {%d, %d, %d x %d}", i, res.x, res.y, res.width, res.height);824825status = DETECTED;826return res;827}828829void cv::DetectionBasedTracker::detectInRegion(const Mat& img, const Rect& r, std::vector<Rect>& detectedObjectsInRegions)830{831Rect r0(Point(), img.size());832Rect r1 = scale_rect(r, innerParameters.coeffTrackingWindowSize);833r1 = r1 & r0;834835if ( (r1.width <=0) || (r1.height <= 0) ) {836LOGD("DetectionBasedTracker::detectInRegion: Empty intersection");837return;838}839840int d = cvRound(std::min(r.width, r.height) * innerParameters.coeffObjectSizeToTrack);841842std::vector<Rect> tmpobjects;843844Mat img1(img, r1);//subimage for rectangle -- without data copying845LOGD("DetectionBasedTracker::detectInRegion: img1.size()=%d x %d, d=%d",846img1.size().width, img1.size().height, d);847848cascadeForTracking->setMinObjectSize(Size(d, d));849cascadeForTracking->detect(img1, tmpobjects);850/*851detectMultiScale( img1, tmpobjects,852parameters.scaleFactor, parameters.minNeighbors, 0853|CV_HAAR_FIND_BIGGEST_OBJECT854|CV_HAAR_SCALE_IMAGE855,856Size(d,d),857max_objectSize858);*/859860for(size_t i=0; i < tmpobjects.size(); i++) {861Rect curres(tmpobjects[i].tl() + r1.tl(), tmpobjects[i].size());862detectedObjectsInRegions.push_back(curres);863}864}865866bool cv::DetectionBasedTracker::setParameters(const Parameters& params)867{868if ( params.maxTrackLifetime < 0 )869{870LOGE("DetectionBasedTracker::setParameters: ERROR: wrong parameters value");871return false;872}873874if (separateDetectionWork) {875separateDetectionWork->setParameters(params);876}877parameters=params;878return true;879}880881const cv::DetectionBasedTracker::Parameters& DetectionBasedTracker::getParameters() const882{883return parameters;884}885886887