< Summary - ReFlex - Library

Information
Class: PointCloud.Benchmark.Interactivity.InteractionObserverBase
Assembly: ReFlex.PointCloud.Benchmark
File(s): D:\a\reflex\reflex\test\Library\Performance\PointCloud.Benchmark\Interactivity\InteractionObserverBase.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 234
Coverable lines: 234
Total lines: 466
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 79
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

D:\a\reflex\reflex\test\Library\Performance\PointCloud.Benchmark\Interactivity\InteractionObserverBase.cs

#LineLine coverage
 1using ReFlex.Core.Common.Components;
 2using ReFlex.Core.Common.Interfaces;
 3using ReFlex.Core.Common.Util;
 4using ReFlex.Core.Interactivity.Components;
 5using ReFlex.Core.Interactivity.Interfaces;
 6using ReFlex.Core.Interactivity.Util;
 7using Math = System.Math;
 8
 9namespace PointCloud.Benchmark.Interactivity
 10{
 11    public abstract class InteractionObserverBase : IInteractionObserver, IPerformanceReporter
 12    {
 13        #region Fields
 14
 15        private readonly InteractionSmoothingBehaviour _smoothingBehaviour;
 016        private int _numSmoothingFrames = 5;
 017        private int _historySize = 25;
 018        private int _maxNumEmptyFramesBetween = 3;
 019        private float _touchMergeDistance2d = 64f;
 020        private float _depthScale = 100.0f;
 21        private FilterType _filterType;
 22        private float _maxConfidence;
 23        private int _extremumTypeCheckRadius;
 24        private int _extremumTypeCheckNumSamples;
 25
 026        protected Tuple<int, int>[] _fixedSamples = Array.Empty<Tuple<int, int>>();
 027        protected Tuple<int, int>[] _stochasticSamples = Array.Empty<Tuple<int, int>>();
 28
 29        #endregion
 30
 31        #region Properties
 32
 33        /// <summary>
 34        /// Gets or sets the distance.
 35        /// </summary>
 36        /// <value>
 37        /// The distance.
 38        /// </value>
 039        public float Distance { get; set; }
 40
 41        /// <summary>
 42        /// Gets or sets the minimum depth.
 43        /// </summary>
 44        /// <value>
 45        /// The maximum depth.
 46        /// </value>
 047        public float MinDistance { get; set; }
 48
 49        /// <summary>
 50        /// Gets or sets the maximum depth.
 51        /// </summary>
 52        /// <value>
 53        /// The maximum depth.
 54        /// </value>
 055        public float MaxDistance { get; set; }
 56
 57        /// <summary>
 58        /// defines how many points should be checked to determine the type of the extremum
 59        /// </summary>
 60        public int ExtremumTypeCheckNumSamples
 61        {
 062            get => _extremumTypeCheckNumSamples;
 63            set
 064            {
 065                if (_extremumTypeCheckNumSamples == value)
 066                    return;
 067                _extremumTypeCheckNumSamples = value;
 068                UpdateSamples();
 069            }
 70        }
 71
 72        /// <summary>
 73        /// The pixel radius in which the points are sampled for deriving the type of the local extremum
 74        /// </summary>
 75        public int ExtremumTypeCheckRadius
 76        {
 077            get => _extremumTypeCheckRadius;
 78            set
 079            {
 080                if (_extremumTypeCheckRadius == value)
 081                    return;
 082                _extremumTypeCheckRadius = value;
 083                UpdateSamples();
 084            }
 85        }
 86
 87        /// <summary>
 88        /// Which ratio of "correctly aligned" points should match to distinguish between Undefined or Minimum/Maximum ?
 89        /// </summary>
 090        public float ExtremumTypeCheckFittingPercentage { get; set; }
 91
 92        /// <summary>
 93        /// Defines how neighboring the points are sampled for determining the type of extremum.
 94        /// </summary>
 095        public ExtremumTypeCheckMethod ExtremumTypeCheckMethod { get; set; }
 96
 97        public int InteractionHistorySize
 98        {
 099            get => _historySize;
 100            set
 0101            {
 0102                _historySize = value;
 0103                if (_smoothingBehaviour != null)
 0104                {
 0105                    _smoothingBehaviour.NumFramesHistory = value;
 106                    // update depending smoothing/filter values
 0107                    NumSmoothingFrames = _numSmoothingFrames;
 0108                    MaxNumEmptyFramesBetween = _maxNumEmptyFramesBetween;
 0109                }
 0110            }
 111        }
 112
 113        public int NumSmoothingFrames
 114        {
 0115            get => _numSmoothingFrames;
 116            set
 0117            {
 0118                _numSmoothingFrames = value;
 0119                if (_smoothingBehaviour != null)
 0120                    _smoothingBehaviour.NumFramesSmoothing = value < _smoothingBehaviour.NumFramesHistory
 0121                        ? _smoothingBehaviour.NumFramesHistory
 0122                        : value;
 0123            }
 124        }
 125
 126        // TODO: write tests for negative (!) values and values larger than history
 127        public int MaxNumEmptyFramesBetween
 128        {
 0129            get => _maxNumEmptyFramesBetween;
 130            set
 0131            {
 0132                _maxNumEmptyFramesBetween = value;
 0133                if (_smoothingBehaviour != null)
 0134                    _smoothingBehaviour.MaxNumEmptyFramesBetween = value < _smoothingBehaviour.NumFramesHistory
 0135                        ? _smoothingBehaviour.NumFramesHistory
 0136                        : value;
 0137            }
 138        }
 139
 140        public float TouchMergeDistance2D
 141        {
 0142            get => _touchMergeDistance2d;
 143            set
 0144            {
 0145                _touchMergeDistance2d = value;
 0146                if (_smoothingBehaviour != null)
 0147                    _smoothingBehaviour.TouchMergeDistance2D = value;
 0148            }
 149        }
 150
 151        public float DepthScale
 152        {
 0153            get => _depthScale;
 154            set
 0155            {
 0156                _depthScale = value;
 0157                if (_smoothingBehaviour != null)
 0158                    _smoothingBehaviour.DepthScale = value;
 0159            }
 160        }
 161
 162        public FilterType FilterType
 163        {
 0164            get => _filterType;
 165            set
 0166            {
 0167                _filterType = value;
 0168                if (_smoothingBehaviour != null)
 0169                    _smoothingBehaviour.UpdateFilterType(_filterType);
 0170            }
 171        }
 172
 173
 174        /// <summary>
 175        /// Gets or sets the minimum angle.
 176        /// </summary>
 177        /// <value>
 178        /// The minimum angle.
 179        /// </value>
 0180        public virtual float MinAngle { get; set; }
 181
 182        /// <summary>
 183        /// Gets or sets the minimum confidence.
 184        /// </summary>
 185        /// <value>
 186        /// The minimum confidence.
 187        /// </value>
 0188        public virtual float MinConfidence { get; set; }
 189
 190        /// <summary>
 191        /// Gets or sets the maximum confidence.
 192        /// </summary>
 193        /// <value>
 194        /// The maximum confidence.
 195        /// </value>
 196        public virtual float MaxConfidence
 197        {
 0198            get => _maxConfidence;
 199            set
 0200            {
 0201                _maxConfidence = value;
 0202                if (_smoothingBehaviour != null)
 0203                    _smoothingBehaviour.MaxConfidence = (int) MaxConfidence;
 0204            }
 205        }
 206
 0207        public bool MeasurePerformance { get; set; }
 208
 0209        protected int FrameId { get; private set; }
 210
 211        #region Abstract Members
 212
 213        public abstract ObserverType Type { get; }
 214        public abstract PointCloud3 PointCloud { get; set; }
 215        public abstract VectorField2 VectorField { get; set; }
 216
 217        public abstract event EventHandler<IList<Interaction>> NewInteractions;
 218
 219        public event EventHandler<PerformanceDataItem> PerformanceDataUpdated;
 220
 221        public event EventHandler<IList<InteractionFrame>> InteractionHistoryUpdated;
 222
 223        public abstract Task<ProcessingResult> Update();
 224
 225        #endregion
 226
 227        #region Constructor
 228
 0229        protected InteractionObserverBase()
 0230        {
 0231            _smoothingBehaviour = new InteractionSmoothingBehaviour(InteractionHistorySize);
 0232        }
 233
 234        #endregion
 235
 236        public void UpdateFrameId(int frameId)
 0237        {
 0238            FrameId = frameId;
 0239        }
 240
 241        #endregion
 242
 243        protected InteractionFrame ComputeSmoothingValue(IList<Interaction> rawInteractions)
 0244        {
 0245            var result = _smoothingBehaviour.Update(rawInteractions);
 0246            InteractionHistoryUpdated?.Invoke(this, _smoothingBehaviour.InteractionsFramesCache);
 247
 0248            return result;
 0249        }
 250
 251        protected virtual ExtremumDescription ComputeExtremumType(Point3[][] pointsArray, int xPos, int yPos)
 0252        {
 0253            if (ExtremumTypeCheckMethod == ExtremumTypeCheckMethod.Global)
 0254                return new ExtremumDescription
 0255                    { Type = ExtremumType.Maximum, NumFittingPoints = ExtremumTypeCheckNumSamples, PercentageFittingPoin
 256
 0257            var xMax = pointsArray.Length - 1;
 0258            var yMax = xMax > 0 ? pointsArray[0].Length - 1 : 0;
 259
 260            // refZ is the absolute distance from sensor
 0261            var refZ = Math.Abs(pointsArray[xPos][yPos].Z);
 262
 0263            var numCloser = 0;
 0264            var numFarther = 0;
 265
 266            Tuple<int, int>[] samples;
 0267            switch (ExtremumTypeCheckMethod)
 268            {
 269                case ExtremumTypeCheckMethod.StochasticStatic:
 0270                    samples = _stochasticSamples;
 0271                    break;
 272                case ExtremumTypeCheckMethod.StochasticDynamic:
 0273                    samples = GenerateSamples();
 0274                    break;
 275                case ExtremumTypeCheckMethod.Global:
 0276                    throw new ArgumentException("invalid Method 'Global' at this point.");
 277                case ExtremumTypeCheckMethod.FixedRadius:
 278                default:
 0279                    samples = _fixedSamples;
 0280                    break;
 281            }
 282
 0283            for (var i = 0; i < samples.Length; i++)
 0284            {
 0285                var sample = GetSample(pointsArray, xPos, yPos, samples, i, xMax, yMax);
 0286                if (Math.Abs(sample.Z) > refZ)
 0287                    numFarther++;
 288                else
 0289                    numCloser++;
 0290            }
 291
 292
 0293            var ratioMax = ExtremumTypeCheckNumSamples > 0 ? (float)numCloser / ExtremumTypeCheckNumSamples : 0;
 0294            var ratioMin = ExtremumTypeCheckNumSamples > 0 ? (float)numFarther / ExtremumTypeCheckNumSamples : 0;
 295
 0296            if (numCloser > numFarther && ratioMax > ExtremumTypeCheckFittingPercentage)
 0297            {
 0298                return new ExtremumDescription
 0299                {
 0300                    Type = ExtremumType.Maximum,
 0301                    NumFittingPoints = numCloser,
 0302                    PercentageFittingPoints = ratioMax
 0303                };
 304            }
 305
 0306            if (numFarther > numCloser && ratioMin > ExtremumTypeCheckFittingPercentage)
 0307            {
 0308                return new ExtremumDescription
 0309                {
 0310                    Type = ExtremumType.Minimum,
 0311                    NumFittingPoints = numFarther,
 0312                    PercentageFittingPoints = ratioMin
 0313                };
 314            }
 315
 0316            return new ExtremumDescription
 0317            {
 0318                Type = ExtremumType.Undefined,
 0319                NumFittingPoints = Math.Max(numCloser, numFarther),
 0320                PercentageFittingPoints = Math.Max(ratioMin, ratioMax)
 0321            };
 322
 0323        }
 324
 325        public List<Interaction> ConvertDepthValue(List<Interaction> interactions)
 0326        {
 0327            var result = new List<Interaction>();
 328
 0329            foreach (var item in interactions)
 0330            {
 0331                if (item == null)
 0332                    continue;
 333
 0334                if (item.Position.Z < Distance)
 0335                {
 0336                    var depth = (Distance - item.Position.Z - MinDistance) / (MinDistance - MaxDistance);
 337
 0338                    if (depth > 0)
 0339                        continue;
 340
 0341                    if (depth < -1)
 0342                        depth = -1;
 343
 0344                    item.Position.Z = depth;
 0345                }
 346                else
 0347                {
 0348                    var depth = (item.Position.Z - MinDistance - Distance) / (MaxDistance - MinDistance);
 349
 0350                    if (depth < 0)
 0351                        continue;
 352
 0353                    if (depth > 1)
 0354                        depth = 1;
 355
 0356                    item.Position.Z = depth;
 0357                }
 358
 0359                result.Add(item);
 0360            }
 361
 0362            return result;
 0363        }
 364
 365        protected virtual IEnumerable<Interaction> ApplyConfidenceFilter(IEnumerable<Interaction> interactions)
 0366        {
 0367            return interactions.Where(item => item.Confidence > MinConfidence);
 0368        }
 369
 370        protected virtual List<Interaction> ComputeExtremumType(List<Interaction> interactions, Point3[][] pointsArray)
 0371        {
 0372            interactions.ForEach(interaction =>
 0373                interaction.ExtremumDescription = ComputeExtremumType(pointsArray, (int)interaction.Position.X, (int)int
 374
 0375            return interactions;
 0376        }
 377
 378        protected virtual void UpdatePerformanceMetrics(ProcessPerformance perfItem)
 0379        {
 0380            var pData = new PerformanceDataItem
 0381            {
 0382                FrameId = Convert.ToInt32(FrameId),
 0383                FrameStart = DateTime.Now.Ticks,
 0384                Process = perfItem,
 0385                Stage = PerformanceDataStage.ProcessingData
 0386            };
 387
 0388            PerformanceDataUpdated?.Invoke(this, pData);
 0389        }
 390
 391        /// <summary>
 392        /// Calculates the average distance for the currently stored PointCloud.
 393        /// </summary>
 394        /// <returns></returns>
 395        public virtual float CalculateAverageDistance()
 0396        {
 0397            var sum = 0f;
 0398            var points = PointCloud?.AsArray();
 399
 0400            if (points == null)
 0401                return sum;
 402
 0403            var numValidSamples = 0;
 404
 0405            for (var i = 0; i < points.Length; ++i)
 0406            {
 0407                if (!points[i].IsValid || points[i].IsFiltered)
 0408                    continue;
 409
 0410                numValidSamples++;
 0411                sum += points[i].Z;
 0412            }
 413
 0414            return (float) decimal.Round((decimal) (sum / numValidSamples), 2);
 0415        }
 416
 417        private static Point3 GetSample(Point3[][] pointsArray, int xPos, int yPos, Tuple<int, int>[] samples, int i, in
 0418        {
 0419            var xIdx = xPos + samples[i].Item1;
 0420            xIdx = Math.Min(Math.Max(xIdx, 0), xMax);
 421
 0422            var yIdx = yPos + samples[i].Item2;
 0423            yIdx = Math.Min(Math.Max(yIdx, 0), yMax);
 0424            var sample = pointsArray[xIdx][yIdx];
 425
 0426            return sample;
 0427        }
 428
 429        private Tuple<int, int>[] GenerateSamples()
 0430        {
 0431            var result = new List<Tuple<int, int>>();
 432
 0433            var rnd = new Random();
 434
 0435            var min = (int)Math.Floor(0.5f * ExtremumTypeCheckRadius);
 0436            var max = ExtremumTypeCheckRadius;
 437
 0438            for (var i = 0; i < ExtremumTypeCheckNumSamples; i++)
 0439            {
 0440                var xStochastic = rnd.Next(min, max);
 0441                var yStochastic = rnd.Next(min, max);
 442
 0443                result.Add(new Tuple<int, int>(xStochastic, yStochastic));
 0444            }
 445
 0446            return result.ToArray();
 0447        }
 448
 449        private void UpdateSamples()
 0450        {
 0451            var samplesFixed = new List<Tuple<int, int>>();
 452
 0453            for (var i = 0; i < ExtremumTypeCheckNumSamples; i++)
 0454            {
 0455                var p = (float)i / ExtremumTypeCheckRadius;
 0456                var xFixed = (int) Math.Floor(ExtremumTypeCheckRadius * Math.Cos(p * 2 * Math.PI));
 0457                var yFixed = (int) Math.Floor(ExtremumTypeCheckRadius * Math.Sin(p * 2 * Math.PI));
 458
 0459                samplesFixed.Add(new Tuple<int, int>(xFixed, yFixed));
 0460            }
 0461            _fixedSamples = samplesFixed.ToArray();
 462
 0463            _stochasticSamples = GenerateSamples();
 0464        }
 465    }
 466}

Methods/Properties

.ctor()
get_Distance()
get_MinDistance()
get_MaxDistance()
get_ExtremumTypeCheckNumSamples()
set_ExtremumTypeCheckNumSamples(System.Int32)
get_ExtremumTypeCheckRadius()
set_ExtremumTypeCheckRadius(System.Int32)
get_ExtremumTypeCheckFittingPercentage()
get_ExtremumTypeCheckMethod()
get_InteractionHistorySize()
set_InteractionHistorySize(System.Int32)
get_NumSmoothingFrames()
set_NumSmoothingFrames(System.Int32)
get_MaxNumEmptyFramesBetween()
set_MaxNumEmptyFramesBetween(System.Int32)
get_TouchMergeDistance2D()
set_TouchMergeDistance2D(System.Single)
get_DepthScale()
set_DepthScale(System.Single)
get_FilterType()
set_FilterType(ReFlex.Core.Interactivity.Util.FilterType)
get_MinAngle()
get_MinConfidence()
get_MaxConfidence()
set_MaxConfidence(System.Single)
get_MeasurePerformance()
get_FrameId()
UpdateFrameId(System.Int32)
ComputeSmoothingValue(System.Collections.Generic.IList`1<ReFlex.Core.Common.Components.Interaction>)
ComputeExtremumType(ReFlex.Core.Common.Components.Point3[][],System.Int32,System.Int32)
ConvertDepthValue(System.Collections.Generic.List`1<ReFlex.Core.Common.Components.Interaction>)
ApplyConfidenceFilter(System.Collections.Generic.IEnumerable`1<ReFlex.Core.Common.Components.Interaction>)
ComputeExtremumType(System.Collections.Generic.List`1<ReFlex.Core.Common.Components.Interaction>,ReFlex.Core.Common.Components.Point3[][])
UpdatePerformanceMetrics(ReFlex.Core.Common.Util.ProcessPerformance)
CalculateAverageDistance()
GetSample(ReFlex.Core.Common.Components.Point3[][],System.Int32,System.Int32,System.Tuple`2<System.Int32,System.Int32>[],System.Int32,System.Int32,System.Int32)
GenerateSamples()
UpdateSamples()