8 #ifndef META_OCEAN_CV_SEGMENTATION_CLUSTERING_H
9 #define META_OCEAN_CV_SEGMENTATION_CLUSTERING_H
23 namespace Segmentation
31 template <
unsigned int tChannels>
53 inline Data(
const uint8_t*
const value,
const unsigned int id);
60 inline uint8_t
value(
unsigned int channel)
const;
66 inline unsigned int id()
const;
72 inline unsigned int channels()
const;
79 inline unsigned int ssd(
const Data& data)
const;
86 inline unsigned int ssd(
const uint8_t* values)
const;
94 inline bool ssd(
const Data& data,
const unsigned int sqrChannel)
const;
102 inline bool ssd(
const uint8_t* values,
const unsigned int sqrChannel)
const;
116 unsigned int id_ = (
unsigned int)(-1);
153 explicit inline Cluster(
const uint8_t*
center,
const size_t expectedElements = 0);
160 inline uint8_t
center(
const unsigned int channel)
const;
167 inline unsigned int variance(
const unsigned int channel)
const;
173 inline const uint8_t*
centers()
const;
185 inline size_t size()
const;
202 explicit inline operator bool()
const;
353 template <
unsigned int tChannels>
357 ocean_assert(
value !=
nullptr);
359 for (
unsigned int n = 0u; n < tChannels; ++n)
365 template <
unsigned int tChannels>
368 ocean_assert(channel < tChannels);
370 return values_[channel];
373 template <
unsigned int tChannels>
379 template <
unsigned int tChannels>
385 template <
unsigned int tChannels>
388 unsigned int result = 0u;
390 for (
unsigned int n = 0u; n < tChannels; ++n)
398 template <
unsigned int tChannels>
401 ocean_assert(values);
403 unsigned int result = 0u;
405 for (
unsigned int n = 0u; n < tChannels; ++n)
413 template <
unsigned int tChannels>
419 template <
unsigned int tChannels>
422 for (
unsigned int n = 0u; n < tChannels; ++n)
433 template <
unsigned int tChannels>
436 ocean_assert(values !=
nullptr);
438 for (
unsigned int n = 0u; n < tChannels; ++n)
440 if (
sqrDistance(values_[n], values[n]) > sqrChannel)
449 template <
unsigned int tChannels>
452 *
this = std::move(cluster);
455 template <
unsigned int tChannels>
458 ocean_assert(center !=
nullptr);
460 for (
unsigned int n = 0u; n < tChannels; ++n)
462 centers_[n] = center[n];
465 for (
unsigned int n = 0u; n < tChannels; ++n)
467 variances_[n] = (
unsigned int)(-1);
470 if (expectedElements != 0)
472 datas_.reserve(expectedElements);
476 template <
unsigned int tChannels>
479 ocean_assert(channel < tChannels);
480 return centers_[channel];
483 template <
unsigned int tChannels>
486 ocean_assert(channel < tChannels);
487 ocean_assert(variances_[channel] != (
unsigned int)(-1));
489 return variances_[channel];
492 template <
unsigned int tChannels>
498 template <
unsigned int tChannels>
504 template <
unsigned int tChannels>
507 return datas_.size();
510 template <
unsigned int tChannels>
513 datas_.push_back(data);
516 template <
unsigned int tChannels>
524 uint64_t means[tChannels] = {0u};
525 uint64_t sqrMeans[tChannels] = {0u};
527 for (
const Data& data : datas_)
529 for (
unsigned int n = 0u; n < tChannels; ++n)
531 means[n] += uint64_t(data.value(n));
534 for (
unsigned int n = 0u; n < tChannels; ++n)
536 sqrMeans[n] += uint64_t(
sqr(data.value(n)));
540 for (
unsigned int n = 0u; n < tChannels; ++n)
542 variances_[n] = (
unsigned int)((sqrMeans[n] * uint64_t(datas_.size()) -
sqr(means[n])) /
sqr(uint64_t(datas_.size())));
546 template <
unsigned int tChannels>
549 return !datas_.empty();
552 template <
unsigned int tChannels>
555 return datas_.size() > cluster.
datas_.size();
558 template <
unsigned int tChannels>
563 datas_ = std::move(right.datas_);
565 for (
unsigned int n = 0u; n < tChannels; ++n)
567 centers_[n] = right.centers_[n];
570 for (
unsigned int n = 0u; n < tChannels; ++n)
572 variances_[n] = right.variances_[n];
579 template <
unsigned int tChannels>
582 averageClusterSize_(-1.0f),
583 maximalClusterSize_(0u)
594 total += cluster.size();
603 template <
unsigned int tChannels>
606 *
this = std::move(segmentation);
609 template <
unsigned int tChannels>
615 template <
unsigned int tChannels>
618 return averageClusterSize_;
621 template <
unsigned int tChannels>
624 return maximalClusterSize_;
627 template <
unsigned int tChannels>
630 return first.maximalClusterSize() > second.maximalClusterSize();
633 template <
unsigned int tChannels>
638 clusters_ = std::move(right.clusters_);
639 averageClusterSize_ = right.averageClusterSize_;
640 maximalClusterSize_ = right.maximalClusterSize_;
646 template <
unsigned int tChannels>
649 static_assert(tChannels != 0u,
"Invalid channel number!");
651 Datas remainingDatas(datas);
652 const unsigned int sqrClusterRadius =
sqr(clusterRadius);
655 tmpDatas.reserve(datas.size());
658 clusters.reserve(expectedClusters);
660 while (!remainingDatas.empty())
662 const unsigned int randomFingerprintIndex =
RandomI::random(randomGenerator, min((
unsigned int)remainingDatas.size() - 1u, randomGenerator.
randMax()));
663 const Data& randomData = remainingDatas[randomFingerprintIndex];
665 clusters.push_back(
Cluster(randomData(), remainingDatas.size()));
666 Cluster& newCluster = clusters.back();
671 for (
typename Datas::const_iterator i = remainingDatas.begin(); i != remainingDatas.end(); ++i)
672 if (randomData.
ssd(*i, sqrClusterRadius))
675 tmpDatas.push_back(*i);
677 std::swap(remainingDatas, tmpDatas);
683 template <
unsigned int tChannels>
686 static_assert(tChannels != 0u,
"Invalid channel number!");
688 Datas copyDatas(datas);
690 const unsigned int sqrClusterRadius =
sqr(clusterRadius);
692 Datas remainingDatas;
693 remainingDatas.reserve(datas.size());
696 clusters.reserve(expectedClusters);
698 while (!copyDatas.empty())
700 const unsigned int randomFingerprintIndex =
RandomI::random(randomGenerator, (
unsigned int)(copyDatas.size()) - 1u);
702 const Data& randomData = copyDatas[randomFingerprintIndex];
706 unsigned int total[tChannels] = {0u};
707 unsigned int totalNumber = 0u;
710 for (
const Data& copyData : copyDatas)
712 if (randomData.
ssd(copyData, sqrClusterRadius))
714 for (
unsigned int n = 0u; n < tChannels; ++n)
717 ocean_assert(uint64_t(total[n]) + uint64_t(copyData.value(n)) < uint64_t((
unsigned int)(-1)));
719 total[n] += copyData.value(n);
726 ocean_assert(totalNumber != 0u);
728 uint8_t centers[tChannels];
730 for (
unsigned int n = 0u; n < tChannels; ++n)
732 const unsigned int center = (total[n] + totalNumber / 2u) / totalNumber;
733 ocean_assert(center <= 255u);
735 centers[n] = uint8_t(center);
738 clusters.emplace_back(centers, copyDatas.size());
739 Cluster& newCluster = clusters.back();
741 remainingDatas.clear();
743 for (
const Data& copyData : copyDatas)
745 if (copyData.ssd(newCluster.
centers(), sqrClusterRadius))
751 remainingDatas.emplace_back(copyData);
755 std::swap(copyDatas, remainingDatas);
761 template <
unsigned int tChannels>
764 static_assert(tChannels != 0u,
"Invalid channel number!");
766 ocean_assert(!datas.empty() && iterations > 0u);
768 if (datas.empty() || iterations == 0u)
775 std::vector<Segmentation> results(worker->
threads());
776 ocean_assert(!results.empty());
778 worker->
executeFunction(
Worker::Function::createStatic(&
Clustering<tChannels>::findOptimalRandomClusteringSubset, &datas, clusterRadius, &randomGenerator, &results[0], oneIteration, 0u, 0u, 0u), 0u, iterations, 5u, 6u, 1u, 7u);
780 unsigned int bestIndex = 0u;
782 for (
unsigned int n = 1u; n < results.size(); ++n)
784 if (results[n].clusters().size() < results[bestIndex].clusters().size())
788 else if (results[n].clusters().size() == results[bestIndex].clusters().size())
807 if (results[n].maximalClusterSize() > results[n].maximalClusterSize())
814 return std::move(results[bestIndex]);
825 template <
unsigned int tChannels>
828 ocean_assert(datas !=
nullptr && randomGenerator !=
nullptr && segmentation !=
nullptr);
829 ocean_assert(numberIterations > 0u);
838 for (
unsigned int n = 1u; n < numberIterations; ++n)
843 if (testSegmentation.clusters().size() < result.clusters().size())
845 result = std::move(testSegmentation);
847 else if (testSegmentation.clusters().size() == result.clusters().size())
866 if (testSegmentation.maximalClusterSize() > result.maximalClusterSize())
868 result = std::move(testSegmentation);
This class implements a single cluster for 3 channel 24 bit data objects.
Definition: Clustering.h:128
unsigned int variance(const unsigned int channel) const
Returns the variance of the first value.
Definition: Clustering.h:484
Cluster & operator=(Cluster &&right) noexcept
Move operator.
Definition: Clustering.h:559
const Datas & datas() const
Returns the elements of this cluster.
Definition: Clustering.h:499
const uint8_t * centers() const
Returns the centers of this cluster.
Definition: Clustering.h:493
uint8_t center(const unsigned int channel) const
Returns the first center value of this cluster.
Definition: Clustering.h:477
bool operator<(const Cluster &cluster) const
Returns whether this cluster holds more elements than a second one.
Definition: Clustering.h:553
size_t size() const
Returns the number of elements this cluster holds.
Definition: Clustering.h:505
Cluster()=default
Creates a default cluster object.
void addData(const Data &data)
Adds a new data value object to this cluster.
Definition: Clustering.h:511
Datas datas_
Data values of this cluster.
Definition: Clustering.h:227
uint8_t centers_[tChannels]
Definition: Clustering.h:221
void calculateVariance()
Calculates or updates the value variance of this cluster.
Definition: Clustering.h:517
unsigned int variances_[tChannels]
Variance values.
Definition: Clustering.h:224
Cluster(const Cluster &cluster)=default
Copy constructor.
This class implements a single data to be clustered.
Definition: Clustering.h:40
const uint8_t * operator()() const
Returns the data of this object.
Definition: Clustering.h:414
uint8_t value(unsigned int channel) const
Returns a specified element of this data object.
Definition: Clustering.h:366
Data()=default
Creates a default data object.
unsigned int id_
the id of the data.
Definition: Clustering.h:116
unsigned int id() const
Returns the id of this data object.
Definition: Clustering.h:374
unsigned int channels() const
Returns the number of channels this data object stores.
Definition: Clustering.h:380
uint8_t values_[tChannels]
The values.
Definition: Clustering.h:113
unsigned int ssd(const Data &data) const
Returns the ssd between two data values.
Definition: Clustering.h:386
This class implements the management of clusters.
Definition: Clustering.h:237
Segmentation & operator=(Segmentation &&right) noexcept
Move operator.
Definition: Clustering.h:634
float averageClusterSize_
Average cluster size of this segmentation.
Definition: Clustering.h:295
float averageClusterSize() const
Returns the average cluster size.
Definition: Clustering.h:616
Clusters clusters_
Clusters of this segmentation object.
Definition: Clustering.h:292
static bool compareMaximalClusterSize(const Segmentation &first, const Segmentation &second)
Compares two segmentation regarding to the maximal cluster size.
Definition: Clustering.h:628
const Clusters & clusters() const
Returns the clusters defined by this segmentation.
Definition: Clustering.h:610
size_t maximalClusterSize_
Maximal cluster size of this segmentation.
Definition: Clustering.h:298
Segmentation()=default
Creates a new segmentation object.
size_t maximalClusterSize() const
Returns the maximal cluster size of this segmentation.
Definition: Clustering.h:622
This class implements simple clustering functions for image information.
Definition: Clustering.h:33
std::vector< Data > Datas
Definition of a vector holding data object.
Definition: Clustering.h:122
std::vector< Cluster > Clusters
Definition of a vector holding cluster objects.
Definition: Clustering.h:231
static void findOptimalRandomClusteringSubset(const Datas *datas, const unsigned int clusterRadius, RandomGenerator *randomGenerator, Segmentation *segmentation, const bool oneIteration, const unsigned int firstIteration, const unsigned int numberIterations, const unsigned int iterationIndex)
Determines an optimal cluster from a set of random clusters for 3 channel 24 bit data elements.
Definition: Clustering.h:826
static Segmentation findRandomClusteringTwoIterations(const Datas &datas, const unsigned int clusterRadius, RandomGenerator &randomGenerator, const size_t expectedClusters=20)
Determines a random cluster for data elements by application of two seeking iterations.
Definition: Clustering.h:684
static Segmentation findRandomClusteringOneIteration(const Datas &datas, const unsigned int clusterRadius, RandomGenerator &randomGenerator, const size_t expectedClusters=20)
Determines a random cluster for data elements by application of one seeking iteration.
Definition: Clustering.h:647
static Segmentation findOptimalRandomClustering(const Datas &datas, const unsigned int clusterRadius, RandomGenerator &randomGenerator, const unsigned int iterations=10u, Worker *worker=nullptr, const bool oneIteration=true)
Determines an optimal cluster from a set of random clusters for 3 channel 24 bit data elements.
Definition: Clustering.h:762
static Caller< void > createStatic(typename StaticFunctionPointerMaker< void, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass >::Type function)
Creates a new caller container for a static function with no function parameter.
Definition: Caller.h:2876
This class implements a generator for random numbers.
Definition: RandomGenerator.h:42
static constexpr unsigned int randMax()
Returns the maximal random value of this generator.
Definition: RandomGenerator.h:183
static unsigned int random(const unsigned int maxValue)
Returns one random integer value with specified maximum value.
This class implements a worker able to distribute function calls over different threads.
Definition: Worker.h:33
unsigned int threads() const
Returns the number of threads this worker uses.
bool executeFunction(const Function &function, const unsigned int first, const unsigned int size, const unsigned int firstIndex=(unsigned int)(-1), const unsigned int sizeIndex=(unsigned int)(-1), const unsigned int minimalIterations=1u, const unsigned int threadIndex=(unsigned int)(-1))
Executes a callback function separable by two function parameters.
unsigned int sqrDistance(const char first, const char second)
Returns the square distance between two values.
Definition: base/Utilities.h:1089
unsigned int sqr(const char value)
Returns the square value of a given value.
Definition: base/Utilities.h:1029
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15