private void SetThresholdScalars(double lh, double ls, double lv, double hh, double hs, double hv) { var settings = ThresholdSettings.Get(lh, ls, lv, hh, hs, hv); _detectorInput.Settings.Absorb(settings); UpdateThresholdSlidersFromSettings(); }
/// <summary> /// Compute the min DTW distance between seq2 and all possible endings of seq1. /// </summary> /// <param name="seq1">Sequence 1</param> /// <param name="seq2">Sequence 2</param> /// <param name="settings">The settings object</param> /// <returns>DTW distance</returns> public double dtw(ArrayList seq1, ArrayList seq2, ThresholdSettings settings) { // Init ArrayList seq1r = new ArrayList(seq1); seq1r.Reverse(); ArrayList seq2r = new ArrayList(seq2); seq2r.Reverse(); double[,] tab = new double[seq1r.Count + 1, seq2r.Count + 1]; int[,] slopeI = new int[seq1r.Count + 1, seq2r.Count + 1]; int[,] slopeJ = new int[seq1r.Count + 1, seq2r.Count + 1]; for (int i = 0; i < seq1r.Count + 1; i++) { for (int j = 0; j < seq2r.Count + 1; j++) { tab[i, j] = double.PositiveInfinity; slopeI[i, j] = 0; slopeJ[i, j] = 0; } } tab[0, 0] = 0; // Dynamic computation of the DTW matrix. for (int i = 1; i < seq1r.Count + 1; i++) { for (int j = 1; j < seq2r.Count + 1; j++) { if (tab[i, j - 1] < tab[i - 1, j - 1] && tab[i, j - 1] < tab[i - 1, j] && slopeI[i, j - 1] < settings.MaxSlope) { tab[i, j] = this.Distance((double[])seq1r[i - 1], (double[])seq2r[j - 1]) + tab[i, j - 1]; slopeI[i, j] = slopeJ[i, j - 1] + 1;; slopeJ[i, j] = 0; } else if (tab[i - 1, j] < tab[i - 1, j - 1] && tab[i - 1, j] < tab[i, j - 1] && slopeJ[i - 1, j] < settings.MaxSlope) { tab[i, j] = this.Distance((double[])seq1r[i - 1], (double[])seq2r[j - 1]) + tab[i - 1, j]; slopeI[i, j] = 0; slopeJ[i, j] = slopeJ[i - 1, j] + 1; } else { tab[i, j] = this.Distance((double[])seq1r[i - 1], (double[])seq2r[j - 1]) + tab[i - 1, j - 1]; slopeI[i, j] = 0; slopeJ[i, j] = 0; } } } // Find best between seq2 and an ending (postfix) of seq1. double bestMatch = double.PositiveInfinity; for (int i = 1; i < seq1r.Count + 1; i++) { if (tab[i, seq2r.Count] < bestMatch) { bestMatch = tab[i, seq2r.Count]; } } return(bestMatch); }
/// <summary> /// Recognizes a gesture sequence. It will always assume that the gesture ends on the last observation of that sequence. /// If the distance between the last observations of each sequence is too great, or if the overall DTW distance between /// the two sequence is too great, no gesture will be recognized /// </summary> /// <param name="seq"></param> /// <returns></returns> public IGesture Recognize(ArrayList seq) { double minDist = double.PositiveInfinity; GestureId gestureId = GestureId.Unknown; ThresholdSettings minSettings = null; for (int i = 0; i < sequences.Count; i++) { ThresholdSettings settings = (ThresholdSettings)recognitionSettings[i]; ArrayList example = (ArrayList)sequences[i]; if (this.Distance((double[])seq[seq.Count - 1], (double[])example[example.Count - 1]) < settings.FirstThreshold) { double d = dtw(seq, example, settings) / (example.Count); if (d < minDist) { minDist = d; gestureId = (GestureId)(sequenceIds[i]); minSettings = settings; } } } return(new Gesture() { Id = (minSettings != null && minDist < minSettings.MatchThreshold ? gestureId : GestureId.Unknown), MinDistance = minDist }); }
/// <summary> /// Constructor /// </summary> public RealExchange(IOptions <ExchangeProviderSettings> settings, IOptions <ThresholdSettings> thresholdSettings, IMapper mapper) { _settings = settings?.Value ?? throw new ArgumentNullException(nameof(settings)); _thresholdSettings = thresholdSettings?.Value ?? throw new ArgumentNullException(nameof(thresholdSettings)); _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper)); }
private bool IsColourFullFrame(CameraProcessInput input) { var isFullFrameColour = false; // detect all black using (new TemporaryThresholdSettings(_colourDetectorInput, ThresholdSettings.Get(0, 0, 0, 180, 255, 40))) { _colourDetectorInput.Captured = input.Captured; var colourOutput = _colourDetector.Process(_colourDetectorInput); const int fullFrameMinimumPercent = 70; var fullFramePixelCount = colourOutput.CapturedImage.Width * colourOutput.CapturedImage.Height; var mimimumColourPixelCount = fullFramePixelCount * fullFrameMinimumPercent / 100; isFullFrameColour = colourOutput.MomentArea > mimimumColourPixelCount; } return(isFullFrameColour); }
/// <summary> /// Creates a new instance based on xml configuration /// </summary> /// <param name="node">The node holding the configuration</param> /// <param name="throwOnMissing">Controls if an exception should be thrown if the attributes are missing</param> /// <returns>A new initialized instance or null</returns> public static ThresholdSettings CreateFromXML(XmlNode node, bool throwOnMissing = true) { ThresholdSettings result = null; if (node.Attributes.Count >= ThresholdSettings.AttributesCount) { result = new DTWRecognizer.ThresholdSettings() { FirstThreshold = double.Parse(node.Attributes["firstThreshold"].Value), MatchThreshold = double.Parse(node.Attributes["matchThreshold"].Value), MaxSlope = double.Parse(node.Attributes["maxSlope"].Value) } } ; else if (throwOnMissing) { throw new InvalidDataException("Invalid number of attributes"); } return(result); }
/// <summary> /// Add a seqence with a label to the known sequences library. /// The gesture MUST start on the first observation of the sequence and end on the last one. /// Sequences may have different lengths. /// </summary> /// <param name="gestureId">The gesture id</param> /// <param name="seq">The gesture sequence</param> /// <param name="settings">The threshold settings</param> public void AddPatterns(GestureId gestureId, ArrayList seq, ThresholdSettings settings) { sequences.Add(seq); sequenceIds.Add(gestureId); recognitionSettings.Add(settings); }