1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install, copy or use the software.
8 // Copyright (C) 2009, Farhad Dadgostar
9 // Intel Corporation and third party copyrights are property of their respective owners.
11 // Redistribution and use in source and binary forms, with or without modification,
12 // are permitted provided that the following conditions are met:
14 // * Redistribution's of source code must retain the above copyright notice,
15 // this list of conditions and the following disclaimer.
17 // * Redistribution's in binary form must reproduce the above copyright notice,
18 // this list of conditions and the following disclaimer in the documentation
19 // and/or other materials provided with the distribution.
21 // * The name of Intel Corporation may not be used to endorse or promote products
22 // derived from this software without specific prior written permission.
24 // This software is provided by the copyright holders and contributors "as is" and
25 // any express or implied warranties, including, but not limited to, the implied
26 // warranties of merchantability and fitness for a particular purpose are disclaimed.
27 // In no event shall the Intel Corporation or contributors be liable for any direct,
28 // indirect, incidental, special, exemplary, or consequential damages
29 // (including, but not limited to, procurement of substitute goods or services;
30 // loss of use, data, or profits; or business interruption) however caused
31 // and on any theory of liability, whether in contract, strict liability,
32 // or tort (including negligence or otherwise) arising in any way out of
33 // the use of this software, even if advised of the possibility of such damage.
37 #include "precomp.hpp"
39 CvFuzzyPoint::CvFuzzyPoint(double _x, double _y)
45 bool CvFuzzyCurve::between(double x, double x1, double x2)
47 if ((x >= x1) && (x <= x2))
49 else if ((x >= x2) && (x <= x1))
55 CvFuzzyCurve::CvFuzzyCurve()
60 CvFuzzyCurve::~CvFuzzyCurve()
65 void CvFuzzyCurve::setCentre(double _centre)
70 double CvFuzzyCurve::getCentre()
75 void CvFuzzyCurve::clear()
80 void CvFuzzyCurve::addPoint(double x, double y)
82 points.push_back(CvFuzzyPoint(x, y));
85 double CvFuzzyCurve::calcValue(double param)
87 int size = (int)points.size();
88 double x1, y1, x2, y2, m, y;
89 for (int i = 1; i < size; i++)
93 if (between(param, x1, x2)) {
106 double CvFuzzyCurve::getValue()
111 void CvFuzzyCurve::setValue(double _value)
117 CvFuzzyFunction::CvFuzzyFunction()
122 CvFuzzyFunction::~CvFuzzyFunction()
127 void CvFuzzyFunction::addCurve(CvFuzzyCurve *curve, double value)
129 curves.push_back(*curve);
130 curve->setValue(value);
133 void CvFuzzyFunction::resetValues()
135 int numCurves = (int)curves.size();
136 for (int i = 0; i < numCurves; i++)
137 curves[i].setValue(0);
140 double CvFuzzyFunction::calcValue()
142 double s1 = 0, s2 = 0, v;
143 int numCurves = (int)curves.size();
144 for (int i = 0; i < numCurves; i++)
146 v = curves[i].getValue();
147 s1 += curves[i].getCentre() * v;
157 CvFuzzyCurve *CvFuzzyFunction::newCurve()
160 c = new CvFuzzyCurve();
165 CvFuzzyRule::CvFuzzyRule()
172 CvFuzzyRule::~CvFuzzyRule()
174 if (fuzzyInput1 != NULL)
177 if (fuzzyInput2 != NULL)
180 if (fuzzyOutput != NULL)
184 void CvFuzzyRule::setRule(CvFuzzyCurve *c1, CvFuzzyCurve *c2, CvFuzzyCurve *o1)
191 double CvFuzzyRule::calcValue(double param1, double param2)
194 v1 = fuzzyInput1->calcValue(param1);
195 if (fuzzyInput2 != NULL)
197 v2 = fuzzyInput2->calcValue(param2);
207 CvFuzzyCurve *CvFuzzyRule::getOutputCurve()
212 CvFuzzyController::CvFuzzyController()
217 CvFuzzyController::~CvFuzzyController()
219 int size = (int)rules.size();
220 for(int i = 0; i < size; i++)
224 void CvFuzzyController::addRule(CvFuzzyCurve *c1, CvFuzzyCurve *c2, CvFuzzyCurve *o1)
226 CvFuzzyRule *f = new CvFuzzyRule();
228 f->setRule(c1, c2, o1);
231 double CvFuzzyController::calcOutput(double param1, double param2)
234 CvFuzzyFunction list;
235 int size = (int)rules.size();
237 for(int i = 0; i < size; i++)
239 v = rules[i]->calcValue(param1, param2);
241 list.addCurve(rules[i]->getOutputCurve(), v);
243 v = list.calcValue();
247 CvFuzzyMeanShiftTracker::FuzzyResizer::FuzzyResizer()
249 CvFuzzyCurve *i1L, *i1M, *i1H;
250 CvFuzzyCurve *oS, *oZE, *oE;
253 double MedStart = 0.1, MedWidth = 0.15;
255 c = iInput.newCurve();
261 c = iInput.newCurve();
262 c->addPoint(0.05, 0);
263 c->addPoint(MedStart, 1);
264 c->addPoint(MedStart+MedWidth, 1);
265 c->addPoint(MedStart+MedWidth+0.05, 0);
266 c->setCentre(MedStart+(MedWidth/2));
269 c = iInput.newCurve();
270 c->addPoint(MedStart+MedWidth, 0);
272 c->addPoint(1000, 1);
276 c = iOutput.newCurve();
277 c->addPoint(-10000, 1);
279 c->addPoint(-0.5, 0);
283 c = iOutput.newCurve();
285 c->addPoint(-0.05, 1);
286 c->addPoint(0.05, 1);
291 c = iOutput.newCurve();
292 c->addPoint(-0.5, 0);
294 c->addPoint(1000, 1);
298 fuzzyController.addRule(i1L, NULL, oS);
299 fuzzyController.addRule(i1M, NULL, oZE);
300 fuzzyController.addRule(i1H, NULL, oE);
303 int CvFuzzyMeanShiftTracker::FuzzyResizer::calcOutput(double edgeDensity, double density)
305 return (int)fuzzyController.calcOutput(edgeDensity, density);
308 CvFuzzyMeanShiftTracker::SearchWindow::SearchWindow()
333 CvFuzzyMeanShiftTracker::SearchWindow::~SearchWindow()
335 if (fuzzyResizer != NULL)
339 void CvFuzzyMeanShiftTracker::SearchWindow::setSize(int _x, int _y, int _width, int _height)
352 if (x + width > maxWidth)
353 width = maxWidth - x;
355 if (y + height > maxHeight)
356 height = maxHeight - y;
359 void CvFuzzyMeanShiftTracker::SearchWindow::initDepthValues(IplImage *maskImage, IplImage *depthMap)
361 unsigned int d=0, mind = 0xFFFF, maxd = 0, m0 = 0, m1 = 0, mc, dd;
362 unsigned char *data = NULL;
363 unsigned short *depthData = NULL;
365 for (int j = 0; j < height; j++)
367 data = (unsigned char *)(maskImage->imageData + (maskImage->widthStep * (j + y)) + x);
369 depthData = (unsigned short *)(depthMap->imageData + (depthMap->widthStep * (j + y)) + x);
371 for (int i = 0; i < width; i++)
398 if ((mc - mind) > (maxd - mc))
413 bool CvFuzzyMeanShiftTracker::SearchWindow::shift()
415 if ((xGc != (width/2)) || (yGc != (height/2)))
417 setSize(x + (xGc-(width/2)), y + (yGc-(height/2)), width, height);
426 void CvFuzzyMeanShiftTracker::SearchWindow::extractInfo(IplImage *maskImage, IplImage *depthMap, bool initDepth)
438 maxWidth = maskImage->width;
439 maxHeight = maskImage->height;
442 initDepthValues(maskImage, depthMap);
444 unsigned char *maskData = NULL;
445 unsigned short *depthData = NULL, depth;
449 verticalEdgeLeft = 0;
450 verticalEdgeRight = 0;
451 horizontalEdgeTop = 0;
452 horizontalEdgeBottom = 0;
454 for (int j = 0; j < height; j++)
456 maskData = (unsigned char *)(maskImage->imageData + (maskImage->widthStep * (j + y)) + x);
458 depthData = (unsigned short *)(depthMap->imageData + (depthMap->widthStep * (j + y)) + x);
461 for (int i = 0; i < width; i++)
468 depth = (*depthData);
469 if ((depth > depthHigh) || (depth < depthLow))
486 else if (i == width-1)
490 else if (j == height-1)
491 horizontalEdgeBottom++;
505 double a, b, c, e1, e2, e3;
506 a = ((double)m20/(double)m00)-(xGc * xGc);
507 b = 2*(((double)m11/(double)m00)-(xGc * yGc));
508 c = ((double)m02/(double)m00)-(yGc * yGc);
511 e2 = sqrt((b*b)+(e3*e3));
512 ellipseHeight = int(sqrt(0.5*(e1+e2)));
513 ellipseWidth = int(sqrt(0.5*(e1-e2)));
517 ellipseAngle = 0.5*atan(b/e3);
519 density = (double)m00/(double)(width * height);
532 void CvFuzzyMeanShiftTracker::SearchWindow::getResizeAttribsEdgeDensityLinear(int &resizeDx, int &resizeDy, int &resizeDw, int &resizeDh) {
533 int x1 = horizontalEdgeTop;
534 int x2 = horizontalEdgeBottom;
535 int y1 = verticalEdgeLeft;
536 int y2 = verticalEdgeRight;
537 int gx = (width*2)/5;
538 int gy = (height*2)/5;
549 } else if (x1 < lx) {
554 resizeDh = resizeDy + 1;
555 } else if (x2 < lx) {
556 resizeDh = - (resizeDy + 1);
558 resizeDh = - resizeDy;
563 } else if (y1 < ly) {
568 resizeDw = resizeDx + 1;
569 } else if (y2 < ly) {
570 resizeDw = - (resizeDx + 1);
572 resizeDw = - resizeDx;
576 void CvFuzzyMeanShiftTracker::SearchWindow::getResizeAttribsInnerDensity(int &resizeDx, int &resizeDy, int &resizeDw, int &resizeDh)
578 int newWidth, newHeight, dx, dy;
580 newWidth = int(sqrt(double(m00)*1.3));
581 newHeight = int(newWidth*1.2);
582 dx = (newWidth - width);
583 dy = (newHeight - height);
584 px = (double)xGc/(double)width;
585 py = (double)yGc/(double)height;
586 resizeDx = (int)(px*dx);
587 resizeDy = (int)(py*dy);
588 resizeDw = (int)((1-px)*dx);
589 resizeDh = (int)((1-py)*dy);
592 void CvFuzzyMeanShiftTracker::SearchWindow::getResizeAttribsEdgeDensityFuzzy(int &resizeDx, int &resizeDy, int &resizeDw, int &resizeDh)
594 double dx1=0, dx2, dy1, dy2;
601 if (fuzzyResizer == NULL)
602 fuzzyResizer = new FuzzyResizer();
604 dx2 = fuzzyResizer->calcOutput(double(verticalEdgeRight)/double(height), density);
607 resizeDx = int(-dx1);
608 resizeDw = int(dx1+dx2);
611 dy1 = fuzzyResizer->calcOutput(double(horizontalEdgeTop)/double(width), density);
612 dy2 = fuzzyResizer->calcOutput(double(horizontalEdgeBottom)/double(width), density);
614 dx1 = fuzzyResizer->calcOutput(double(verticalEdgeLeft)/double(height), density);
615 dx2 = fuzzyResizer->calcOutput(double(verticalEdgeRight)/double(height), density);
618 resizeDx = int(-dx1);
619 resizeDw = int(dx1+dx2);
622 dy1 = fuzzyResizer->calcOutput(double(horizontalEdgeTop)/double(width), density);
623 dy2 = fuzzyResizer->calcOutput(double(horizontalEdgeBottom)/double(width), density);
626 resizeDy = int(-dy1);
627 resizeDh = int(dy1+dy2);
631 bool CvFuzzyMeanShiftTracker::SearchWindow::meanShift(IplImage *maskImage, IplImage *depthMap, int maxIteration, bool initDepth)
636 extractInfo(maskImage, depthMap, initDepth);
639 } while (++numShifts < maxIteration);
644 void CvFuzzyMeanShiftTracker::findOptimumSearchWindow(SearchWindow &searchWindow, IplImage *maskImage, IplImage *depthMap, int maxIteration, int resizeMethod, bool initDepth)
646 int resizeDx, resizeDy, resizeDw, resizeDh;
651 searchWindow.numIters = 0;
652 for (int i = 0; i < maxIteration; i++)
654 searchWindow.numIters++;
655 searchWindow.meanShift(maskImage, depthMap, MaxMeanShiftIteration, initDepth);
656 switch (resizeMethod)
658 case rmEdgeDensityLinear :
659 searchWindow.getResizeAttribsEdgeDensityLinear(resizeDx, resizeDy, resizeDw, resizeDh);
661 case rmEdgeDensityFuzzy :
662 //searchWindow.getResizeAttribsEdgeDensityLinear(resizeDx, resizeDy, resizeDw, resizeDh);
663 searchWindow.getResizeAttribsEdgeDensityFuzzy(resizeDx, resizeDy, resizeDw, resizeDh);
665 case rmInnerDensity :
666 searchWindow.getResizeAttribsInnerDensity(resizeDx, resizeDy, resizeDw, resizeDh);
669 searchWindow.getResizeAttribsEdgeDensityLinear(resizeDx, resizeDy, resizeDw, resizeDh);
672 searchWindow.ldx = resizeDx;
673 searchWindow.ldy = resizeDy;
674 searchWindow.ldw = resizeDw;
675 searchWindow.ldh = resizeDh;
677 if ((resizeDx == 0) && (resizeDy == 0) && (resizeDw == 0) && (resizeDh == 0))
680 searchWindow.setSize(searchWindow.x + resizeDx, searchWindow.y + resizeDy, searchWindow.width + resizeDw, searchWindow.height + resizeDh);
684 CvFuzzyMeanShiftTracker::CvFuzzyMeanShiftTracker()
686 searchMode = tsSetWindow;
689 CvFuzzyMeanShiftTracker::~CvFuzzyMeanShiftTracker()
694 void CvFuzzyMeanShiftTracker::track(IplImage *maskImage, IplImage *depthMap, int resizeMethod, bool resetSearch, int minKernelMass)
696 bool initDepth = false;
699 searchMode = tsSetWindow;
708 kernel.maxWidth = maskImage->width;
709 kernel.maxHeight = maskImage->height;
710 kernel.setSize(0, 0, maskImage->width, maskImage->height);
713 searchMode = tsSearching;
714 findOptimumSearchWindow(kernel, maskImage, depthMap, MaxSetSizeIteration, resizeMethod, initDepth);
715 if ((kernel.density == 0) || (kernel.m00 < minKernelMass))
716 searchMode = tsSetWindow;
718 searchMode = tsTracking;