"atomic bomb" commit. Reorganized OpenCV directory structure
This commit is contained in:
288
modules/contrib/src/adaptiveskindetector.cpp
Normal file
288
modules/contrib/src/adaptiveskindetector.cpp
Normal file
@@ -0,0 +1,288 @@
|
||||
/*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.
|
||||
//
|
||||
// Copyright (C) 2009, Farhad Dadgostar
|
||||
// Intel Corporation and 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*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
#define ASD_INTENSITY_SET_PIXEL(pointer, qq) {(*pointer) = (unsigned char)qq;}
|
||||
|
||||
#define ASD_IS_IN_MOTION(pointer, v, threshold) ((abs((*(pointer)) - (v)) > (threshold)) ? true : false)
|
||||
|
||||
void CvAdaptiveSkinDetector::initData(IplImage *src, int widthDivider, int heightDivider)
|
||||
{
|
||||
CvSize imageSize = cvSize(src->width/widthDivider, src->height/heightDivider);
|
||||
|
||||
imgHueFrame = cvCreateImage(imageSize, IPL_DEPTH_8U, 1);
|
||||
imgShrinked = cvCreateImage(imageSize, IPL_DEPTH_8U, src->nChannels);
|
||||
imgSaturationFrame = cvCreateImage(imageSize, IPL_DEPTH_8U, 1);
|
||||
imgMotionFrame = cvCreateImage(imageSize, IPL_DEPTH_8U, 1);
|
||||
imgTemp = cvCreateImage(imageSize, IPL_DEPTH_8U, 1);
|
||||
imgFilteredFrame = cvCreateImage(imageSize, IPL_DEPTH_8U, 1);
|
||||
imgGrayFrame = cvCreateImage(imageSize, IPL_DEPTH_8U, 1);
|
||||
imgLastGrayFrame = cvCreateImage(imageSize, IPL_DEPTH_8U, 1);
|
||||
imgHSVFrame = cvCreateImage(imageSize, IPL_DEPTH_8U, 3);
|
||||
};
|
||||
|
||||
CvAdaptiveSkinDetector::CvAdaptiveSkinDetector(int samplingDivider, int morphingMethod)
|
||||
{
|
||||
nSkinHueLowerBound = GSD_HUE_LT;
|
||||
nSkinHueUpperBound = GSD_HUE_UT;
|
||||
|
||||
fHistogramMergeFactor = 0.05; // empirical result
|
||||
fHuePercentCovered = 0.95; // empirical result
|
||||
|
||||
nMorphingMethod = morphingMethod;
|
||||
nSamplingDivider = samplingDivider;
|
||||
|
||||
nFrameCount = 0;
|
||||
nStartCounter = 0;
|
||||
|
||||
imgHueFrame = NULL;
|
||||
imgMotionFrame = NULL;
|
||||
imgTemp = NULL;
|
||||
imgFilteredFrame = NULL;
|
||||
imgShrinked = NULL;
|
||||
imgGrayFrame = NULL;
|
||||
imgLastGrayFrame = NULL;
|
||||
imgSaturationFrame = NULL;
|
||||
imgHSVFrame = NULL;
|
||||
};
|
||||
|
||||
CvAdaptiveSkinDetector::~CvAdaptiveSkinDetector()
|
||||
{
|
||||
cvReleaseImage(&imgHueFrame);
|
||||
cvReleaseImage(&imgSaturationFrame);
|
||||
cvReleaseImage(&imgMotionFrame);
|
||||
cvReleaseImage(&imgTemp);
|
||||
cvReleaseImage(&imgFilteredFrame);
|
||||
cvReleaseImage(&imgShrinked);
|
||||
cvReleaseImage(&imgGrayFrame);
|
||||
cvReleaseImage(&imgLastGrayFrame);
|
||||
cvReleaseImage(&imgHSVFrame);
|
||||
};
|
||||
|
||||
void CvAdaptiveSkinDetector::process(IplImage *inputBGRImage, IplImage *outputHueMask)
|
||||
{
|
||||
IplImage *src = inputBGRImage;
|
||||
|
||||
int h, v, i, l;
|
||||
bool isInit = false;
|
||||
|
||||
nFrameCount++;
|
||||
|
||||
if (imgHueFrame == NULL)
|
||||
{
|
||||
isInit = true;
|
||||
initData(src, nSamplingDivider, nSamplingDivider);
|
||||
}
|
||||
|
||||
unsigned char *pShrinked, *pHueFrame, *pMotionFrame, *pLastGrayFrame, *pFilteredFrame, *pGrayFrame;
|
||||
pShrinked = (unsigned char *)imgShrinked->imageData;
|
||||
pHueFrame = (unsigned char *)imgHueFrame->imageData;
|
||||
pMotionFrame = (unsigned char *)imgMotionFrame->imageData;
|
||||
pLastGrayFrame = (unsigned char *)imgLastGrayFrame->imageData;
|
||||
pFilteredFrame = (unsigned char *)imgFilteredFrame->imageData;
|
||||
pGrayFrame = (unsigned char *)imgGrayFrame->imageData;
|
||||
|
||||
if ((src->width != imgHueFrame->width) || (src->height != imgHueFrame->height))
|
||||
{
|
||||
cvResize(src, imgShrinked);
|
||||
cvCvtColor(imgShrinked, imgHSVFrame, CV_BGR2HSV);
|
||||
}
|
||||
else
|
||||
{
|
||||
cvCvtColor(src, imgHSVFrame, CV_BGR2HSV);
|
||||
}
|
||||
|
||||
cvSplit(imgHSVFrame, imgHueFrame, imgSaturationFrame, imgGrayFrame, 0);
|
||||
|
||||
cvSetZero(imgMotionFrame);
|
||||
cvSetZero(imgFilteredFrame);
|
||||
|
||||
l = imgHueFrame->height * imgHueFrame->width;
|
||||
|
||||
for (i = 0; i < l; i++)
|
||||
{
|
||||
v = (*pGrayFrame);
|
||||
if ((v >= GSD_INTENSITY_LT) && (v <= GSD_INTENSITY_UT))
|
||||
{
|
||||
h = (*pHueFrame);
|
||||
if ((h >= GSD_HUE_LT) && (h <= GSD_HUE_UT))
|
||||
{
|
||||
if ((h >= nSkinHueLowerBound) && (h <= nSkinHueUpperBound))
|
||||
ASD_INTENSITY_SET_PIXEL(pFilteredFrame, h);
|
||||
|
||||
if (ASD_IS_IN_MOTION(pLastGrayFrame, v, 7))
|
||||
ASD_INTENSITY_SET_PIXEL(pMotionFrame, h);
|
||||
}
|
||||
}
|
||||
pShrinked += 3;
|
||||
pGrayFrame++;
|
||||
pLastGrayFrame++;
|
||||
pMotionFrame++;
|
||||
pHueFrame++;
|
||||
pFilteredFrame++;
|
||||
}
|
||||
|
||||
if (isInit)
|
||||
cvCalcHist(&imgHueFrame, skinHueHistogram.fHistogram);
|
||||
|
||||
cvCopy(imgGrayFrame, imgLastGrayFrame);
|
||||
|
||||
cvErode(imgMotionFrame, imgTemp); // eliminate disperse pixels, which occur because of the camera noise
|
||||
cvDilate(imgTemp, imgMotionFrame);
|
||||
|
||||
cvCalcHist(&imgMotionFrame, histogramHueMotion.fHistogram);
|
||||
|
||||
skinHueHistogram.mergeWith(&histogramHueMotion, fHistogramMergeFactor);
|
||||
|
||||
skinHueHistogram.findCurveThresholds(nSkinHueLowerBound, nSkinHueUpperBound, 1 - fHuePercentCovered);
|
||||
|
||||
switch (nMorphingMethod)
|
||||
{
|
||||
case MORPHING_METHOD_ERODE :
|
||||
cvErode(imgFilteredFrame, imgTemp);
|
||||
cvCopy(imgTemp, imgFilteredFrame);
|
||||
break;
|
||||
case MORPHING_METHOD_ERODE_ERODE :
|
||||
cvErode(imgFilteredFrame, imgTemp);
|
||||
cvErode(imgTemp, imgFilteredFrame);
|
||||
break;
|
||||
case MORPHING_METHOD_ERODE_DILATE :
|
||||
cvErode(imgFilteredFrame, imgTemp);
|
||||
cvDilate(imgTemp, imgFilteredFrame);
|
||||
break;
|
||||
}
|
||||
|
||||
if (outputHueMask != NULL)
|
||||
cvCopy(imgFilteredFrame, outputHueMask);
|
||||
};
|
||||
|
||||
|
||||
//------------------------- Histogram for Adaptive Skin Detector -------------------------//
|
||||
|
||||
CvAdaptiveSkinDetector::Histogram::Histogram()
|
||||
{
|
||||
int histogramSize[] = { HistogramSize };
|
||||
float range[] = { GSD_HUE_LT, GSD_HUE_UT };
|
||||
float *ranges[] = { range };
|
||||
fHistogram = cvCreateHist(1, histogramSize, CV_HIST_ARRAY, ranges, 1);
|
||||
cvClearHist(fHistogram);
|
||||
};
|
||||
|
||||
CvAdaptiveSkinDetector::Histogram::~Histogram()
|
||||
{
|
||||
cvReleaseHist(&fHistogram);
|
||||
};
|
||||
|
||||
int CvAdaptiveSkinDetector::Histogram::findCoverageIndex(double surfaceToCover, int defaultValue)
|
||||
{
|
||||
float s = 0;
|
||||
for (int i = 0; i < HistogramSize; i++)
|
||||
{
|
||||
s += cvGetReal1D( fHistogram->bins, i );
|
||||
if (s >= surfaceToCover)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
};
|
||||
|
||||
void CvAdaptiveSkinDetector::Histogram::findCurveThresholds(int &x1, int &x2, double percent)
|
||||
{
|
||||
float sum = 0;
|
||||
|
||||
for (int i = 0; i < HistogramSize; i++)
|
||||
{
|
||||
sum += cvGetReal1D( fHistogram->bins, i );
|
||||
}
|
||||
|
||||
x1 = findCoverageIndex(sum * percent, -1);
|
||||
x2 = findCoverageIndex(sum * (1-percent), -1);
|
||||
|
||||
if (x1 == -1)
|
||||
x1 = GSD_HUE_LT;
|
||||
else
|
||||
x1 += GSD_HUE_LT;
|
||||
|
||||
if (x2 == -1)
|
||||
x2 = GSD_HUE_UT;
|
||||
else
|
||||
x2 += GSD_HUE_LT;
|
||||
};
|
||||
|
||||
void CvAdaptiveSkinDetector::Histogram::mergeWith(CvAdaptiveSkinDetector::Histogram *source, double weight)
|
||||
{
|
||||
float myweight = (float)(1-weight);
|
||||
float maxVal1 = 0, maxVal2 = 0, *f1, *f2, ff1, ff2;
|
||||
|
||||
cvGetMinMaxHistValue(source->fHistogram, NULL, &maxVal2);
|
||||
|
||||
if (maxVal2 > 0 )
|
||||
{
|
||||
cvGetMinMaxHistValue(fHistogram, NULL, &maxVal1);
|
||||
if (maxVal1 <= 0)
|
||||
{
|
||||
for (int i = 0; i < HistogramSize; i++)
|
||||
{
|
||||
f1 = (float*)cvPtr1D(fHistogram->bins, i);
|
||||
f2 = (float*)cvPtr1D(source->fHistogram->bins, i);
|
||||
(*f1) = (*f2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < HistogramSize; i++)
|
||||
{
|
||||
f1 = (float*)cvPtr1D(fHistogram->bins, i);
|
||||
f2 = (float*)cvPtr1D(source->fHistogram->bins, i);
|
||||
|
||||
ff1 = ((*f1)/maxVal1)*myweight;
|
||||
if (ff1 < 0)
|
||||
ff1 = -ff1;
|
||||
|
||||
ff2 = (float)(((*f2)/maxVal2)*weight);
|
||||
if (ff2 < 0)
|
||||
ff2 = -ff2;
|
||||
|
||||
(*f1) = (ff1 + ff2);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
1109
modules/contrib/src/ba.cpp
Normal file
1109
modules/contrib/src/ba.cpp
Normal file
File diff suppressed because it is too large
Load Diff
722
modules/contrib/src/fuzzymeanshifttracker.cpp
Normal file
722
modules/contrib/src/fuzzymeanshifttracker.cpp
Normal file
@@ -0,0 +1,722 @@
|
||||
/*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.
|
||||
//
|
||||
// Copyright (C) 2009, Farhad Dadgostar
|
||||
// Intel Corporation and 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*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
CvFuzzyPoint::CvFuzzyPoint(double _x, double _y)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
};
|
||||
|
||||
bool CvFuzzyCurve::between(double x, double x1, double x2)
|
||||
{
|
||||
if ((x >= x1) && (x <= x2))
|
||||
return true;
|
||||
else if ((x >= x2) && (x <= x1))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
CvFuzzyCurve::CvFuzzyCurve()
|
||||
{
|
||||
value = 0;
|
||||
};
|
||||
|
||||
CvFuzzyCurve::~CvFuzzyCurve()
|
||||
{
|
||||
// nothing to do
|
||||
};
|
||||
|
||||
void CvFuzzyCurve::setCentre(double _centre)
|
||||
{
|
||||
centre = _centre;
|
||||
};
|
||||
|
||||
double CvFuzzyCurve::getCentre()
|
||||
{
|
||||
return centre;
|
||||
};
|
||||
|
||||
void CvFuzzyCurve::clear()
|
||||
{
|
||||
points.clear();
|
||||
};
|
||||
|
||||
void CvFuzzyCurve::addPoint(double x, double y)
|
||||
{
|
||||
CvFuzzyPoint *point;
|
||||
point = new CvFuzzyPoint(x, y);
|
||||
points.push_back(*point);
|
||||
};
|
||||
|
||||
double CvFuzzyCurve::calcValue(double param)
|
||||
{
|
||||
int size = (int)points.size();
|
||||
double x1, y1, x2, y2, m, y;
|
||||
for (int i = 1; i < size; i++)
|
||||
{
|
||||
x1 = points[i-1].x;
|
||||
x2 = points[i].x;
|
||||
if (between(param, x1, x2)) {
|
||||
y1 = points[i-1].y;
|
||||
y2 = points[i].y;
|
||||
if (x2 == x1)
|
||||
return y2;
|
||||
m = (y2-y1)/(x2-x1);
|
||||
y = m*(param-x1)+y1;
|
||||
return y;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
double CvFuzzyCurve::getValue()
|
||||
{
|
||||
return value;
|
||||
};
|
||||
|
||||
void CvFuzzyCurve::setValue(double _value)
|
||||
{
|
||||
value = _value;
|
||||
};
|
||||
|
||||
|
||||
CvFuzzyFunction::CvFuzzyFunction()
|
||||
{
|
||||
// nothing to do
|
||||
};
|
||||
|
||||
CvFuzzyFunction::~CvFuzzyFunction()
|
||||
{
|
||||
curves.clear();
|
||||
};
|
||||
|
||||
void CvFuzzyFunction::addCurve(CvFuzzyCurve *curve, double value)
|
||||
{
|
||||
curves.push_back(*curve);
|
||||
curve->setValue(value);
|
||||
};
|
||||
|
||||
void CvFuzzyFunction::resetValues()
|
||||
{
|
||||
int numCurves = (int)curves.size();
|
||||
for (int i = 0; i < numCurves; i++)
|
||||
curves[i].setValue(0);
|
||||
};
|
||||
|
||||
double CvFuzzyFunction::calcValue()
|
||||
{
|
||||
double s1 = 0, s2 = 0, v;
|
||||
int numCurves = (int)curves.size();
|
||||
for (int i = 0; i < numCurves; i++)
|
||||
{
|
||||
v = curves[i].getValue();
|
||||
s1 += curves[i].getCentre() * v;
|
||||
s2 += v;
|
||||
}
|
||||
|
||||
if (s2 != 0)
|
||||
return s1/s2;
|
||||
else
|
||||
return 0;
|
||||
};
|
||||
|
||||
CvFuzzyCurve *CvFuzzyFunction::newCurve()
|
||||
{
|
||||
CvFuzzyCurve *c;
|
||||
c = new CvFuzzyCurve();
|
||||
addCurve(c);
|
||||
return c;
|
||||
};
|
||||
|
||||
CvFuzzyRule::CvFuzzyRule()
|
||||
{
|
||||
fuzzyInput1 = NULL;
|
||||
fuzzyInput2 = NULL;
|
||||
fuzzyOutput = NULL;
|
||||
};
|
||||
|
||||
CvFuzzyRule::~CvFuzzyRule()
|
||||
{
|
||||
if (fuzzyInput1 != NULL)
|
||||
delete fuzzyInput1;
|
||||
|
||||
if (fuzzyInput2 != NULL)
|
||||
delete fuzzyInput2;
|
||||
|
||||
if (fuzzyOutput != NULL)
|
||||
delete fuzzyOutput;
|
||||
};
|
||||
|
||||
void CvFuzzyRule::setRule(CvFuzzyCurve *c1, CvFuzzyCurve *c2, CvFuzzyCurve *o1)
|
||||
{
|
||||
fuzzyInput1 = c1;
|
||||
fuzzyInput2 = c2;
|
||||
fuzzyOutput = o1;
|
||||
};
|
||||
|
||||
double CvFuzzyRule::calcValue(double param1, double param2)
|
||||
{
|
||||
double v1, v2;
|
||||
v1 = fuzzyInput1->calcValue(param1);
|
||||
if (fuzzyInput2 != NULL)
|
||||
{
|
||||
v2 = fuzzyInput2->calcValue(param2);
|
||||
if (v1 < v2)
|
||||
return v1;
|
||||
else
|
||||
return v2;
|
||||
}
|
||||
else
|
||||
return v1;
|
||||
};
|
||||
|
||||
CvFuzzyCurve *CvFuzzyRule::getOutputCurve()
|
||||
{
|
||||
return fuzzyOutput;
|
||||
};
|
||||
|
||||
CvFuzzyController::CvFuzzyController()
|
||||
{
|
||||
// nothing to do
|
||||
};
|
||||
|
||||
CvFuzzyController::~CvFuzzyController()
|
||||
{
|
||||
int size = (int)rules.size();
|
||||
for(int i = 0; i < size; i++)
|
||||
delete rules[i];
|
||||
};
|
||||
|
||||
void CvFuzzyController::addRule(CvFuzzyCurve *c1, CvFuzzyCurve *c2, CvFuzzyCurve *o1)
|
||||
{
|
||||
CvFuzzyRule *f = new CvFuzzyRule();
|
||||
rules.push_back(f);
|
||||
f->setRule(c1, c2, o1);
|
||||
};
|
||||
|
||||
double CvFuzzyController::calcOutput(double param1, double param2)
|
||||
{
|
||||
double v;
|
||||
CvFuzzyFunction list;
|
||||
int size = (int)rules.size();
|
||||
|
||||
for(int i = 0; i < size; i++)
|
||||
{
|
||||
v = rules[i]->calcValue(param1, param2);
|
||||
if (v != 0)
|
||||
list.addCurve(rules[i]->getOutputCurve(), v);
|
||||
}
|
||||
v = list.calcValue();
|
||||
return v;
|
||||
};
|
||||
|
||||
CvFuzzyMeanShiftTracker::FuzzyResizer::FuzzyResizer()
|
||||
{
|
||||
CvFuzzyCurve *i1L, *i1M, *i1H;
|
||||
CvFuzzyCurve *oS, *oZE, *oE;
|
||||
CvFuzzyCurve *c;
|
||||
|
||||
double MedStart = 0.1, MedWidth = 0.15;
|
||||
|
||||
c = iInput.newCurve();
|
||||
c->addPoint(0, 1);
|
||||
c->addPoint(0.1, 0);
|
||||
c->setCentre(0);
|
||||
i1L = c;
|
||||
|
||||
c = iInput.newCurve();
|
||||
c->addPoint(0.05, 0);
|
||||
c->addPoint(MedStart, 1);
|
||||
c->addPoint(MedStart+MedWidth, 1);
|
||||
c->addPoint(MedStart+MedWidth+0.05, 0);
|
||||
c->setCentre(MedStart+(MedWidth/2));
|
||||
i1M = c;
|
||||
|
||||
c = iInput.newCurve();
|
||||
c->addPoint(MedStart+MedWidth, 0);
|
||||
c->addPoint(1, 1);
|
||||
c->addPoint(1000, 1);
|
||||
c->setCentre(1);
|
||||
i1H = c;
|
||||
|
||||
c = iOutput.newCurve();
|
||||
c->addPoint(-10000, 1);
|
||||
c->addPoint(-5, 1);
|
||||
c->addPoint(-0.5, 0);
|
||||
c->setCentre(-5);
|
||||
oS = c;
|
||||
|
||||
c = iOutput.newCurve();
|
||||
c->addPoint(-1, 0);
|
||||
c->addPoint(-0.05, 1);
|
||||
c->addPoint(0.05, 1);
|
||||
c->addPoint(1, 0);
|
||||
c->setCentre(0);
|
||||
oZE = c;
|
||||
|
||||
c = iOutput.newCurve();
|
||||
c->addPoint(-0.5, 0);
|
||||
c->addPoint(5, 1);
|
||||
c->addPoint(1000, 1);
|
||||
c->setCentre(5);
|
||||
oE = c;
|
||||
|
||||
fuzzyController.addRule(i1L, NULL, oS);
|
||||
fuzzyController.addRule(i1M, NULL, oZE);
|
||||
fuzzyController.addRule(i1H, NULL, oE);
|
||||
};
|
||||
|
||||
int CvFuzzyMeanShiftTracker::FuzzyResizer::calcOutput(double edgeDensity, double density)
|
||||
{
|
||||
return (int)fuzzyController.calcOutput(edgeDensity, density);
|
||||
};
|
||||
|
||||
CvFuzzyMeanShiftTracker::SearchWindow::SearchWindow()
|
||||
{
|
||||
x = 0;
|
||||
y = 0;
|
||||
width = 0;
|
||||
height = 0;
|
||||
maxWidth = 0;
|
||||
maxHeight = 0;
|
||||
xGc = 0;
|
||||
yGc = 0;
|
||||
m00 = 0;
|
||||
m01 = 0;
|
||||
m10 = 0;
|
||||
m11 = 0;
|
||||
m02 = 0;
|
||||
m20 = 0;
|
||||
ellipseHeight = 0;
|
||||
ellipseWidth = 0;
|
||||
ellipseAngle = 0;
|
||||
density = 0;
|
||||
depthLow = 0;
|
||||
depthHigh = 0;
|
||||
fuzzyResizer = NULL;
|
||||
};
|
||||
|
||||
CvFuzzyMeanShiftTracker::SearchWindow::~SearchWindow()
|
||||
{
|
||||
if (fuzzyResizer != NULL)
|
||||
delete fuzzyResizer;
|
||||
}
|
||||
|
||||
void CvFuzzyMeanShiftTracker::SearchWindow::setSize(int _x, int _y, int _width, int _height)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
width = _width;
|
||||
height = _height;
|
||||
|
||||
if (x < 0)
|
||||
x = 0;
|
||||
|
||||
if (y < 0)
|
||||
y = 0;
|
||||
|
||||
if (x + width > maxWidth)
|
||||
width = maxWidth - x;
|
||||
|
||||
if (y + height > maxHeight)
|
||||
height = maxHeight - y;
|
||||
};
|
||||
|
||||
void CvFuzzyMeanShiftTracker::SearchWindow::initDepthValues(IplImage *maskImage, IplImage *depthMap)
|
||||
{
|
||||
unsigned int d=0, mind = 0xFFFF, maxd = 0, m0 = 0, m1 = 0, mc, dd;
|
||||
unsigned char *data = NULL;
|
||||
unsigned short *depthData = NULL;
|
||||
|
||||
for (int j = 0; j < height; j++)
|
||||
{
|
||||
data = (unsigned char *)(maskImage->imageData + (maskImage->widthStep * (j + y)) + x);
|
||||
if (depthMap)
|
||||
depthData = (unsigned short *)(depthMap->imageData + (depthMap->widthStep * (j + y)) + x);
|
||||
|
||||
for (int i = 0; i < width; i++)
|
||||
{
|
||||
if (*data)
|
||||
{
|
||||
m0 += 1;
|
||||
|
||||
if (depthData)
|
||||
{
|
||||
if (*depthData)
|
||||
{
|
||||
m1 += d;
|
||||
if (d < mind)
|
||||
mind = d;
|
||||
if (d > maxd)
|
||||
maxd = d;
|
||||
}
|
||||
depthData++;
|
||||
}
|
||||
}
|
||||
data++;
|
||||
}
|
||||
}
|
||||
|
||||
if (m0 > 0)
|
||||
{
|
||||
mc = m1/m0;
|
||||
if ((mc - mind) > (maxd - mc))
|
||||
dd = maxd - mc;
|
||||
else
|
||||
dd = mc - mind;
|
||||
dd = dd - dd/10;
|
||||
depthHigh = mc + dd;
|
||||
depthLow = mc - dd;
|
||||
}
|
||||
else
|
||||
{
|
||||
depthHigh = 32000;
|
||||
depthLow = 0;
|
||||
}
|
||||
};
|
||||
|
||||
bool CvFuzzyMeanShiftTracker::SearchWindow::shift()
|
||||
{
|
||||
if ((xGc != (width/2)) || (yGc != (height/2)))
|
||||
{
|
||||
setSize(x + (xGc-(width/2)), y + (yGc-(height/2)), width, height);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
void CvFuzzyMeanShiftTracker::SearchWindow::extractInfo(IplImage *maskImage, IplImage *depthMap, bool initDepth)
|
||||
{
|
||||
m00 = 0;
|
||||
m10 = 0;
|
||||
m01 = 0;
|
||||
m11 = 0;
|
||||
density = 0;
|
||||
m02 = 0;
|
||||
m20 = 0;
|
||||
ellipseHeight = 0;
|
||||
ellipseWidth = 0;
|
||||
|
||||
maxWidth = maskImage->width;
|
||||
maxHeight = maskImage->height;
|
||||
|
||||
if (initDepth)
|
||||
initDepthValues(maskImage, depthMap);
|
||||
|
||||
unsigned char *maskData = NULL;
|
||||
unsigned short *depthData = NULL, depth;
|
||||
bool isOk;
|
||||
unsigned long count;
|
||||
|
||||
verticalEdgeLeft = 0;
|
||||
verticalEdgeRight = 0;
|
||||
horizontalEdgeTop = 0;
|
||||
horizontalEdgeBottom = 0;
|
||||
|
||||
for (int j = 0; j < height; j++)
|
||||
{
|
||||
maskData = (unsigned char *)(maskImage->imageData + (maskImage->widthStep * (j + y)) + x);
|
||||
if (depthMap)
|
||||
depthData = (unsigned short *)(depthMap->imageData + (depthMap->widthStep * (j + y)) + x);
|
||||
|
||||
count = 0;
|
||||
for (int i = 0; i < width; i++)
|
||||
{
|
||||
if (*maskData)
|
||||
{
|
||||
isOk = true;
|
||||
if (depthData)
|
||||
{
|
||||
depth = (*depthData);
|
||||
if ((depth > depthHigh) || (depth < depthLow))
|
||||
isOk = false;
|
||||
|
||||
depthData++;
|
||||
}
|
||||
|
||||
if (isOk)
|
||||
{
|
||||
m00++;
|
||||
m01 += j;
|
||||
m10 += i;
|
||||
m02 += (j * j);
|
||||
m20 += (i * i);
|
||||
m11 += (j * i);
|
||||
|
||||
if (i == 0)
|
||||
verticalEdgeLeft++;
|
||||
else if (i == width-1)
|
||||
verticalEdgeRight++;
|
||||
else if (j == 0)
|
||||
horizontalEdgeTop++;
|
||||
else if (j == height-1)
|
||||
horizontalEdgeBottom++;
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
maskData++;
|
||||
}
|
||||
}
|
||||
|
||||
if (m00 > 0)
|
||||
{
|
||||
xGc = (m10 / m00);
|
||||
yGc = (m01 / m00);
|
||||
|
||||
double a, b, c, e1, e2, e3;
|
||||
a = ((double)m20/(double)m00)-(xGc * xGc);
|
||||
b = 2*(((double)m11/(double)m00)-(xGc * yGc));
|
||||
c = ((double)m02/(double)m00)-(yGc * yGc);
|
||||
e1 = a+c;
|
||||
e3 = a-c;
|
||||
e2 = sqrt((b*b)+(e3*e3));
|
||||
ellipseHeight = int(sqrt(0.5*(e1+e2)));
|
||||
ellipseWidth = int(sqrt(0.5*(e1-e2)));
|
||||
if (e3 == 0)
|
||||
ellipseAngle = 0;
|
||||
else
|
||||
ellipseAngle = 0.5*atan(b/e3);
|
||||
|
||||
density = (double)m00/(double)(width * height);
|
||||
}
|
||||
else
|
||||
{
|
||||
xGc = width / 2;
|
||||
yGc = height / 2;
|
||||
ellipseHeight = 0;
|
||||
ellipseWidth = 0;
|
||||
ellipseAngle = 0;
|
||||
density = 0;
|
||||
}
|
||||
};
|
||||
|
||||
void CvFuzzyMeanShiftTracker::SearchWindow::getResizeAttribsEdgeDensityLinear(int &resizeDx, int &resizeDy, int &resizeDw, int &resizeDh) {
|
||||
int x1 = horizontalEdgeTop;
|
||||
int x2 = horizontalEdgeBottom;
|
||||
int y1 = verticalEdgeLeft;
|
||||
int y2 = verticalEdgeRight;
|
||||
int gx = (width*2)/5;
|
||||
int gy = (height*2)/5;
|
||||
int lx = width/10;
|
||||
int ly = height/10;
|
||||
|
||||
resizeDy = 0;
|
||||
resizeDh = 0;
|
||||
resizeDx = 0;
|
||||
resizeDw = 0;
|
||||
|
||||
if (x1 > gx) {
|
||||
resizeDy = -1;
|
||||
} else if (x1 < lx) {
|
||||
resizeDy = +1;
|
||||
}
|
||||
|
||||
if (x2 > gx) {
|
||||
resizeDh = resizeDy + 1;
|
||||
} else if (x2 < lx) {
|
||||
resizeDh = - (resizeDy + 1);
|
||||
} else {
|
||||
resizeDh = - resizeDy;
|
||||
}
|
||||
|
||||
if (y1 > gy) {
|
||||
resizeDx = -1;
|
||||
} else if (y1 < ly) {
|
||||
resizeDx = +1;
|
||||
}
|
||||
|
||||
if (y2 > gy) {
|
||||
resizeDw = resizeDx + 1;
|
||||
} else if (y2 < ly) {
|
||||
resizeDw = - (resizeDx + 1);
|
||||
} else {
|
||||
resizeDw = - resizeDx;
|
||||
}
|
||||
};
|
||||
|
||||
void CvFuzzyMeanShiftTracker::SearchWindow::getResizeAttribsInnerDensity(int &resizeDx, int &resizeDy, int &resizeDw, int &resizeDh)
|
||||
{
|
||||
int newWidth, newHeight, dx, dy;
|
||||
double px, py;
|
||||
newWidth = int(sqrt(double(m00)*1.3));
|
||||
newHeight = int(newWidth*1.2);
|
||||
dx = (newWidth - width);
|
||||
dy = (newHeight - height);
|
||||
px = (double)xGc/(double)width;
|
||||
py = (double)yGc/(double)height;
|
||||
resizeDx = (int)(px*dx);
|
||||
resizeDy = (int)(py*dy);
|
||||
resizeDw = (int)((1-px)*dx);
|
||||
resizeDh = (int)((1-py)*dy);
|
||||
};
|
||||
|
||||
void CvFuzzyMeanShiftTracker::SearchWindow::getResizeAttribsEdgeDensityFuzzy(int &resizeDx, int &resizeDy, int &resizeDw, int &resizeDh)
|
||||
{
|
||||
double dx1=0, dx2, dy1, dy2;
|
||||
|
||||
resizeDy = 0;
|
||||
resizeDh = 0;
|
||||
resizeDx = 0;
|
||||
resizeDw = 0;
|
||||
|
||||
if (fuzzyResizer == NULL)
|
||||
fuzzyResizer = new FuzzyResizer();
|
||||
|
||||
dx2 = fuzzyResizer->calcOutput(double(verticalEdgeRight)/double(height), density);
|
||||
if (dx1 == dx2)
|
||||
{
|
||||
resizeDx = int(-dx1);
|
||||
resizeDw = int(dx1+dx2);
|
||||
}
|
||||
|
||||
dy1 = fuzzyResizer->calcOutput(double(horizontalEdgeTop)/double(width), density);
|
||||
dy2 = fuzzyResizer->calcOutput(double(horizontalEdgeBottom)/double(width), density);
|
||||
|
||||
dx1 = fuzzyResizer->calcOutput(double(verticalEdgeLeft)/double(height), density);
|
||||
dx2 = fuzzyResizer->calcOutput(double(verticalEdgeRight)/double(height), density);
|
||||
//if (dx1 == dx2)
|
||||
{
|
||||
resizeDx = int(-dx1);
|
||||
resizeDw = int(dx1+dx2);
|
||||
}
|
||||
|
||||
dy1 = fuzzyResizer->calcOutput(double(horizontalEdgeTop)/double(width), density);
|
||||
dy2 = fuzzyResizer->calcOutput(double(horizontalEdgeBottom)/double(width), density);
|
||||
//if (dy1 == dy2)
|
||||
{
|
||||
resizeDy = int(-dy1);
|
||||
resizeDh = int(dy1+dy2);
|
||||
}
|
||||
};
|
||||
|
||||
bool CvFuzzyMeanShiftTracker::SearchWindow::meanShift(IplImage *maskImage, IplImage *depthMap, int maxIteration, bool initDepth)
|
||||
{
|
||||
numShifts = 0;
|
||||
do
|
||||
{
|
||||
extractInfo(maskImage, depthMap, initDepth);
|
||||
if (! shift())
|
||||
return true;
|
||||
} while (++numShifts < maxIteration);
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
void CvFuzzyMeanShiftTracker::findOptimumSearchWindow(SearchWindow &searchWindow, IplImage *maskImage, IplImage *depthMap, int maxIteration, int resizeMethod, bool initDepth)
|
||||
{
|
||||
int resizeDx, resizeDy, resizeDw, resizeDh;
|
||||
resizeDx = 0;
|
||||
resizeDy = 0;
|
||||
resizeDw = 0;
|
||||
resizeDh = 0;
|
||||
searchWindow.numIters = 0;
|
||||
for (int i = 0; i < maxIteration; i++)
|
||||
{
|
||||
searchWindow.numIters++;
|
||||
searchWindow.meanShift(maskImage, depthMap, MaxMeanShiftIteration, initDepth);
|
||||
switch (resizeMethod)
|
||||
{
|
||||
case rmEdgeDensityLinear :
|
||||
searchWindow.getResizeAttribsEdgeDensityLinear(resizeDx, resizeDy, resizeDw, resizeDh);
|
||||
break;
|
||||
case rmEdgeDensityFuzzy :
|
||||
//searchWindow.getResizeAttribsEdgeDensityLinear(resizeDx, resizeDy, resizeDw, resizeDh);
|
||||
searchWindow.getResizeAttribsEdgeDensityFuzzy(resizeDx, resizeDy, resizeDw, resizeDh);
|
||||
break;
|
||||
case rmInnerDensity :
|
||||
searchWindow.getResizeAttribsInnerDensity(resizeDx, resizeDy, resizeDw, resizeDh);
|
||||
break;
|
||||
default:
|
||||
searchWindow.getResizeAttribsEdgeDensityLinear(resizeDx, resizeDy, resizeDw, resizeDh);
|
||||
}
|
||||
|
||||
searchWindow.ldx = resizeDx;
|
||||
searchWindow.ldy = resizeDy;
|
||||
searchWindow.ldw = resizeDw;
|
||||
searchWindow.ldh = resizeDh;
|
||||
|
||||
if ((resizeDx == 0) && (resizeDy == 0) && (resizeDw == 0) && (resizeDh == 0))
|
||||
break;
|
||||
|
||||
searchWindow.setSize(searchWindow.x + resizeDx, searchWindow.y + resizeDy, searchWindow.width + resizeDw, searchWindow.height + resizeDh);
|
||||
}
|
||||
};
|
||||
|
||||
CvFuzzyMeanShiftTracker::CvFuzzyMeanShiftTracker()
|
||||
{
|
||||
searchMode = tsSetWindow;
|
||||
};
|
||||
|
||||
CvFuzzyMeanShiftTracker::~CvFuzzyMeanShiftTracker()
|
||||
{
|
||||
// nothing to do
|
||||
};
|
||||
|
||||
void CvFuzzyMeanShiftTracker::track(IplImage *maskImage, IplImage *depthMap, int resizeMethod, bool resetSearch, int minKernelMass)
|
||||
{
|
||||
bool initDepth = false;
|
||||
|
||||
if (resetSearch)
|
||||
searchMode = tsSetWindow;
|
||||
|
||||
switch (searchMode)
|
||||
{
|
||||
case tsDisabled:
|
||||
return;
|
||||
case tsSearching:
|
||||
return;
|
||||
case tsSetWindow:
|
||||
kernel.maxWidth = maskImage->width;
|
||||
kernel.maxHeight = maskImage->height;
|
||||
kernel.setSize(0, 0, maskImage->width, maskImage->height);
|
||||
initDepth = true;
|
||||
case tsTracking:
|
||||
searchMode = tsSearching;
|
||||
findOptimumSearchWindow(kernel, maskImage, depthMap, MaxSetSizeIteration, resizeMethod, initDepth);
|
||||
if ((kernel.density == 0) || (kernel.m00 < minKernelMass))
|
||||
searchMode = tsSetWindow;
|
||||
else
|
||||
searchMode = tsTracking;
|
||||
}
|
||||
};
|
||||
|
340
modules/contrib/src/octree.cpp
Normal file
340
modules/contrib/src/octree.cpp
Normal file
@@ -0,0 +1,340 @@
|
||||
/*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.
|
||||
// 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*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include <limits>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
const size_t MAX_STACK_SIZE = 255;
|
||||
const size_t MAX_LEAFS = 8;
|
||||
|
||||
bool checkIfNodeOutsideSphere(const Octree::Node& node, const Point3f& c, float r)
|
||||
{
|
||||
if (node.x_max < (c.x - r) || node.y_max < (c.y - r) || node.z_max < (c.z - r))
|
||||
return true;
|
||||
|
||||
if ((c.x + r) < node.x_min || (c.y + r) < node.y_min || (c.z + r) < node.z_min)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool checkIfNodeInsideSphere(const Octree::Node& node, const Point3f& c, float r)
|
||||
{
|
||||
r *= r;
|
||||
|
||||
float d2_xmin = (node.x_min - c.x) * (node.x_min - c.x);
|
||||
float d2_ymin = (node.y_min - c.y) * (node.y_min - c.y);
|
||||
float d2_zmin = (node.z_min - c.z) * (node.z_min - c.z);
|
||||
|
||||
if (d2_xmin + d2_ymin + d2_zmin > r)
|
||||
return false;
|
||||
|
||||
float d2_zmax = (node.z_max - c.z) * (node.z_max - c.z);
|
||||
|
||||
if (d2_xmin + d2_ymin + d2_zmax > r)
|
||||
return false;
|
||||
|
||||
float d2_ymax = (node.y_max - c.y) * (node.y_max - c.y);
|
||||
|
||||
if (d2_xmin + d2_ymax + d2_zmin > r)
|
||||
return false;
|
||||
|
||||
if (d2_xmin + d2_ymax + d2_zmax > r)
|
||||
return false;
|
||||
|
||||
float d2_xmax = (node.x_max - c.x) * (node.x_max - c.x);
|
||||
|
||||
if (d2_xmax + d2_ymin + d2_zmin > r)
|
||||
return false;
|
||||
|
||||
if (d2_xmax + d2_ymin + d2_zmax > r)
|
||||
return false;
|
||||
|
||||
if (d2_xmax + d2_ymax + d2_zmin > r)
|
||||
return false;
|
||||
|
||||
if (d2_xmax + d2_ymax + d2_zmax > r)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void fillMinMax(const vector<Point3f>& points, Octree::Node& node)
|
||||
{
|
||||
node.x_max = node.y_max = node.z_max = std::numeric_limits<float>::min();
|
||||
node.x_min = node.y_min = node.z_min = std::numeric_limits<float>::max();
|
||||
|
||||
for (size_t i = 0; i < points.size(); ++i)
|
||||
{
|
||||
const Point3f& point = points[i];
|
||||
|
||||
if (node.x_max < point.x)
|
||||
node.x_max = point.x;
|
||||
|
||||
if (node.y_max < point.y)
|
||||
node.y_max = point.y;
|
||||
|
||||
if (node.z_max < point.z)
|
||||
node.z_max = point.z;
|
||||
|
||||
if (node.x_min > point.x)
|
||||
node.x_min = point.x;
|
||||
|
||||
if (node.y_min > point.y)
|
||||
node.y_min = point.y;
|
||||
|
||||
if (node.z_min > point.z)
|
||||
node.z_min = point.z;
|
||||
}
|
||||
}
|
||||
|
||||
size_t findSubboxForPoint(const Point3f& point, const Octree::Node& node)
|
||||
{
|
||||
size_t ind_x = point.x < (node.x_max + node.x_min) / 2 ? 0 : 1;
|
||||
size_t ind_y = point.y < (node.y_max + node.y_min) / 2 ? 0 : 1;
|
||||
size_t ind_z = point.z < (node.z_max + node.z_min) / 2 ? 0 : 1;
|
||||
|
||||
return (ind_x << 2) + (ind_y << 1) + (ind_z << 0);
|
||||
}
|
||||
void initChildBox(const Octree::Node& parent, size_t boxIndex, Octree::Node& child)
|
||||
{
|
||||
child.x_min = child.x_max = (parent.x_max + parent.x_min) / 2;
|
||||
child.y_min = child.y_max = (parent.y_max + parent.y_min) / 2;
|
||||
child.z_min = child.z_max = (parent.z_max + parent.z_min) / 2;
|
||||
|
||||
if ((boxIndex >> 0) & 1)
|
||||
child.z_max = parent.z_max;
|
||||
else
|
||||
child.z_min = parent.z_min;
|
||||
|
||||
if ((boxIndex >> 1) & 1)
|
||||
child.y_max = parent.y_max;
|
||||
else
|
||||
child.y_min = parent.y_min;
|
||||
|
||||
if ((boxIndex >> 2) & 1)
|
||||
child.x_max = parent.x_max;
|
||||
else
|
||||
child.x_min = parent.x_min;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////// Octree //////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Octree::Octree()
|
||||
{
|
||||
}
|
||||
|
||||
Octree::Octree(const vector<Point3f>& points3d, int maxLevels, int minPoints)
|
||||
{
|
||||
buildTree(points3d, maxLevels, minPoints);
|
||||
}
|
||||
|
||||
Octree::~Octree()
|
||||
{
|
||||
}
|
||||
|
||||
void Octree::getPointsWithinSphere(const Point3f& center, float radius, vector<Point3f>& out) const
|
||||
{
|
||||
out.clear();
|
||||
|
||||
if (nodes.empty())
|
||||
return;
|
||||
|
||||
int stack[MAX_STACK_SIZE];
|
||||
int pos = 0;
|
||||
stack[pos] = 0;
|
||||
|
||||
while (pos >= 0)
|
||||
{
|
||||
const Node& cur = nodes[stack[pos--]];
|
||||
|
||||
if (checkIfNodeOutsideSphere(cur, center, radius))
|
||||
continue;
|
||||
|
||||
if (checkIfNodeInsideSphere(cur, center, radius))
|
||||
{
|
||||
size_t sz = out.size();
|
||||
out.resize(sz + cur.end - cur.begin);
|
||||
for (int i = cur.begin; i < cur.end; ++i)
|
||||
out[sz++] = points[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cur.isLeaf)
|
||||
{
|
||||
double r2 = radius * radius;
|
||||
size_t sz = out.size();
|
||||
out.resize(sz + (cur.end - cur.begin));
|
||||
|
||||
for (int i = cur.begin; i < cur.end; ++i)
|
||||
{
|
||||
const Point3f& point = points[i];
|
||||
|
||||
double dx = (point.x - center.x);
|
||||
double dy = (point.y - center.y);
|
||||
double dz = (point.z - center.z);
|
||||
|
||||
double dist2 = dx * dx + dy * dy + dz * dz;
|
||||
|
||||
if (dist2 < r2)
|
||||
out[sz++] = point;
|
||||
};
|
||||
out.resize(sz);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cur.children[0])
|
||||
stack[++pos] = cur.children[0];
|
||||
|
||||
if (cur.children[1])
|
||||
stack[++pos] = cur.children[1];
|
||||
|
||||
if (cur.children[2])
|
||||
stack[++pos] = cur.children[2];
|
||||
|
||||
if (cur.children[3])
|
||||
stack[++pos] = cur.children[3];
|
||||
|
||||
if (cur.children[4])
|
||||
stack[++pos] = cur.children[4];
|
||||
|
||||
if (cur.children[5])
|
||||
stack[++pos] = cur.children[5];
|
||||
|
||||
if (cur.children[6])
|
||||
stack[++pos] = cur.children[6];
|
||||
|
||||
if (cur.children[7])
|
||||
stack[++pos] = cur.children[7];
|
||||
}
|
||||
}
|
||||
|
||||
void Octree::buildTree(const vector<Point3f>& points3d, int maxLevels, int minPoints)
|
||||
{
|
||||
assert((size_t)maxLevels * 8 < MAX_STACK_SIZE);
|
||||
points.resize(points3d.size());
|
||||
std::copy(points3d.begin(), points3d.end(), points.begin());
|
||||
this->minPoints = minPoints;
|
||||
|
||||
nodes.clear();
|
||||
nodes.push_back(Node());
|
||||
Node& root = nodes[0];
|
||||
fillMinMax(points, root);
|
||||
|
||||
root.isLeaf = true;
|
||||
root.maxLevels = maxLevels;
|
||||
root.begin = 0;
|
||||
root.end = (int)points.size();
|
||||
for (size_t i = 0; i < MAX_LEAFS; i++)
|
||||
root.children[i] = 0;
|
||||
|
||||
if (maxLevels != 1 && (root.end - root.begin) > minPoints)
|
||||
{
|
||||
root.isLeaf = false;
|
||||
buildNext(0);
|
||||
}
|
||||
}
|
||||
|
||||
void Octree::buildNext(size_t nodeInd)
|
||||
{
|
||||
size_t size = nodes[nodeInd].end - nodes[nodeInd].begin;
|
||||
|
||||
vector<size_t> boxBorders(MAX_LEAFS+1, 0);
|
||||
vector<size_t> boxIndices(size);
|
||||
vector<Point3f> tempPoints(size);
|
||||
|
||||
for (int i = nodes[nodeInd].begin, j = 0; i < nodes[nodeInd].end; ++i, ++j)
|
||||
{
|
||||
const Point3f& p = points[i];
|
||||
|
||||
size_t subboxInd = findSubboxForPoint(p, nodes[nodeInd]);
|
||||
|
||||
boxBorders[subboxInd+1]++;
|
||||
boxIndices[j] = subboxInd;
|
||||
tempPoints[j] = p;
|
||||
}
|
||||
|
||||
for (size_t i = 1; i < boxBorders.size(); ++i)
|
||||
boxBorders[i] += boxBorders[i-1];
|
||||
|
||||
vector<size_t> writeInds(boxBorders.begin(), boxBorders.end());
|
||||
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
size_t boxIndex = boxIndices[i];
|
||||
Point3f& curPoint = tempPoints[i];
|
||||
|
||||
size_t copyTo = nodes[nodeInd].begin + writeInds[boxIndex]++;
|
||||
points[copyTo] = curPoint;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < MAX_LEAFS; ++i)
|
||||
{
|
||||
if (boxBorders[i] == boxBorders[i+1])
|
||||
continue;
|
||||
|
||||
nodes.push_back(Node());
|
||||
Node& child = nodes.back();
|
||||
initChildBox(nodes[nodeInd], i, child);
|
||||
|
||||
child.isLeaf = true;
|
||||
child.maxLevels = nodes[nodeInd].maxLevels - 1;
|
||||
child.begin = nodes[nodeInd].begin + (int)boxBorders[i+0];
|
||||
child.end = nodes[nodeInd].begin + (int)boxBorders[i+1];
|
||||
for (size_t k = 0; k < MAX_LEAFS; k++)
|
||||
child.children[k] = 0;
|
||||
|
||||
nodes[nodeInd].children[i] = (int)(nodes.size() - 1);
|
||||
|
||||
if (child.maxLevels != 1 && (child.end - child.begin) > minPoints)
|
||||
{
|
||||
child.isLeaf = false;
|
||||
buildNext(nodes.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
44
modules/contrib/src/precomp.cpp
Normal file
44
modules/contrib/src/precomp.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
/*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*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
/* End of file. */
|
57
modules/contrib/src/precomp.hpp
Normal file
57
modules/contrib/src/precomp.hpp
Normal file
@@ -0,0 +1,57 @@
|
||||
/*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.
|
||||
// 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_PRECOMP_H__
|
||||
#define __OPENCV_PRECOMP_H__
|
||||
|
||||
#if _MSC_VER >= 1200
|
||||
#pragma warning( disable: 4251 4710 4711 4514 4996 ) /* function AAA selected for automatic inline expansion */
|
||||
#endif
|
||||
|
||||
#include "opencv2/contrib/contrib.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
#include "opencv2/objdetect/objdetect.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/imgproc/imgproc_c.h"
|
||||
#include "opencv2/core/internal.hpp"
|
||||
|
||||
#endif
|
364
modules/contrib/src/quadsubpix.cpp
Normal file
364
modules/contrib/src/quadsubpix.cpp
Normal file
@@ -0,0 +1,364 @@
|
||||
/*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*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
//#define _SUBPIX_VERBOSE
|
||||
|
||||
#undef max
|
||||
|
||||
namespace cv {
|
||||
|
||||
|
||||
void drawCircles(Mat& img, const vector<Point2f>& corners, const vector<float>& radius)
|
||||
{
|
||||
for(size_t i = 0; i < corners.size(); i++)
|
||||
{
|
||||
circle(img, corners[i], cvRound(radius[i]), CV_RGB(255, 0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
int histQuantile(const MatND& hist, float quantile)
|
||||
{
|
||||
if(hist.dims > 1) return -1; // works for 1D histograms only
|
||||
|
||||
float cur_sum = 0;
|
||||
float total_sum = (float)sum(hist).val[0];
|
||||
float quantile_sum = total_sum*quantile;
|
||||
for(int j = 0; j < hist.size[0]; j++)
|
||||
{
|
||||
cur_sum += (float)hist.at<double>(j);
|
||||
if(cur_sum > quantile_sum)
|
||||
{
|
||||
return j;
|
||||
}
|
||||
}
|
||||
|
||||
return hist.size[0] - 1;
|
||||
}
|
||||
|
||||
bool is_smaller(const std::pair<int, float>& p1, const std::pair<int, float>& p2)
|
||||
{
|
||||
return p1.second < p2.second;
|
||||
}
|
||||
|
||||
void orderContours(const vector<vector<Point> >& contours, Point2f point, vector<std::pair<int, float> >& order)
|
||||
{
|
||||
order.clear();
|
||||
for(size_t i = 0; i < contours.size(); i++)
|
||||
{
|
||||
double min_dist = std::numeric_limits<double>::max();
|
||||
for(size_t j = 0; j < contours[i].size(); j++)
|
||||
{
|
||||
double dist = norm(Point2f((float)contours[i][j].x, (float)contours[i][j].y) - point);
|
||||
min_dist = MIN(min_dist, dist);
|
||||
}
|
||||
order.push_back(std::pair<int, float>(i, (float)min_dist));
|
||||
}
|
||||
|
||||
std::sort(order.begin(), order.end(), is_smaller);
|
||||
}
|
||||
|
||||
// fit second order curve to a set of 2D points
|
||||
void fitCurve2Order(const vector<Point2f>& /*points*/, vector<float>& /*curve*/)
|
||||
{
|
||||
// TBD
|
||||
}
|
||||
|
||||
void findCurvesCross(const vector<float>& /*curve1*/, const vector<float>& /*curve2*/, Point2f& /*cross_point*/)
|
||||
{
|
||||
}
|
||||
|
||||
void findLinesCrossPoint(Point2f origin1, Point2f dir1, Point2f origin2, Point2f dir2, Point2f& cross_point)
|
||||
{
|
||||
float det = dir2.x*dir1.y - dir2.y*dir1.x;
|
||||
Point2f offset = origin2 - origin1;
|
||||
|
||||
float alpha = (dir2.x*offset.y - dir2.y*offset.x)/det;
|
||||
cross_point = origin1 + dir1*alpha;
|
||||
}
|
||||
|
||||
void findCorner(const vector<Point>& contour, Point2f point, Point2f& corner)
|
||||
{
|
||||
// find the nearest point
|
||||
double min_dist = std::numeric_limits<double>::max();
|
||||
int min_idx = -1;
|
||||
|
||||
Rect brect = boundingRect(Mat(contour));
|
||||
|
||||
// find corner idx
|
||||
for(size_t i = 0; i < contour.size(); i++)
|
||||
{
|
||||
double dist = norm(Point2f((float)contour[i].x, (float)contour[i].y) - point);
|
||||
if(dist < min_dist)
|
||||
{
|
||||
min_dist = dist;
|
||||
min_idx = i;
|
||||
}
|
||||
}
|
||||
assert(min_idx >= 0);
|
||||
|
||||
// temporary solution, have to make something more precise
|
||||
corner = contour[min_idx];
|
||||
return;
|
||||
}
|
||||
|
||||
void findCorner(const vector<Point2f>& contour, Point2f point, Point2f& corner)
|
||||
{
|
||||
// find the nearest point
|
||||
double min_dist = std::numeric_limits<double>::max();
|
||||
int min_idx = -1;
|
||||
|
||||
Rect brect = boundingRect(Mat(contour));
|
||||
|
||||
// find corner idx
|
||||
for(size_t i = 0; i < contour.size(); i++)
|
||||
{
|
||||
double dist = norm(contour[i] - point);
|
||||
if(dist < min_dist)
|
||||
{
|
||||
min_dist = dist;
|
||||
min_idx = i;
|
||||
}
|
||||
}
|
||||
assert(min_idx >= 0);
|
||||
|
||||
// temporary solution, have to make something more precise
|
||||
corner = contour[min_idx];
|
||||
return;
|
||||
}
|
||||
|
||||
int segment_hist_max(const MatND& hist, int& low_thresh, int& high_thresh)
|
||||
{
|
||||
Mat bw;
|
||||
//const double max_bell_width = 20; // we expect two bells with width bounded above
|
||||
//const double min_bell_width = 5; // and below
|
||||
|
||||
double total_sum = sum(hist).val[0];
|
||||
//double thresh = total_sum/(2*max_bell_width)*0.25f; // quarter of a bar inside a bell
|
||||
|
||||
// threshold(hist, bw, thresh, 255.0, CV_THRESH_BINARY);
|
||||
|
||||
double quantile_sum = 0.0;
|
||||
//double min_quantile = 0.2;
|
||||
double low_sum = 0;
|
||||
double max_segment_length = 0;
|
||||
int max_start_x = -1;
|
||||
int max_end_x = -1;
|
||||
int start_x = 0;
|
||||
const double out_of_bells_fraction = 0.1;
|
||||
for(int x = 0; x < hist.size[0]; x++)
|
||||
{
|
||||
quantile_sum += hist.at<double>(x);
|
||||
if(quantile_sum < 0.2*total_sum) continue;
|
||||
|
||||
if(quantile_sum - low_sum > out_of_bells_fraction*total_sum)
|
||||
{
|
||||
if(max_segment_length < x - start_x)
|
||||
{
|
||||
max_segment_length = x - start_x;
|
||||
max_start_x = start_x;
|
||||
max_end_x = x;
|
||||
}
|
||||
|
||||
low_sum = quantile_sum;
|
||||
start_x = x;
|
||||
}
|
||||
}
|
||||
|
||||
if(start_x == -1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
low_thresh = cvRound(max_start_x + 0.25*(max_end_x - max_start_x));
|
||||
high_thresh = cvRound(max_start_x + 0.75*(max_end_x - max_start_x));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool find4QuadCornerSubpix(const Mat& img, std::vector<Point2f>& corners, Size region_size)
|
||||
{
|
||||
const int nbins = 256;
|
||||
float ranges[] = {0, 256};
|
||||
const float* _ranges = ranges;
|
||||
MatND hist;
|
||||
|
||||
#if defined(_SUBPIX_VERBOSE)
|
||||
vector<float> radius;
|
||||
radius.assign(corners.size(), 0.0f);
|
||||
#endif //_SUBPIX_VERBOSE
|
||||
|
||||
|
||||
Mat black_comp, white_comp;
|
||||
for(size_t i = 0; i < corners.size(); i++)
|
||||
{
|
||||
int channels = 0;
|
||||
Rect roi(cvRound(corners[i].x - region_size.width), cvRound(corners[i].y - region_size.height),
|
||||
region_size.width*2 + 1, region_size.height*2 + 1);
|
||||
Mat img_roi = img(roi);
|
||||
calcHist(&img_roi, 1, &channels, Mat(), hist, 1, &nbins, &_ranges);
|
||||
|
||||
#if 0
|
||||
int black_thresh = histQuantile(hist, 0.45f);
|
||||
int white_thresh = histQuantile(hist, 0.55f);
|
||||
#else
|
||||
int black_thresh, white_thresh;
|
||||
segment_hist_max(hist, black_thresh, white_thresh);
|
||||
#endif
|
||||
|
||||
threshold(img, black_comp, black_thresh, 255.0, CV_THRESH_BINARY_INV);
|
||||
threshold(img, white_comp, white_thresh, 255.0, CV_THRESH_BINARY);
|
||||
|
||||
const int erode_count = 1;
|
||||
erode(black_comp, black_comp, Mat(), Point(-1, -1), erode_count);
|
||||
erode(white_comp, white_comp, Mat(), Point(-1, -1), erode_count);
|
||||
|
||||
#if defined(_SUBPIX_VERBOSE)
|
||||
namedWindow("roi", 1);
|
||||
imshow("roi", img_roi);
|
||||
imwrite("test.jpg", img);
|
||||
namedWindow("black", 1);
|
||||
imshow("black", black_comp);
|
||||
namedWindow("white", 1);
|
||||
imshow("white", white_comp);
|
||||
cvWaitKey(0);
|
||||
imwrite("black.jpg", black_comp);
|
||||
imwrite("white.jpg", white_comp);
|
||||
#endif
|
||||
|
||||
|
||||
vector<vector<Point> > white_contours, black_contours;
|
||||
vector<Vec4i> white_hierarchy, black_hierarchy;
|
||||
findContours(black_comp, black_contours, black_hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
|
||||
findContours(white_comp, white_contours, white_hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
|
||||
|
||||
if(black_contours.size() < 5 || white_contours.size() < 5) continue;
|
||||
|
||||
// find two white and black blobs that are close to the input point
|
||||
vector<std::pair<int, float> > white_order, black_order;
|
||||
orderContours(black_contours, corners[i], black_order);
|
||||
orderContours(white_contours, corners[i], white_order);
|
||||
|
||||
const float max_dist = 10.0f;
|
||||
if(black_order[0].second > max_dist || black_order[1].second > max_dist ||
|
||||
white_order[0].second > max_dist || white_order[1].second > max_dist)
|
||||
{
|
||||
continue; // there will be no improvement in this corner position
|
||||
}
|
||||
|
||||
const vector<Point>* quads[4] = {&black_contours[black_order[0].first], &black_contours[black_order[1].first],
|
||||
&white_contours[white_order[0].first], &white_contours[white_order[1].first]};
|
||||
vector<Point2f> quads_approx[4];
|
||||
Point2f quad_corners[4];
|
||||
for(int k = 0; k < 4; k++)
|
||||
{
|
||||
#if 1
|
||||
vector<Point2f> temp;
|
||||
for(size_t j = 0; j < quads[k]->size(); j++) temp.push_back((*quads[k])[j]);
|
||||
approxPolyDP(Mat(temp), quads_approx[k], 0.5, true);
|
||||
|
||||
findCorner(quads_approx[k], corners[i], quad_corners[k]);
|
||||
#else
|
||||
findCorner(*quads[k], corners[i], quad_corners[k]);
|
||||
#endif
|
||||
quad_corners[k] += Point2f(0.5f, 0.5f);
|
||||
}
|
||||
|
||||
// cross two lines
|
||||
Point2f origin1 = quad_corners[0];
|
||||
Point2f dir1 = quad_corners[1] - quad_corners[0];
|
||||
Point2f origin2 = quad_corners[2];
|
||||
Point2f dir2 = quad_corners[3] - quad_corners[2];
|
||||
double angle = acos(dir1.dot(dir2)/(norm(dir1)*norm(dir2)));
|
||||
if(cvIsNaN(angle) || cvIsInf(angle) || angle < 0.5 || angle > CV_PI - 0.5) continue;
|
||||
|
||||
findLinesCrossPoint(origin1, dir1, origin2, dir2, corners[i]);
|
||||
|
||||
#if defined(_SUBPIX_VERBOSE)
|
||||
radius[i] = norm(corners[i] - ground_truth_corners[ground_truth_idx])*6;
|
||||
|
||||
#if 1
|
||||
Mat test(img.size(), CV_32FC3);
|
||||
cvtColor(img, test, CV_GRAY2RGB);
|
||||
// line(test, quad_corners[0] - corners[i] + Point2f(30, 30), quad_corners[1] - corners[i] + Point2f(30, 30), cvScalar(0, 255, 0));
|
||||
// line(test, quad_corners[2] - corners[i] + Point2f(30, 30), quad_corners[3] - corners[i] + Point2f(30, 30), cvScalar(0, 255, 0));
|
||||
vector<vector<Point> > contrs;
|
||||
contrs.resize(1);
|
||||
for(int k = 0; k < 4; k++)
|
||||
{
|
||||
//contrs[0] = quads_approx[k];
|
||||
contrs[0].clear();
|
||||
for(size_t j = 0; j < quads_approx[k].size(); j++) contrs[0].push_back(quads_approx[k][j]);
|
||||
drawContours(test, contrs, 0, CV_RGB(0, 0, 255), 1, 1, vector<Vec4i>(), 2);
|
||||
circle(test, quad_corners[k], 0.5, CV_RGB(255, 0, 0));
|
||||
}
|
||||
Mat test1 = test(Rect(corners[i].x - 30, corners[i].y - 30, 60, 60));
|
||||
namedWindow("1", 1);
|
||||
imshow("1", test1);
|
||||
imwrite("test.jpg", test);
|
||||
waitKey(0);
|
||||
#endif
|
||||
#endif //_SUBPIX_VERBOSE
|
||||
|
||||
}
|
||||
|
||||
#if defined(_SUBPIX_VERBOSE)
|
||||
Mat test(img.size(), CV_32FC3);
|
||||
cvtColor(img, test, CV_GRAY2RGB);
|
||||
drawCircles(test, corners, radius);
|
||||
|
||||
namedWindow("corners", 1);
|
||||
imshow("corners", test);
|
||||
waitKey();
|
||||
#endif //_SUBPIX_VERBOSE
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}; // namespace std
|
259
modules/contrib/src/selfsimilarity.cpp
Normal file
259
modules/contrib/src/selfsimilarity.cpp
Normal file
@@ -0,0 +1,259 @@
|
||||
// This is based on Rainer Lienhart contribution. Below is the original copyright:
|
||||
//
|
||||
/*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.
|
||||
//
|
||||
//
|
||||
// University of Augsburg License Agreement
|
||||
// For Open Source MultiMedia Computing (MMC) Library
|
||||
//
|
||||
// Copyright (C) 2007, University of Augsburg, Germany, 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 University of Augsburg, Germany 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 University of Augsburg, Germany 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*/
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
// Author: Rainer Lienhart
|
||||
// email: Rainer.Lienhart@informatik.uni-augsburg.de
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
|
||||
// Please cite the following two papers:
|
||||
// 1. Shechtman, E., Irani, M.:
|
||||
// Matching local self-similarities across images and videos.
|
||||
// CVPR, (2007)
|
||||
// 2. Eva Horster, Thomas Greif, Rainer Lienhart, Malcolm Slaney.
|
||||
// Comparing Local Feature Descriptors in pLSA-Based Image Models.
|
||||
// 30th Annual Symposium of the German Association for
|
||||
// Pattern Recognition (DAGM) 2008, Munich, Germany, June 2008.
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
SelfSimDescriptor::SelfSimDescriptor()
|
||||
{
|
||||
smallSize = DEFAULT_SMALL_SIZE;
|
||||
largeSize = DEFAULT_LARGE_SIZE;
|
||||
numberOfAngles = DEFAULT_NUM_ANGLES;
|
||||
startDistanceBucket = DEFAULT_START_DISTANCE_BUCKET;
|
||||
numberOfDistanceBuckets = DEFAULT_NUM_DISTANCE_BUCKETS;
|
||||
}
|
||||
|
||||
SelfSimDescriptor::SelfSimDescriptor(int _ssize, int _lsize,
|
||||
int _startDistanceBucket,
|
||||
int _numberOfDistanceBuckets, int _numberOfAngles)
|
||||
{
|
||||
smallSize = _ssize;
|
||||
largeSize = _lsize;
|
||||
startDistanceBucket = _startDistanceBucket;
|
||||
numberOfDistanceBuckets = _numberOfDistanceBuckets;
|
||||
numberOfAngles = _numberOfAngles;
|
||||
}
|
||||
|
||||
SelfSimDescriptor::SelfSimDescriptor(const SelfSimDescriptor& ss)
|
||||
{
|
||||
smallSize = ss.smallSize;
|
||||
largeSize = ss.largeSize;
|
||||
startDistanceBucket = ss.startDistanceBucket;
|
||||
numberOfDistanceBuckets = ss.numberOfDistanceBuckets;
|
||||
numberOfAngles = ss.numberOfAngles;
|
||||
}
|
||||
|
||||
SelfSimDescriptor::~SelfSimDescriptor()
|
||||
{
|
||||
}
|
||||
|
||||
SelfSimDescriptor& SelfSimDescriptor::operator = (const SelfSimDescriptor& ss)
|
||||
{
|
||||
if( this != &ss )
|
||||
{
|
||||
smallSize = ss.smallSize;
|
||||
largeSize = ss.largeSize;
|
||||
startDistanceBucket = ss.startDistanceBucket;
|
||||
numberOfDistanceBuckets = ss.numberOfDistanceBuckets;
|
||||
numberOfAngles = ss.numberOfAngles;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
size_t SelfSimDescriptor::getDescriptorSize() const
|
||||
{
|
||||
return numberOfAngles*(numberOfDistanceBuckets - startDistanceBucket);
|
||||
}
|
||||
|
||||
Size SelfSimDescriptor::getGridSize( Size imgSize, Size winStride ) const
|
||||
{
|
||||
winStride.width = std::max(winStride.width, 1);
|
||||
winStride.height = std::max(winStride.height, 1);
|
||||
int border = largeSize/2 + smallSize/2;
|
||||
return Size(std::max(imgSize.width - border*2 + winStride.width - 1, 0)/winStride.width,
|
||||
std::max(imgSize.height - border*2 + winStride.height - 1, 0)/winStride.height);
|
||||
}
|
||||
|
||||
// TODO: optimized with SSE2
|
||||
void SelfSimDescriptor::SSD(const Mat& img, Point pt, Mat& ssd) const
|
||||
{
|
||||
int x, y, dx, dy, r0 = largeSize/2, r1 = smallSize/2;
|
||||
int step = img.step;
|
||||
for( y = -r0; y <= r0; y++ )
|
||||
{
|
||||
float* sptr = ssd.ptr<float>(y+r0) + r0;
|
||||
for( x = -r0; x <= r0; x++ )
|
||||
{
|
||||
int sum = 0;
|
||||
const uchar* src0 = img.ptr<uchar>(y + pt.y - r1) + x + pt.x;
|
||||
const uchar* src1 = img.ptr<uchar>(pt.y - r1) + pt.x;
|
||||
for( dy = -r1; dy <= r1; dy++, src0 += step, src1 += step )
|
||||
for( dx = -r1; dx <= r1; dx++ )
|
||||
{
|
||||
int t = src0[dx] - src1[dx];
|
||||
sum += t*t;
|
||||
}
|
||||
sptr[x] = (float)sum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SelfSimDescriptor::compute(const Mat& img, vector<float>& descriptors, Size winStride,
|
||||
const vector<Point>& locations) const
|
||||
{
|
||||
CV_Assert( img.depth() == CV_8U );
|
||||
|
||||
winStride.width = std::max(winStride.width, 1);
|
||||
winStride.height = std::max(winStride.height, 1);
|
||||
Size gridSize = getGridSize(img.size(), winStride);
|
||||
int i, nwindows = locations.empty() ? gridSize.width*gridSize.height : (int)locations.size();
|
||||
int border = largeSize/2 + smallSize/2;
|
||||
int fsize = (int)getDescriptorSize();
|
||||
vector<float> tempFeature(fsize+1);
|
||||
descriptors.resize(fsize*nwindows + 1);
|
||||
Mat ssd(largeSize, largeSize, CV_32F), mappingMask;
|
||||
computeLogPolarMapping(mappingMask);
|
||||
|
||||
#if 0 //def _OPENMP
|
||||
int nthreads = cvGetNumThreads();
|
||||
#pragma omp parallel for num_threads(nthreads)
|
||||
#endif
|
||||
for( i = 0; i < nwindows; i++ )
|
||||
{
|
||||
Point pt;
|
||||
float* feature0 = &descriptors[fsize*i];
|
||||
float* feature = &tempFeature[0];
|
||||
int x, y, j;
|
||||
|
||||
if( !locations.empty() )
|
||||
{
|
||||
pt = locations[i];
|
||||
if( pt.x < border || pt.x >= img.cols - border ||
|
||||
pt.y < border || pt.y >= img.rows - border )
|
||||
{
|
||||
for( j = 0; j < fsize; j++ )
|
||||
feature0[j] = 0.f;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
pt = Point((i % gridSize.width)*winStride.width + border,
|
||||
(i / gridSize.width)*winStride.height + border);
|
||||
|
||||
SSD(img, pt, ssd);
|
||||
|
||||
// Determine in the local neighborhood the largest difference and use for normalization
|
||||
float var_noise = 1000.f;
|
||||
for( y = -1; y <= 1 ; y++ )
|
||||
for( x = -1 ; x <= 1 ; x++ )
|
||||
var_noise = std::max(var_noise, ssd.at<float>(largeSize/2+y, largeSize/2+x));
|
||||
|
||||
for( j = 0; j <= fsize; j++ )
|
||||
feature[j] = FLT_MAX;
|
||||
|
||||
// Derive feature vector before exp(-x) computation
|
||||
// Idea: for all x,a >= 0, a=const. we have:
|
||||
// max [ exp( -x / a) ] = exp ( -min(x) / a )
|
||||
// Thus, determine min(ssd) and store in feature[...]
|
||||
for( y = 0; y < ssd.rows; y++ )
|
||||
{
|
||||
const schar *mappingMaskPtr = mappingMask.ptr<schar>(y);
|
||||
const float *ssdPtr = ssd.ptr<float>(y);
|
||||
for( x = 0 ; x < ssd.cols; x++ )
|
||||
{
|
||||
int index = mappingMaskPtr[x];
|
||||
feature[index] = std::max(feature[index], ssdPtr[x]);
|
||||
}
|
||||
}
|
||||
|
||||
var_noise = -1.f/var_noise;
|
||||
for( j = 0; j < fsize; j++ )
|
||||
feature0[j] = feature[j]*var_noise;
|
||||
Mat _f(1, fsize, CV_32F, feature0);
|
||||
cv::exp(_f, _f);
|
||||
}
|
||||
}
|
||||
|
||||
void SelfSimDescriptor::computeLogPolarMapping(Mat& mappingMask) const
|
||||
{
|
||||
mappingMask.create(largeSize, largeSize, CV_8S);
|
||||
|
||||
// What we want is
|
||||
// log_m (radius) = numberOfDistanceBuckets
|
||||
// <==> log_10 (radius) / log_10 (m) = numberOfDistanceBuckets
|
||||
// <==> log_10 (radius) / numberOfDistanceBuckets = log_10 (m)
|
||||
// <==> m = 10 ^ log_10(m) = 10 ^ [log_10 (radius) / numberOfDistanceBuckets]
|
||||
//
|
||||
int radius = largeSize/2, angleBucketSize = 360 / numberOfAngles;
|
||||
int fsize = (int)getDescriptorSize();
|
||||
double inv_log10m = (double)numberOfDistanceBuckets/log10((double)radius);
|
||||
|
||||
for (int y=-radius ; y<=radius ; y++)
|
||||
{
|
||||
schar* mrow = mappingMask.ptr<schar>(y+radius);
|
||||
for (int x=-radius ; x<=radius ; x++)
|
||||
{
|
||||
int index = fsize;
|
||||
float dist = (float)std::sqrt((float)x*x + (float)y*y);
|
||||
int distNo = dist > 0 ? cvRound(log10(dist)*inv_log10m) : 0;
|
||||
if( startDistanceBucket <= distNo && distNo < numberOfDistanceBuckets )
|
||||
{
|
||||
float angle = std::atan2( (float)y, (float)x ) / (float)CV_PI * 180.0f;
|
||||
if (angle < 0) angle += 360.0f;
|
||||
int angleInt = (cvRound(angle) + angleBucketSize/2) % 360;
|
||||
int angleIndex = angleInt / angleBucketSize;
|
||||
index = (distNo-startDistanceBucket)*numberOfAngles + angleIndex;
|
||||
}
|
||||
mrow[x + radius] = saturate_cast<schar>(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
1221
modules/contrib/src/spinimages.cpp
Normal file
1221
modules/contrib/src/spinimages.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user