Commit a6215264 authored by Vladislav Sovrasov's avatar Vladislav Sovrasov

tracking: eliminate code duplication

parent b8588f84
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
//M*/ //M*/
#include "tldDetector.hpp" #include "tldDetector.hpp"
#include "tracking_utils.hpp"
#include <opencv2/core/utility.hpp> #include <opencv2/core/utility.hpp>
...@@ -72,12 +73,12 @@ namespace cv ...@@ -72,12 +73,12 @@ namespace cv
for (int i = 0; i < *posNum; i++) for (int i = 0; i < *posNum; i++)
{ {
modelSample.data = &(posExp->data[i * 225]); 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++) for (int i = 0; i < *negNum; i++)
{ {
modelSample.data = &(negExp->data[i * 225]); 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) if (splus + sminus == 0.0)
...@@ -167,7 +168,7 @@ namespace cv ...@@ -167,7 +168,7 @@ namespace cv
for (int id = 0; id < numOfPatches; id++) for (int id = 0; id < numOfPatches; id++)
{ {
double spr = 0.0, smr = 0.0, spc = 0.0, smc = 0; 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++) for (int i = 0; i < *posNum; i++)
{ {
spr = std::max(spr, 0.5 * (posNCC.at<float>(id * 500 + i) + 1.0)); spr = std::max(spr, 0.5 * (posNCC.at<float>(id * 500 + i) + 1.0));
...@@ -195,19 +196,19 @@ namespace cv ...@@ -195,19 +196,19 @@ namespace cv
{ {
double splus = 0.0, sminus = 0.0; double splus = 0.0, sminus = 0.0;
Mat_<uchar> modelSample(STANDARD_PATCH_SIZE, STANDARD_PATCH_SIZE); Mat_<uchar> modelSample(STANDARD_PATCH_SIZE, STANDARD_PATCH_SIZE);
int med = getMedian((*timeStampsPositive)); int med = tracking_internal::getMedian((*timeStampsPositive));
for (int i = 0; i < *posNum; i++) for (int i = 0; i < *posNum; i++)
{ {
if ((int)(*timeStampsPositive)[i] <= med) if ((int)(*timeStampsPositive)[i] <= med)
{ {
modelSample.data = &(posExp->data[i * 225]); 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++) for (int i = 0; i < *negNum; i++)
{ {
modelSample.data = &(negExp->data[i * 225]); 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) if (splus + sminus == 0.0)
...@@ -249,7 +250,7 @@ namespace cv ...@@ -249,7 +250,7 @@ namespace cv
Mat resNCC = devNCC.getMat(ACCESS_READ); Mat resNCC = devNCC.getMat(ACCESS_READ);
int med = getMedian((*timeStampsPositive)); int med = tracking_internal::getMedian((*timeStampsPositive));
for (int i = 0; i < *posNum; i++) for (int i = 0; i < *posNum; i++)
if ((int)(*timeStampsPositive)[i] <= med) if ((int)(*timeStampsPositive)[i] <= med)
splus = std::max(splus, 0.5 * (resNCC.at<float>(i) +1.0)); splus = std::max(splus, 0.5 * (resNCC.at<float>(i) +1.0));
......
...@@ -164,35 +164,6 @@ double variance(const Mat& img) ...@@ -164,35 +164,6 @@ double variance(const Mat& img)
return p2 - p * p; return p2 - p * p;
} }
//Normalized Correlation Coefficient
double NCC(const Mat_<uchar>& patch1, const Mat_<uchar>& 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<int>& values, int size)
{
if( size == -1 )
size = (int)values.size();
std::vector<int> 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 //Overlap between two BB
double overlap(const Rect2d& r1, const Rect2d& r2) double overlap(const Rect2d& r1, const Rect2d& r2)
{ {
......
...@@ -46,13 +46,8 @@ namespace cv ...@@ -46,13 +46,8 @@ namespace cv
void resample(const Mat& img, const Rect2d& r2, Mat_<uchar>& samples); void resample(const Mat& img, const Rect2d& r2, Mat_<uchar>& samples);
/** Computes the variance of single given image.*/ /** Computes the variance of single given image.*/
double variance(const Mat& img); double variance(const Mat& img);
/** Computes normalized corellation coefficient between the two patches (they should be
* of the same size).*/
double NCC(const Mat_<uchar>& patch1, const Mat_<uchar>& patch2);
void getClosestN(std::vector<Rect2d>& scanGrid, Rect2d bBox, int n, std::vector<Rect2d>& res); void getClosestN(std::vector<Rect2d>& scanGrid, Rect2d bBox, int n, std::vector<Rect2d>& res);
double scaleAndBlur(const Mat& originalImg, int scale, Mat& scaledImg, Mat& blurredImg, Size GaussBlurKernelSize, double scaleStep); double scaleAndBlur(const Mat& originalImg, int scale, Mat& scaledImg, Mat& blurredImg, Size GaussBlurKernelSize, double scaleStep);
int getMedian(const std::vector<int>& values, int size = -1);
} }
} }
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include "precomp.hpp" #include "precomp.hpp"
#include "opencv2/video/tracking.hpp" #include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc.hpp" #include "opencv2/imgproc.hpp"
#include "tracking_utils.hpp"
#include <algorithm> #include <algorithm>
#include <limits.h> #include <limits.h>
...@@ -94,12 +95,6 @@ private: ...@@ -94,12 +95,6 @@ private:
TrackerMedianFlow::Params params; TrackerMedianFlow::Params params;
}; };
template<typename T>
T getMedian( const std::vector<T>& values );
template<typename T>
T getMedianAndDoPartition( std::vector<T>& values );
Mat getPatch(Mat image, Size patch_size, Point2f patch_center) Mat getPatch(Mat image, Size patch_size, Point2f patch_center)
{ {
Mat patch; Mat patch;
...@@ -282,7 +277,7 @@ bool TrackerMedianFlowImpl::medianFlowImpl(Mat oldImage,Mat newImage,Rect2d& old ...@@ -282,7 +277,7 @@ bool TrackerMedianFlowImpl::medianFlowImpl(Mat oldImage,Mat newImage,Rect2d& old
di[i]-=mDisplacement; di[i]-=mDisplacement;
displacements.push_back((float)sqrt(di[i].ddot(di[i]))); 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)); dprintf(("\tmedian of length of difference of displacements = %f\n", median_displacements));
if(median_displacements > params.maxMedianLengthOfDisplacementDifference){ if(median_displacements > params.maxMedianLengthOfDisplacementDifference){
dprintf(("\tmedian flow tracker returns false due to big median length of difference between displacements\n")); 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<Point2f>& oldPoints,const s ...@@ -310,10 +305,10 @@ Rect2d TrackerMedianFlowImpl::vote(const std::vector<Point2f>& oldPoints,const s
float xshift=0,yshift=0; float xshift=0,yshift=0;
std::vector<float> buf_for_location(n, 0.); std::vector<float> buf_for_location(n, 0.);
for(size_t i=0;i<n;i++){ buf_for_location[i]=newPoints[i].x-oldPoints[i].x; } for(size_t i=0;i<n;i++){ buf_for_location[i]=newPoints[i].x-oldPoints[i].x; }
xshift=getMedianAndDoPartition(buf_for_location); xshift=tracking_internal::getMedianAndDoPartition(buf_for_location);
newCenter.x+=xshift; newCenter.x+=xshift;
for(size_t i=0;i<n;i++){ buf_for_location[i]=newPoints[i].y-oldPoints[i].y; } for(size_t i=0;i<n;i++){ buf_for_location[i]=newPoints[i].y-oldPoints[i].y; }
yshift=getMedianAndDoPartition(buf_for_location); yshift=tracking_internal::getMedianAndDoPartition(buf_for_location);
newCenter.y+=yshift; newCenter.y+=yshift;
mD=Point2f((float)xshift,(float)yshift); mD=Point2f((float)xshift,(float)yshift);
...@@ -327,7 +322,7 @@ Rect2d TrackerMedianFlowImpl::vote(const std::vector<Point2f>& oldPoints,const s ...@@ -327,7 +322,7 @@ Rect2d TrackerMedianFlowImpl::vote(const std::vector<Point2f>& 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)); dprintf(("xshift, yshift, scale = %f %f %f\n",xshift,yshift,scale));
newRect.x=newCenter.x-scale*oldRect.width/2.0; newRect.x=newCenter.x-scale*oldRect.width/2.0;
newRect.y=newCenter.y-scale*oldRect.height/2.0; newRect.y=newCenter.y-scale*oldRect.height/2.0;
...@@ -371,7 +366,7 @@ void TrackerMedianFlowImpl::check_FB(const std::vector<Mat>& oldImagePyr, const ...@@ -371,7 +366,7 @@ void TrackerMedianFlowImpl::check_FB(const std::vector<Mat>& oldImagePyr, const
for(size_t i=0;i<oldPoints.size();i++){ for(size_t i=0;i<oldPoints.size();i++){
FBerror[i]=(float)norm(oldPoints[i]-pointsToTrackReprojection[i]); FBerror[i]=(float)norm(oldPoints[i]-pointsToTrackReprojection[i]);
} }
float FBerrorMedian=getMedian(FBerror); float FBerrorMedian=tracking_internal::getMedian(FBerror);
dprintf(("point median=%f\n",FBerrorMedian)); dprintf(("point median=%f\n",FBerrorMedian));
dprintf(("FBerrorMedian=%f\n",FBerrorMedian)); dprintf(("FBerrorMedian=%f\n",FBerrorMedian));
for(size_t i=0;i<oldPoints.size();i++){ for(size_t i=0;i<oldPoints.size();i++){
...@@ -388,51 +383,14 @@ void TrackerMedianFlowImpl::check_NCC(const Mat& oldImage,const Mat& newImage, ...@@ -388,51 +383,14 @@ void TrackerMedianFlowImpl::check_NCC(const Mat& oldImage,const Mat& newImage,
p1 = getPatch(oldImage, params.winSizeNCC, oldPoints[i]); p1 = getPatch(oldImage, params.winSizeNCC, oldPoints[i]);
p2 = getPatch(newImage, params.winSizeNCC, newPoints[i]); p2 = getPatch(newImage, params.winSizeNCC, newPoints[i]);
const int patch_area=params.winSizeNCC.area(); NCC[i] = (float)tracking_internal::computeNCC(p1, p2);
double s1=sum(p1)(0),s2=sum(p2)(0);
double n1=norm(p1),n2=norm(p2);
double prod=p1.dot(p2);
double sq1=sqrt(n1*n1-s1*s1/patch_area),sq2=sqrt(n2*n2-s2*s2/patch_area);
double ares=(sq2==0)?sq1/abs(sq1):(prod-s1*s2/patch_area)/sq1/sq2;
NCC[i] = (float)ares;
} }
float median = getMedian(NCC); float median = tracking_internal::getMedian(NCC);
for(size_t i = 0; i < oldPoints.size(); i++) { for(size_t i = 0; i < oldPoints.size(); i++) {
status[i] = status[i] && (NCC[i] >= median); status[i] = status[i] && (NCC[i] >= median);
} }
} }
template<typename T>
T getMedian(const std::vector<T>& values)
{
std::vector<T> copy(values);
return getMedianAndDoPartition(copy);
}
template<typename T>
T getMedianAndDoPartition(std::vector<T>& 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 */ } /* anonymous namespace */
namespace cv namespace cv
......
// 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;
}
// 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 <algorithm>
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<typename T>
T getMedianAndDoPartition(std::vector<T>& 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<typename T>
T getMedian(const std::vector<T>& values)
{
std::vector<T> copy(values);
return getMedianAndDoPartition(copy);
}
}
}
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment