/******************************************************************** ** Image Component Library (ICL) ** ** ** ** Copyright (C) 2006-2013 CITEC, University of Bielefeld ** ** Neuroinformatics Group ** ** Website: www.iclcv.org and ** ** http://opensource.cit-ec.de/projects/icl ** ** ** ** File : ICLCV/src/ICLCV/HungarianAlgorithm.cpp ** ** Module : ICLCV ** ** Authors: Christof Elbrechter, Michael Goetting ** ** ** ** ** ** GNU LESSER GENERAL PUBLIC LICENSE ** ** This file may be used under the terms of the GNU Lesser General ** ** Public License version 3.0 as published by the ** ** ** ** Free Software Foundation and appearing in the file LICENSE.LGPL ** ** included in the packaging of this file. Please review the ** ** following information to ensure the license requirements will ** ** be met: http://www.gnu.org/licenses/lgpl-3.0.txt ** ** ** ** The development of this software was supported by the ** ** Excellence Cluster EXC 277 Cognitive Interaction Technology. ** ** The Excellence Cluster EXC 277 is a grant of the Deutsche ** ** Forschungsgemeinschaft (DFG) in the context of the German ** ** Excellence Initiative. ** ** ** ********************************************************************/ #include #include #include #include #include #include using namespace icl::utils; using namespace icl::core; namespace icl{ namespace cv{ typedef Array2D imat; typedef std::vector vec; //#define BEGIN_METHOD(X) counter_##X++; MethodTimer __timer(&timer_##X) void clearCovers(vec &rowCover, vec &colCover){ // {{{ open for (unsigned int i=0; i int hg_step1(int step, Array2D &cost){ // {{{ open //What STEP 1 does: //For each row of the cost matrix, find the smallest element //and subtract it from from every other element in its row. real minval; for(int i=0; i int hg_step2(int step, Array2D &cost, imat &mask, vec &rowCover, vec &colCover){ // {{{ open //What STEP 2 does: //Marks uncovered zeros as starred and covers their row and column. for (int i=0; i=mask.getWidth()){//Should be cost.length but ok, because mask has same dimensions. step=7; }else { step=4; } return step; } // }}} /* orig:: working, but slow !!! template int hg_step4(int step, Array2D &cost, imat &mask, vec &rowCover, vec &colCover, vec &zero_RC){ BEGIN_METHOD(hg_step4); // {{{ open //What STEP 4 does: //Find an uncovered zero in cost and prime it (if none go to step 6). Check for star in same row: //if yes, cover the row and uncover the star's column. Repeat until no uncovered zeros are left //and go to step 6. If not, save location of primed zero and go to step 5. vec row_col(2); //Holds row and col of uncovered zero. bool done = false; while (!done){ row_col = findUncoveredZero(row_col, cost, rowCover, colCover); if (row_col[0] == -1){ done = true; step = 6; }else{ mask[row_col[0]][row_col[1]] = 2; //Prime the found uncovered zero. bool starInRow = false; for (int j=0; j void findZeroPositions(std::vector &dst, Array2D &cost){ // {{{ open for(int i=0;i vec findUncoveredZero(vec &row_col, Array2D &cost, vec &rowCover, vec &colCover){ // {{{ open for(int i=0;i= cost.getWidth()){ done = true; } }//end outer while return row_col; ****************************/ } // }}} /* Best function, 5x faster then original, and twice as fast as ***Fast */ vec findUncoveredZeroLite(vec &row_col, const std::vector &indices, vec &rowCover, vec &colCover){ // {{{ open // x = col; for(unsigned int i=0;i int hg_step4(int step, Array2D &cost, imat &mask, vec &rowCover, vec &colCover, vec &zero_RC){ // {{{ open //What STEP 4 does: //Find an uncovered zero in cost and prime it (if none go to step 6). Check for star in same row: //if yes, cover the row and uncover the star's column. Repeat until no uncovered zeros are left //and go to step 6. If not, save location of primed zero and go to step 5. vec row_col(2); //Holds row and col of uncovered zero. bool done = false; std::vector zeroPositions; findZeroPositions(zeroPositions, cost); if(!zeroPositions.size()){ step = 6; return step; } while (!done){ findUncoveredZeroLite(row_col, zeroPositions, rowCover, colCover); if (row_col[0] == -1){ done = true; step = 6; }else{ mask(row_col[0],row_col[1]) = 2; //Prime the found uncovered zero. bool starInRow = false; for (int j=0; j vecPath; vecPath.push_back(Point(zero_RC[0],zero_RC[1])); //path[count][0] = zero_RC[0];//Row of last prime. //path[count][1] = zero_RC[1];//Column of last prime. bool done = false; while (!done){ // int r = findStarInCol(mask,path[count][1]); int r = findStarInCol(mask,vecPath[count].y); if (r>=0){ count++; vecPath.push_back(Point(r,vecPath[count-1].y)); // path[count][0] = r; //Row of starred zero. // path[count][1] = path[count-1][1];//Column of starred zero. }else{ done = true; } if(!done){ //int c = findPrimeInRow(mask, path[count][0]); int c = findPrimeInRow(mask, vecPath[count].x); count++; vecPath.push_back(Point(vecPath[count-1].x,c)); // path[count][0] = path [count-1][0]; //Row of primed zero. // path[count][1] = c; //Col of primed zero. } }//end while imat path((int)vecPath.size(),2); for(unsigned int i=0;i real findSmallest(Array2D &cost, vec &rowCover, vec &colCover, real maxCost){ // {{{ open real minval = maxCost; //There cannot be a larger cost than this. for (int i=0; i cost(i,j))){ minval = cost(i,j); } } } return minval; } // }}} template int hg_step6(int step, Array2D &cost, vec &rowCover, vec &colCover, real maxCost){ // {{{ open //What STEP 6 does: //Find smallest uncovered value in cost: a. Add it to every element of covered rows //b. Subtract it from every element of uncovered columns. Go to step 4. real minval = findSmallest(cost, rowCover, colCover, maxCost); for (unsigned int i=0; i vec HungarianAlgorithm::apply(const Array2D &m, bool isCostMatrix){ // {{{ open if(!m.getDim()) return vec(); mat cost = m.deepCopy(); if(!isCostMatrix){ real maxWeight = cost.maxElem(); for(int i=0;i void HungarianAlgorithm::visualizeAssignment(const Array2D &cost, const vec &a){ // {{{ open mat v(cost.getWidth(),cost.getHeight()); v.fill(0); for(unsigned int i=0;i; template class ICLCV_API HungarianAlgorithm; template class ICLCV_API HungarianAlgorithm; } // namespace cv }