diff --git a/modules/tracking/src/tldDetector.cpp b/modules/tracking/src/tldDetector.cpp index 633a60b0a..3dac8b53b 100644 --- a/modules/tracking/src/tldDetector.cpp +++ b/modules/tracking/src/tldDetector.cpp @@ -40,6 +40,7 @@ //M*/ #include "tldDetector.hpp" +#include "tracking_utils.hpp" #include @@ -72,12 +73,12 @@ namespace cv for (int i = 0; i < *posNum; i++) { modelSample.data = &(posExp->data[i * 225]); - splus = std::max(splus, 0.5 * (NCC(modelSample, patch) + 1.0)); + splus = std::max(splus, 0.5 * (tracking_internal::computeNCC(modelSample, patch) + 1.0)); } for (int i = 0; i < *negNum; i++) { modelSample.data = &(negExp->data[i * 225]); - sminus = std::max(sminus, 0.5 * (NCC(modelSample, patch) + 1.0)); + sminus = std::max(sminus, 0.5 * (tracking_internal::computeNCC(modelSample, patch) + 1.0)); } if (splus + sminus == 0.0) @@ -167,7 +168,7 @@ namespace cv for (int id = 0; id < numOfPatches; id++) { double spr = 0.0, smr = 0.0, spc = 0.0, smc = 0; - int med = getMedian((*timeStampsPositive)); + int med = tracking_internal::getMedian((*timeStampsPositive)); for (int i = 0; i < *posNum; i++) { spr = std::max(spr, 0.5 * (posNCC.at(id * 500 + i) + 1.0)); @@ -195,19 +196,19 @@ namespace cv { double splus = 0.0, sminus = 0.0; Mat_ modelSample(STANDARD_PATCH_SIZE, STANDARD_PATCH_SIZE); - int med = getMedian((*timeStampsPositive)); + int med = tracking_internal::getMedian((*timeStampsPositive)); for (int i = 0; i < *posNum; i++) { if ((int)(*timeStampsPositive)[i] <= med) { modelSample.data = &(posExp->data[i * 225]); - splus = std::max(splus, 0.5 * (NCC(modelSample, patch) + 1.0)); + splus = std::max(splus, 0.5 * (tracking_internal::computeNCC(modelSample, patch) + 1.0)); } } for (int i = 0; i < *negNum; i++) { modelSample.data = &(negExp->data[i * 225]); - sminus = std::max(sminus, 0.5 * (NCC(modelSample, patch) + 1.0)); + sminus = std::max(sminus, 0.5 * (tracking_internal::computeNCC(modelSample, patch) + 1.0)); } if (splus + sminus == 0.0) @@ -249,7 +250,7 @@ namespace cv Mat resNCC = devNCC.getMat(ACCESS_READ); - int med = getMedian((*timeStampsPositive)); + int med = tracking_internal::getMedian((*timeStampsPositive)); for (int i = 0; i < *posNum; i++) if ((int)(*timeStampsPositive)[i] <= med) splus = std::max(splus, 0.5 * (resNCC.at(i) +1.0)); diff --git a/modules/tracking/src/tldUtils.cpp b/modules/tracking/src/tldUtils.cpp index f01f30a56..17377c793 100644 --- a/modules/tracking/src/tldUtils.cpp +++ b/modules/tracking/src/tldUtils.cpp @@ -164,35 +164,6 @@ double variance(const Mat& img) return p2 - p * p; } -//Normalized Correlation Coefficient -double NCC(const Mat_& patch1, const Mat_& patch2) -{ - CV_Assert( patch1.rows == patch2.rows ); - CV_Assert( patch1.cols == patch2.cols ); - - int N = patch1.rows * patch1.cols; - double s1 = sum(patch1)(0); - double s2 = sum(patch2)(0); - double n1 = norm(patch1, NORM_L2SQR); - double n2 = norm(patch2, NORM_L2SQR); - double prod=patch1.dot(patch2); - double sq1 = sqrt(std::max(0.0, n1 - 1.0 * s1 * s1 / N)); - double sq2 = sqrt(std::max(0.0, n2 - 1.0 * s2 * s2 / N)); - return (sq2 == 0) ? sq1 / abs(sq1) : (prod - s1 * s2 / N) / sq1 / sq2; -} - -int getMedian(const std::vector& values, int size) -{ - if( size == -1 ) - size = (int)values.size(); - std::vector copy(values.begin(), values.begin() + size); - std::sort(copy.begin(), copy.end()); - if( size % 2 == 0 ) - return (copy[size / 2 - 1] + copy[size / 2]) / 2; - else - return copy[(size - 1) / 2]; -} - //Overlap between two BB double overlap(const Rect2d& r1, const Rect2d& r2) { diff --git a/modules/tracking/src/tldUtils.hpp b/modules/tracking/src/tldUtils.hpp index e6090069a..1a606429d 100644 --- a/modules/tracking/src/tldUtils.hpp +++ b/modules/tracking/src/tldUtils.hpp @@ -46,13 +46,8 @@ namespace cv void resample(const Mat& img, const Rect2d& r2, Mat_& samples); /** Computes the variance of single given image.*/ double variance(const Mat& img); - /** Computes normalized corellation coefficient between the two patches (they should be - * of the same size).*/ - double NCC(const Mat_& patch1, const Mat_& patch2); void getClosestN(std::vector& scanGrid, Rect2d bBox, int n, std::vector& res); double scaleAndBlur(const Mat& originalImg, int scale, Mat& scaledImg, Mat& blurredImg, Size GaussBlurKernelSize, double scaleStep); - int getMedian(const std::vector& values, int size = -1); - } } diff --git a/modules/tracking/src/trackerMedianFlow.cpp b/modules/tracking/src/trackerMedianFlow.cpp index db1e80557..57a0e2a4b 100644 --- a/modules/tracking/src/trackerMedianFlow.cpp +++ b/modules/tracking/src/trackerMedianFlow.cpp @@ -42,6 +42,7 @@ #include "precomp.hpp" #include "opencv2/video/tracking.hpp" #include "opencv2/imgproc.hpp" +#include "tracking_utils.hpp" #include #include @@ -94,12 +95,6 @@ private: TrackerMedianFlow::Params params; }; -template -T getMedian( const std::vector& values ); - -template -T getMedianAndDoPartition( std::vector& values ); - Mat getPatch(Mat image, Size patch_size, Point2f patch_center) { Mat patch; @@ -282,7 +277,7 @@ bool TrackerMedianFlowImpl::medianFlowImpl(Mat oldImage,Mat newImage,Rect2d& old di[i]-=mDisplacement; displacements.push_back((float)sqrt(di[i].ddot(di[i]))); } - float median_displacements = getMedianAndDoPartition(displacements); + float median_displacements = tracking_internal::getMedianAndDoPartition(displacements); dprintf(("\tmedian of length of difference of displacements = %f\n", median_displacements)); if(median_displacements > params.maxMedianLengthOfDisplacementDifference){ dprintf(("\tmedian flow tracker returns false due to big median length of difference between displacements\n")); @@ -310,10 +305,10 @@ Rect2d TrackerMedianFlowImpl::vote(const std::vector& oldPoints,const s float xshift=0,yshift=0; std::vector buf_for_location(n, 0.); for(size_t i=0;i& oldPoints,const s } } - double scale=getMedianAndDoPartition(buf_for_scale); + double scale=tracking_internal::getMedianAndDoPartition(buf_for_scale); dprintf(("xshift, yshift, scale = %f %f %f\n",xshift,yshift,scale)); newRect.x=newCenter.x-scale*oldRect.width/2.0; newRect.y=newCenter.y-scale*oldRect.height/2.0; @@ -371,7 +366,7 @@ void TrackerMedianFlowImpl::check_FB(const std::vector& oldImagePyr, const for(size_t i=0;i= median); } } -template -T getMedian(const std::vector& values) -{ - std::vector copy(values); - return getMedianAndDoPartition(copy); -} - -template -T getMedianAndDoPartition(std::vector& values) -{ - size_t size = values.size(); - if(size%2==0) - { - std::nth_element(values.begin(), values.begin() + size/2-1, values.end()); - T firstMedian = values[size/2-1]; - - std::nth_element(values.begin(), values.begin() + size/2, values.end()); - T secondMedian = values[size/2]; - - return (firstMedian + secondMedian) / (T)2; - } - else - { - size_t medianIndex = (size - 1) / 2; - std::nth_element(values.begin(), values.begin() + medianIndex, values.end()); - - return values[medianIndex]; - } -} - } /* anonymous namespace */ namespace cv diff --git a/modules/tracking/src/tracking_utils.cpp b/modules/tracking/src/tracking_utils.cpp new file mode 100644 index 000000000..ee0cc2c02 --- /dev/null +++ b/modules/tracking/src/tracking_utils.cpp @@ -0,0 +1,23 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +#include "tracking_utils.hpp" + +using namespace cv; + +double tracking_internal::computeNCC(const Mat& patch1, const Mat& patch2) +{ + CV_Assert( patch1.rows == patch2.rows ); + CV_Assert( patch1.cols == patch2.cols ); + + int N = patch1.rows * patch1.cols; + double s1 = sum(patch1)(0); + double s2 = sum(patch2)(0); + double n1 = norm(patch1, NORM_L2SQR); + double n2 = norm(patch2, NORM_L2SQR); + double prod=patch1.dot(patch2); + double sq1 = sqrt(std::max(0.0, n1 - 1.0 * s1 * s1 / N)); + double sq2 = sqrt(std::max(0.0, n2 - 1.0 * s2 * s2 / N)); + return (sq2 == 0) ? sq1 / abs(sq1) : (prod - s1 * s2 / N) / sq1 / sq2; +} diff --git a/modules/tracking/src/tracking_utils.hpp b/modules/tracking/src/tracking_utils.hpp new file mode 100644 index 000000000..a73562242 --- /dev/null +++ b/modules/tracking/src/tracking_utils.hpp @@ -0,0 +1,47 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +#ifndef __OPENCV_TRACKING_UTILS_HPP__ + +#include "precomp.hpp" +#include + +namespace cv { +namespace tracking_internal +{ +/** Computes normalized corellation coefficient between the two patches (they should be +* of the same size).*/ + double computeNCC(const Mat& patch1, const Mat& patch2); + + template + T getMedianAndDoPartition(std::vector& values) + { + size_t size = values.size(); + if(size%2==0) + { + std::nth_element(values.begin(), values.begin() + size/2-1, values.end()); + T firstMedian = values[size/2-1]; + + std::nth_element(values.begin(), values.begin() + size/2, values.end()); + T secondMedian = values[size/2]; + + return (firstMedian + secondMedian) / (T)2; + } + else + { + size_t medianIndex = (size - 1) / 2; + std::nth_element(values.begin(), values.begin() + medianIndex, values.end()); + + return values[medianIndex]; + } + } + + template + T getMedian(const std::vector& values) + { + std::vector copy(values); + return getMedianAndDoPartition(copy); + } +} +} +#endif