/// <summary> /// Analyzes the image frame, applies filters and creates new <see cref="TrackerResult"/> objects. /// This method performs a deep analysis over the frame and is computationally expensive. /// Use this method wisely and never more than once per frame. If you need to get the tracker results /// multiple times in a frame use <see cref="GetLatestResult"/> instead. /// </summary> /// <param name="weightThreshold">The allowed amount of particles distribution to consider a good result.</param> /// <returns>The latest tracking result.</returns> public List <TrackerResult> Compute(float weightThreshold = 0.01f) { _result.Clear(); if (_input != null && _running) { int dstW = _input.width / _downscaleAmount; int dstH = _input.height / _downscaleAmount; if (_input.data == null) { return(_result); } if (_downscaleAmount > 1) { int requiredBufferLenght = dstW * dstH * 3; if (_resizedBuffer == null || _resizedBuffer.Length != requiredBufferLenght) { _resizedBuffer = new byte[requiredBufferLenght]; } ResizeBuffer(_resizedBuffer, _input.data, _input.width, _input.height, dstW, dstH, 3, 3); } else { _resizedBuffer = _input.data; } if (enableColorTrack) { for (int i = 0; i < _processors.Count; ++i) { ColorProcessor clp = _processors[i]; TrackerResult result = _resultHash[i]; clp.Compute(_resizedBuffer, result, dstW, dstH, weightThreshold, useKalmanFilter); if (!IsPositionNearToBounds(ref result.center, 10.0f)) { result.center *= _downscaleAmount; _result.Add(result); } } } if (enableColorMap) { _colorMap.ComputeColorMap(_resizedBuffer, dstW, dstH, colorTargets, _downscaleAmount, colorMapPointSpacing); } if (listener != null && _result.Count > 0) { listener.WhenNewResultAvailable(this); } } return(_result); }
/// <summary> /// Search the color on the image buffer. When color is found it enables a new <see cref="TrackerResult"/> and sets the /// proper <see cref="TrackingState"/> to the object. To improve the memory usage the results are cached and persistent so /// it is safe to store reference to results. /// </summary> /// <param name="pixelsRGB">The image buffer in RGB format.</param> /// <param name="result">A reference to the cached result to write on.</param> /// <param name="width">The current frame width. (useful for occasional frame dimension changes)</param> /// <param name="height">The current frame height. (useful for occasional frame dimension changes)</param> /// <param name="weightThreshold">The allowed amount of particles distribution to consider a good result.</param> /// <param name="useKalmanFilter">Toggles the use of <see cref="KalmanFilter"/>.</param> public void Compute(byte[] pixelsRGB, TrackerResult result, int width, int height, float weightThreshold, bool useKalmanFilter) { if (target == null || pixelsRGB.Length == 0) { return; } _particle.colorTolerance = target.tolerance; _particle.Resample(width, height); _particle.Predict(); double w = _particle.ComputeWeight(pixelsRGB); if (w <= weightThreshold) { result.state = TrackingState.Lost; _particle.Reset(); } else { Vector3 prevCenter = result.center; _particle.Measure(ref result.center); float depth = ((float)w * 100 / _particle.ParticleCount()); result.center.z = depth; if (useKalmanFilter) { if (result.state == TrackingState.Tracked) { _kalman.Predict(ref result.center); } else { _kalman.ResetTo(result.center); } } Vector2 lvel = (result.center - prevCenter); lvel.y *= -1; result.linearVelocity = lvel; result.state = TrackingState.Tracked; } }