moved cv::partition from private.hpp to operations.hpp, to expose the function to users
This commit is contained in:
parent
47838a4a22
commit
d58cadc1ea
@ -526,6 +526,105 @@ void AlgorithmInfo::addParam(Algorithm& algo, const char* parameter, Ptr<_Tp>& v
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************************\
|
||||||
|
* Auxiliary algorithms *
|
||||||
|
\****************************************************************************************/
|
||||||
|
|
||||||
|
// This function splits the input sequence or set into one or more equivalence classes and
|
||||||
|
// returns the vector of labels - 0-based class indexes for each element.
|
||||||
|
// predicate(a,b) returns true if the two sequence elements certainly belong to the same class.
|
||||||
|
//
|
||||||
|
// The algorithm is described in "Introduction to Algorithms"
|
||||||
|
// by Cormen, Leiserson and Rivest, the chapter "Data structures for disjoint sets"
|
||||||
|
template<typename _Tp, class _EqPredicate> int
|
||||||
|
partition( const std::vector<_Tp>& _vec, std::vector<int>& labels,
|
||||||
|
_EqPredicate predicate=_EqPredicate())
|
||||||
|
{
|
||||||
|
int i, j, N = (int)_vec.size();
|
||||||
|
const _Tp* vec = &_vec[0];
|
||||||
|
|
||||||
|
const int PARENT=0;
|
||||||
|
const int RANK=1;
|
||||||
|
|
||||||
|
std::vector<int> _nodes(N*2);
|
||||||
|
int (*nodes)[2] = (int(*)[2])&_nodes[0];
|
||||||
|
|
||||||
|
// The first O(N) pass: create N single-vertex trees
|
||||||
|
for(i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
nodes[i][PARENT]=-1;
|
||||||
|
nodes[i][RANK] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The main O(N^2) pass: merge connected components
|
||||||
|
for( i = 0; i < N; i++ )
|
||||||
|
{
|
||||||
|
int root = i;
|
||||||
|
|
||||||
|
// find root
|
||||||
|
while( nodes[root][PARENT] >= 0 )
|
||||||
|
root = nodes[root][PARENT];
|
||||||
|
|
||||||
|
for( j = 0; j < N; j++ )
|
||||||
|
{
|
||||||
|
if( i == j || !predicate(vec[i], vec[j]))
|
||||||
|
continue;
|
||||||
|
int root2 = j;
|
||||||
|
|
||||||
|
while( nodes[root2][PARENT] >= 0 )
|
||||||
|
root2 = nodes[root2][PARENT];
|
||||||
|
|
||||||
|
if( root2 != root )
|
||||||
|
{
|
||||||
|
// unite both trees
|
||||||
|
int rank = nodes[root][RANK], rank2 = nodes[root2][RANK];
|
||||||
|
if( rank > rank2 )
|
||||||
|
nodes[root2][PARENT] = root;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nodes[root][PARENT] = root2;
|
||||||
|
nodes[root2][RANK] += rank == rank2;
|
||||||
|
root = root2;
|
||||||
|
}
|
||||||
|
CV_Assert( nodes[root][PARENT] < 0 );
|
||||||
|
|
||||||
|
int k = j, parent;
|
||||||
|
|
||||||
|
// compress the path from node2 to root
|
||||||
|
while( (parent = nodes[k][PARENT]) >= 0 )
|
||||||
|
{
|
||||||
|
nodes[k][PARENT] = root;
|
||||||
|
k = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compress the path from node to root
|
||||||
|
k = i;
|
||||||
|
while( (parent = nodes[k][PARENT]) >= 0 )
|
||||||
|
{
|
||||||
|
nodes[k][PARENT] = root;
|
||||||
|
k = parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Final O(N) pass: enumerate classes
|
||||||
|
labels.resize(N);
|
||||||
|
int nclasses = 0;
|
||||||
|
|
||||||
|
for( i = 0; i < N; i++ )
|
||||||
|
{
|
||||||
|
int root = i;
|
||||||
|
while( nodes[root][PARENT] >= 0 )
|
||||||
|
root = nodes[root][PARENT];
|
||||||
|
// re-use the rank as the class label
|
||||||
|
if( nodes[root][RANK] >= 0 )
|
||||||
|
nodes[root][RANK] = ~nclasses++;
|
||||||
|
labels[i] = ~nodes[root][RANK];
|
||||||
|
}
|
||||||
|
|
||||||
|
return nclasses;
|
||||||
|
}
|
||||||
|
|
||||||
} // cv
|
} // cv
|
||||||
|
|
||||||
|
@ -301,111 +301,4 @@ typedef enum CvStatus
|
|||||||
}
|
}
|
||||||
CvStatus;
|
CvStatus;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************************\
|
|
||||||
* Auxiliary algorithms *
|
|
||||||
\****************************************************************************************/
|
|
||||||
|
|
||||||
namespace cv
|
|
||||||
{
|
|
||||||
|
|
||||||
// This function splits the input sequence or set into one or more equivalence classes and
|
|
||||||
// returns the vector of labels - 0-based class indexes for each element.
|
|
||||||
// predicate(a,b) returns true if the two sequence elements certainly belong to the same class.
|
|
||||||
//
|
|
||||||
// The algorithm is described in "Introduction to Algorithms"
|
|
||||||
// by Cormen, Leiserson and Rivest, the chapter "Data structures for disjoint sets"
|
|
||||||
template<typename _Tp, class _EqPredicate> int
|
|
||||||
partition( const std::vector<_Tp>& _vec, std::vector<int>& labels,
|
|
||||||
_EqPredicate predicate=_EqPredicate())
|
|
||||||
{
|
|
||||||
int i, j, N = (int)_vec.size();
|
|
||||||
const _Tp* vec = &_vec[0];
|
|
||||||
|
|
||||||
const int PARENT=0;
|
|
||||||
const int RANK=1;
|
|
||||||
|
|
||||||
std::vector<int> _nodes(N*2);
|
|
||||||
int (*nodes)[2] = (int(*)[2])&_nodes[0];
|
|
||||||
|
|
||||||
// The first O(N) pass: create N single-vertex trees
|
|
||||||
for(i = 0; i < N; i++)
|
|
||||||
{
|
|
||||||
nodes[i][PARENT]=-1;
|
|
||||||
nodes[i][RANK] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The main O(N^2) pass: merge connected components
|
|
||||||
for( i = 0; i < N; i++ )
|
|
||||||
{
|
|
||||||
int root = i;
|
|
||||||
|
|
||||||
// find root
|
|
||||||
while( nodes[root][PARENT] >= 0 )
|
|
||||||
root = nodes[root][PARENT];
|
|
||||||
|
|
||||||
for( j = 0; j < N; j++ )
|
|
||||||
{
|
|
||||||
if( i == j || !predicate(vec[i], vec[j]))
|
|
||||||
continue;
|
|
||||||
int root2 = j;
|
|
||||||
|
|
||||||
while( nodes[root2][PARENT] >= 0 )
|
|
||||||
root2 = nodes[root2][PARENT];
|
|
||||||
|
|
||||||
if( root2 != root )
|
|
||||||
{
|
|
||||||
// unite both trees
|
|
||||||
int rank = nodes[root][RANK], rank2 = nodes[root2][RANK];
|
|
||||||
if( rank > rank2 )
|
|
||||||
nodes[root2][PARENT] = root;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nodes[root][PARENT] = root2;
|
|
||||||
nodes[root2][RANK] += rank == rank2;
|
|
||||||
root = root2;
|
|
||||||
}
|
|
||||||
CV_Assert( nodes[root][PARENT] < 0 );
|
|
||||||
|
|
||||||
int k = j, parent;
|
|
||||||
|
|
||||||
// compress the path from node2 to root
|
|
||||||
while( (parent = nodes[k][PARENT]) >= 0 )
|
|
||||||
{
|
|
||||||
nodes[k][PARENT] = root;
|
|
||||||
k = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
// compress the path from node to root
|
|
||||||
k = i;
|
|
||||||
while( (parent = nodes[k][PARENT]) >= 0 )
|
|
||||||
{
|
|
||||||
nodes[k][PARENT] = root;
|
|
||||||
k = parent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Final O(N) pass: enumerate classes
|
|
||||||
labels.resize(N);
|
|
||||||
int nclasses = 0;
|
|
||||||
|
|
||||||
for( i = 0; i < N; i++ )
|
|
||||||
{
|
|
||||||
int root = i;
|
|
||||||
while( nodes[root][PARENT] >= 0 )
|
|
||||||
root = nodes[root][PARENT];
|
|
||||||
// re-use the rank as the class label
|
|
||||||
if( nodes[root][RANK] >= 0 )
|
|
||||||
nodes[root][RANK] = ~nclasses++;
|
|
||||||
labels[i] = ~nodes[root][RANK];
|
|
||||||
}
|
|
||||||
|
|
||||||
return nclasses;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace cv
|
|
||||||
|
|
||||||
#endif // __OPENCV_CORE_PRIVATE_HPP__
|
#endif // __OPENCV_CORE_PRIVATE_HPP__
|
||||||
|
Loading…
x
Reference in New Issue
Block a user