Ejemplo n.º 1
0
        public void CreateCurrent()
        {
            // arrange
            PointF center      = new PointF(3, 2);
            SizeF  size        = new SizeF(4, 5);
            Size   gridSize    = new Size(4, 2);
            SizeF  gridPadding = new SizeF(1, 1);
            IMedianFlowTrackerBoundingBox bb = new MedianFlowTrackerBoundingBox(
                center,
                size,
                gridSize,
                gridPadding
                );

            // define expected
            PointF expectedCenter      = new PointF(5.5f, 3.5f);
            SizeF  expectedSize        = new SizeF(6, 7.5f);
            Size   expectedGridSize    = gridSize;
            SizeF  expectedGridPadding = gridPadding;

            // get actual
            IMedianFlowTrackerBoundingBox IactualBB = bb.CreateCurrent(2.5f, 1.5f, 1.5f);
            MedianFlowTrackerBoundingBox  actualBB  = IactualBB as MedianFlowTrackerBoundingBox;

            // assert
            Assert.AreEqual(expectedCenter, actualBB.Center);
            Assert.AreEqual(expectedSize, actualBB.Size);
            Assert.AreEqual(expectedGridSize, actualBB.GridSize);
            Assert.AreEqual(expectedGridPadding, actualBB.GridPadding);
        }
Ejemplo n.º 2
0
        public MedianFlowTracker(
            IMedianFlowTrackerBoundingBox bb,
            ILucasKanadeTracker lucasKanade,
            FBError_Calculator FBError,
            NCC_Calculator NCC,
            Size patchSize,
            float madTreshold
            )
        {
            _currentBb   = bb;
            _lucasKanade = lucasKanade;
            _FBError     = FBError;
            _NCC         = NCC;
            _patchSize   = patchSize;
            _madTreshold = madTreshold;

            _failureEnabled = true;
        }
Ejemplo n.º 3
0
        public IBoundingBox FindObject(Image <Gray, byte> currentFrame)
        {
            /* If the tracker failed in the past,
             * don't try to track the object anymore
             */
            if (_failed)
            {
                return(null);
            }

            /* Set up the state.
             */
            _previousBb = _currentBb;

            /* Get valid shifts.
             * Valid shift is a shift where both forward and backward point are found inside the frame.
             */

            // track points forward and backward
            PointF[] prevPoints = _previousBb.GetGridPoints();
            byte[]   forwStatus;
            PointF[] forwPoints = _lucasKanade.TrackPointsForward(prevPoints, currentFrame, out forwStatus);
            byte[]   backStatus;
            PointF[] backPoints = _lucasKanade.TrackPointsBackward(out backStatus);

            // create valid shifts
            List <Shift> validShiftList = new List <Shift>();

            for (int i = 0; i < prevPoints.Length; i++)
            {
                if (forwStatus[i] == 1 && backStatus[i] == 1)
                {
                    Shift shift = new Shift(prevPoints[i], forwPoints[i], backPoints[i]);
                    validShiftList.Add(shift);
                }
            }
            _validShiftArray = validShiftList.ToArray();

            // if there are less that 2 valid shifts, return null
            // (2 shifts are minimum if want to calculate scale)
            if (_validShiftArray.Length < 2)
            {
                Status = MedianFlowTrackerStatus.NOT_ENOUGH_VALID_SHIFTS;
                if (_failureEnabled)
                {
                    _failed = true;
                }
                return(null);
            }

            /* Leave only reliable shifts.
             * Reliable shift is a shift which has, at the same time:
             *       - FB error <= median(FB error)
             *       - NCC      >= median(NCC)
             */

            // calculate FB error and NCC for each shift
            foreach (Shift shift in _validShiftArray)
            {
                shift.FBError = _FBError(shift.Previous, shift.Backward);
                shift.NCC     = _NCC(
                    _previousFrame.GetPatch(shift.Previous, _patchSize),
                    currentFrame.GetPatch(shift.Forward, _patchSize)
                    );
            }

            // calculate FB error and NCC median
            FbErrorMedian = Service.GetMedian <Shift>(_validShiftArray, s => s.FBError);
            NccMedian     = Service.GetMedian <Shift>(_validShiftArray, s => s.NCC);

            // if MAD (fbErrorMedian) is bigger that a threshold, return null
            if (FbErrorMedian > _madTreshold)
            {
                Status = MedianFlowTrackerStatus.MAD_TOO_BIG;
                if (_failureEnabled)
                {
                    _failed = true;
                }
                return(null);
            }

            // leave only reliable shifts
            List <Shift> reliableShiftList = new List <Shift>();

            foreach (Shift shift in _validShiftArray)
            {
                if (shift.FBError <= FbErrorMedian && shift.NCC >= NccMedian)
                {
                    reliableShiftList.Add(shift);
                }
            }
            _reliableShiftArray = reliableShiftList.ToArray();

            // if there are no reliable shifts, return null
            if (_reliableShiftArray.Length < 2)
            {
                Status = MedianFlowTrackerStatus.NOT_ENOUGH_RELIABLE_SHIFTS;
                if (_failureEnabled)
                {
                    _failed = true;
                }
                return(null);
            }

            /* Calculate horizontal translation, vertical translation and scale of the previous bounding box
             * Horizontal translation = median(horizontal translations of all shifts)
             * Vertical   translation = median(vertical   translations of all shifts)
             * Scale calculation:
             *      - for every pair of shifts,
             *        calculate the ratio between the distances of their forward and previous points
             *      - scale is the median of these ratios
             */

            // calculate horizontal and vertical translation
            float transX = Service.GetMedian <Shift>(_reliableShiftArray, s => s.Horizontal);
            float transY = Service.GetMedian <Shift>(_reliableShiftArray, s => s.Vertical);

            // calculate scale
            Combinations <Shift> shiftPairs = new Combinations <Shift>(_reliableShiftArray, 2);
            long n = shiftPairs.Count;

            float[] ratios = new float[n];

            long _pair = 0;

            foreach (IList <Shift> pair in shiftPairs)
            {
                Shift s1       = pair[0];
                Shift s2       = pair[1];
                float forwDist = s1.Forward.DistanceTo(s2.Forward);
                float prevDist = s1.Previous.DistanceTo(s2.Previous);
                ratios[_pair] = forwDist / prevDist;
                _pair++;
            }

            float scale = Service.GetMedian <float>(ratios, r => r);

            /* Declare a tracking success and return the new bounding box
             */

            Status         = MedianFlowTrackerStatus.OK;
            _previousFrame = currentFrame;
            _currentBb     = _previousBb.CreateCurrent(transX, transY, scale);
            return(_currentBb);
        }