Commit a6215264 authored by Vladislav Sovrasov's avatar Vladislav Sovrasov

tracking: eliminate code duplication

parent b8588f84
......@@ -40,6 +40,7 @@
//M*/
#include "tldDetector.hpp"
#include "tracking_utils.hpp"
#include <opencv2/core/utility.hpp>
......@@ -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<float>(id * 500 + i) + 1.0));
......@@ -195,19 +196,19 @@ namespace cv
{
double splus = 0.0, sminus = 0.0;
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++)
{
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<float>(i) +1.0));
......
......@@ -164,35 +164,6 @@ double variance(const Mat& img)
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
double overlap(const Rect2d& r1, const Rect2d& r2)
{
......
......@@ -46,13 +46,8 @@ namespace cv
void resample(const Mat& img, const Rect2d& r2, Mat_<uchar>& 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_<uchar>& patch1, const Mat_<uchar>& patch2);
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);
int getMedian(const std::vector<int>& values, int size = -1);
}
}
......
......@@ -42,6 +42,7 @@
#include "precomp.hpp"
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc.hpp"
#include "tracking_utils.hpp"
#include <algorithm>
#include <limits.h>
......@@ -94,12 +95,6 @@ private:
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 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<Point2f>& oldPoints,const s
float xshift=0,yshift=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; }
xshift=getMedianAndDoPartition(buf_for_location);
xshift=tracking_internal::getMedianAndDoPartition(buf_for_location);
newCenter.x+=xshift;
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;
mD=Point2f((float)xshift,(float)yshift);
......@@ -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));
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<Mat>& oldImagePyr, const
for(size_t i=0;i<oldPoints.size();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(("FBerrorMedian=%f\n",FBerrorMedian));
for(size_t i=0;i<oldPoints.size();i++){
......@@ -388,51 +383,14 @@ void TrackerMedianFlowImpl::check_NCC(const Mat& oldImage,const Mat& newImage,
p1 = getPatch(oldImage, params.winSizeNCC, oldPoints[i]);
p2 = getPatch(newImage, params.winSizeNCC, newPoints[i]);
const int patch_area=params.winSizeNCC.area();
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;
NCC[i] = (float)tracking_internal::computeNCC(p1, p2);
}
float median = getMedian(NCC);
float median = tracking_internal::getMedian(NCC);
for(size_t i = 0; i < oldPoints.size(); i++) {
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 */
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