123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- #pragma once
- #ifndef __CVTT_ENDPOINTSELECTOR_H__
- #define __CVTT_ENDPOINTSELECTOR_H__
- #include "ConvectionKernels_ParallelMath.h"
- #include "ConvectionKernels_UnfinishedEndpoints.h"
- #include "ConvectionKernels_PackedCovarianceMatrix.h"
- namespace cvtt
- {
- namespace Internal
- {
- static const int NumEndpointSelectorPasses = 3;
- template<int TVectorSize, int TIterationCount>
- class EndpointSelector
- {
- public:
- typedef ParallelMath::Float MFloat;
- EndpointSelector()
- {
- for (int ch = 0; ch < TVectorSize; ch++)
- {
- m_centroid[ch] = ParallelMath::MakeFloatZero();
- m_direction[ch] = ParallelMath::MakeFloatZero();
- }
- m_weightTotal = ParallelMath::MakeFloatZero();
- m_minDist = ParallelMath::MakeFloat(FLT_MAX);
- m_maxDist = ParallelMath::MakeFloat(-FLT_MAX);
- }
- void ContributePass(const MFloat *value, int pass, const MFloat &weight)
- {
- if (pass == 0)
- ContributeCentroid(value, weight);
- else if (pass == 1)
- ContributeDirection(value, weight);
- else if (pass == 2)
- ContributeMinMax(value);
- }
- void FinishPass(int pass)
- {
- if (pass == 0)
- FinishCentroid();
- else if (pass == 1)
- FinishDirection();
- }
- UnfinishedEndpoints<TVectorSize> GetEndpoints(const float channelWeights[TVectorSize]) const
- {
- MFloat unweightedBase[TVectorSize];
- MFloat unweightedOffset[TVectorSize];
- for (int ch = 0; ch < TVectorSize; ch++)
- {
- MFloat min = m_centroid[ch] + m_direction[ch] * m_minDist;
- MFloat max = m_centroid[ch] + m_direction[ch] * m_maxDist;
- float safeWeight = channelWeights[ch];
- if (safeWeight == 0.f)
- safeWeight = 1.0f;
- unweightedBase[ch] = min / channelWeights[ch];
- unweightedOffset[ch] = (max - min) / channelWeights[ch];
- }
- return UnfinishedEndpoints<TVectorSize>(unweightedBase, unweightedOffset);
- }
- private:
- void ContributeCentroid(const MFloat *value, const MFloat &weight)
- {
- for (int ch = 0; ch < TVectorSize; ch++)
- m_centroid[ch] = m_centroid[ch] + value[ch] * weight;
- m_weightTotal = m_weightTotal + weight;
- }
- void FinishCentroid()
- {
- MFloat denom = m_weightTotal;
- ParallelMath::MakeSafeDenominator(denom);
- for (int ch = 0; ch < TVectorSize; ch++)
- m_centroid[ch] = m_centroid[ch] / denom;
- }
- void ContributeDirection(const MFloat *value, const MFloat &weight)
- {
- MFloat diff[TVectorSize];
- for (int ch = 0; ch < TVectorSize; ch++)
- diff[ch] = value[ch] - m_centroid[ch];
- m_covarianceMatrix.Add(diff, weight);
- }
- void FinishDirection()
- {
- MFloat approx[TVectorSize];
- for (int ch = 0; ch < TVectorSize; ch++)
- approx[ch] = ParallelMath::MakeFloat(1.0f);
- for (int i = 0; i < TIterationCount; i++)
- {
- MFloat product[TVectorSize];
- m_covarianceMatrix.Product(product, approx);
- MFloat largestComponent = product[0];
- for (int ch = 1; ch < TVectorSize; ch++)
- largestComponent = ParallelMath::Max(largestComponent, product[ch]);
- // product = largestComponent*newApprox
- ParallelMath::MakeSafeDenominator(largestComponent);
- for (int ch = 0; ch < TVectorSize; ch++)
- approx[ch] = product[ch] / largestComponent;
- }
- // Normalize
- MFloat approxLen = ParallelMath::MakeFloatZero();
- for (int ch = 0; ch < TVectorSize; ch++)
- approxLen = approxLen + approx[ch] * approx[ch];
- approxLen = ParallelMath::Sqrt(approxLen);
- ParallelMath::MakeSafeDenominator(approxLen);
- for (int ch = 0; ch < TVectorSize; ch++)
- m_direction[ch] = approx[ch] / approxLen;
- }
- void ContributeMinMax(const MFloat *value)
- {
- MFloat dist = ParallelMath::MakeFloatZero();
- for (int ch = 0; ch < TVectorSize; ch++)
- dist = dist + m_direction[ch] * (value[ch] - m_centroid[ch]);
- m_minDist = ParallelMath::Min(m_minDist, dist);
- m_maxDist = ParallelMath::Max(m_maxDist, dist);
- }
- ParallelMath::Float m_centroid[TVectorSize];
- ParallelMath::Float m_direction[TVectorSize];
- PackedCovarianceMatrix<TVectorSize> m_covarianceMatrix;
- ParallelMath::Float m_weightTotal;
- ParallelMath::Float m_minDist;
- ParallelMath::Float m_maxDist;
- };
- }
- }
- #endif
|