예제 #1
0
        private double DistantBlobTrack(CvBlob b, CvTrack t)
        {
            double d1;

            if (b.Centroid.X < t.MinX)
            {
                if (b.Centroid.Y < t.MinY)
                {
                    d1 = Math.Max(t.MinX - b.Centroid.X, t.MinY - b.Centroid.Y);
                }
                else if (b.Centroid.Y > t.MaxY)
                {
                    d1 = Math.Max(t.MinX - b.Centroid.X, b.Centroid.Y - t.MaxY);
                }
                else // if (t.MinY < b.Centroid.Y)&&(b.Centroid.Y < t.MaxY)
                {
                    d1 = t.MinX - b.Centroid.X;
                }
            }
            else if (b.Centroid.X > t.MaxX)
            {
                if (b.Centroid.Y < t.MinY)
                {
                    d1 = Math.Max(b.Centroid.X - t.MaxX, t.MinY - b.Centroid.Y);
                }
                else if (b.Centroid.Y > t.MaxY)
                {
                    d1 = Math.Max(b.Centroid.X - t.MaxX, b.Centroid.Y - t.MaxY);
                }
                else
                {
                    d1 = b.Centroid.X - t.MaxX;
                }
            }
            else // if (t.MinX =< b.Centroid.X) && (b.Centroid.X =< t.MaxX)
            {
                if (b.Centroid.Y < t.MinY)
                {
                    d1 = t.MinY - b.Centroid.Y;
                }
                else if (b.Centroid.Y > t.MaxY)
                {
                    d1 = b.Centroid.Y - t.MaxY;
                }
                else
                {
                    return(0.0);
                }
            }

            double d2;

            if (t.Centroid.X < b.MinX)
            {
                if (t.Centroid.Y < b.MinY)
                {
                    d2 = Math.Max(b.MinX - t.Centroid.X, b.MinY - t.Centroid.Y);
                }
                else if (t.Centroid.Y > b.MaxY)
                {
                    d2 = Math.Max(b.MinX - t.Centroid.X, t.Centroid.Y - b.MaxY);
                }
                else // if (b.MinY < t.Centroid.Y)&&(t.Centroid.Y < b.MaxY)
                {
                    d2 = b.MinX - t.Centroid.X;
                }
            }
            else if (t.Centroid.X > b.MaxX)
            {
                if (t.Centroid.Y < b.MinY)
                {
                    d2 = Math.Max(t.Centroid.X - b.MaxX, b.MinY - t.Centroid.Y);
                }
                else if (t.Centroid.Y > b.MaxY)
                {
                    d2 = Math.Max(t.Centroid.X - b.MaxX, t.Centroid.Y - b.MaxY);
                }
                else
                {
                    d2 = t.Centroid.X - b.MaxX;
                }
            }
            else // if (b.MinX =< t.Centroid.X) && (t.Centroid.X =< b.MaxX)
            {
                if (t.Centroid.Y < b.MinY)
                {
                    d2 = b.MinY - t.Centroid.Y;
                }
                else if (t.Centroid.Y > b.MaxY)
                {
                    d2 = t.Centroid.Y - b.MaxY;
                }
                else
                {
                    return(0.0);
                }
            }

            return(Math.Min(d1, d2));
        }
예제 #2
0
        /// <summary>
        /// Updates list of tracks based on current blobs.
        /// </summary>
        /// <param name="tracks">List of tracks.</param>
        /// <param name="thDistance">Max distance to determine when a track and a blob match.</param>
        /// <param name="thInactive">Max number of frames a track can be inactive.</param>
        /// <param name="thActive">If a track becomes inactive but it has been active less than thActive frames, the track will be deleted.</param>
        /// <remarks>
        /// Tracking based on:
        /// A. Senior, A. Hampapur, Y-L Tian, L. Brown, S. Pankanti, R. Bolle. Appearance Models for
        /// Occlusion Handling. Second International workshop on Performance Evaluation of Tracking and
        /// Surveillance Systems &amp; CVPR'01. December, 2001.
        /// (http://www.research.ibm.com/peoplevision/PETS2001.pdf)
        /// </remarks>
        public void UpdateTracks(CvTracks tracks, double thDistance, int thInactive, int thActive)
        {
            if (tracks == null)
            {
                throw new ArgumentNullException("tracks");
            }

            int nBlobs  = this.Count;
            int nTracks = tracks.Count;

            if (nBlobs == 0)
            {
                return;
            }

            // Proximity matrix:
            // Last row/column is for ID/label.
            // Last-1 "/" is for accumulation.
            ProximityMatrix close = new ProximityMatrix(nBlobs, nTracks);

            // Initialization:
            int i = 0;

            foreach (CvBlob blob in Values)
            {
                close.AB[i] = 0;
                close.IB[i] = blob.Label;
                i++;
            }

            int maxTrackID = 0;
            int j          = 0;

            foreach (CvTrack track in tracks.Values)
            {
                close.AT[j] = 0;
                close.AT[j] = track.Id;
                if (track.Id > maxTrackID)
                {
                    maxTrackID = track.Id;
                }
                j++;
            }

            // Proximity matrix calculation and "used blob" list inicialization:
            for (i = 0; i < nBlobs; i++)
            {
                for (j = 0; j < nTracks; j++)
                {
                    CvBlob  b = this[close.IB[i]];
                    CvTrack t = tracks[close.IT[j]];
                    close[i, j] = (DistantBlobTrack(b, t) < thDistance) ? 1 : 0;
                    if (close[i, j] < thDistance)
                    {
                        close.AB[i]++;
                        close.AT[j]++;
                    }
                }
            }

            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            // Detect inactive tracks
            for (j = 0; j < nTracks; j++)
            {
                int c = close[nBlobs, j];
                if (c == 0)
                {
                    //cout << "Inactive track: " << j << endl;

                    // Inactive track.
                    CvTrack track = tracks[j];
                    track.Inactive++;
                    track.Label = 0;
                }
            }

            // Detect new tracks
            for (i = 0; i < nBlobs; i++)
            {
                int c = close.AB[i];
                if (c == 0)
                {
                    //cout << "Blob (new track): " << maxTrackID+1 << endl;
                    //cout << *B(i) << endl;

                    // New track.
                    maxTrackID++;
                    CvBlob  blob  = this[i + 1];
                    CvTrack track = new CvTrack
                    {
                        Id       = maxTrackID,
                        Label    = blob.Label,
                        MinX     = blob.MinX,
                        MinY     = blob.MinY,
                        MaxX     = blob.MaxX,
                        MaxY     = blob.MaxY,
                        Centroid = blob.Centroid,
                        LifeTime = 0,
                        Active   = 0,
                        Inactive = 0,
                    };
                    tracks[maxTrackID] = track;
                }
            }

            // Clustering
            for (j = 0; j < nTracks; j++)
            {
                int c = close.AT[j];
                if (c != 0)
                {
                    List <CvTrack> tt = new List <CvTrack> {
                        tracks[j]
                    };
                    List <CvBlob> bb = new List <CvBlob>();

                    GetClusterForTrack(j, close, nBlobs, nTracks, this, tracks, bb, tt);

                    // Select track
                    CvTrack track = null;
                    int     area  = 0;
                    foreach (CvTrack t in tt)
                    {
                        int a = (t.MaxX - t.MinX) * (t.MaxY - t.MinY);
                        if (a > area)
                        {
                            area  = a;
                            track = t;
                        }
                    }

                    // Select blob
                    CvBlob blob = null;
                    area = 0;
                    foreach (CvBlob b in Values)
                    {
                        if (b.Area > area)
                        {
                            area = b.Area;
                            blob = b;
                        }
                    }

                    if (blob == null || track == null)
                    {
                        throw new NotSupportedException();
                    }

                    // Update track
                    track.Label    = blob.Label;
                    track.Centroid = blob.Centroid;
                    track.MinX     = blob.MinX;
                    track.MinY     = blob.MinY;
                    track.MaxX     = blob.MaxX;
                    track.MaxY     = blob.MaxY;
                    if (track.Inactive != 0)
                    {
                        track.Active = 0;
                    }
                    track.Inactive = 0;

                    // Others to inactive
                    foreach (CvTrack t in tt)
                    {
                        if (t != track)
                        {
                            //cout << "Inactive: track=" << t->id << endl;
                            t.Inactive++;
                            t.Label = 0;
                        }
                    }
                }
            }
            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            int[] trackKeys = new int[tracks.Count];
            tracks.Keys.CopyTo(trackKeys, 0);
            foreach (int tkey in trackKeys)
            {
                CvTrack t = tracks[tkey];
                if ((t.Inactive >= thInactive) ||
                    ((t.Inactive != 0) && (thActive != 0) && (t.Active < thActive)))
                {
                    tracks.Remove(tkey);
                }
                else
                {
                    t.LifeTime++;
                    if (t.Inactive == 0)
                    {
                        t.Active++;
                    }
                }
            }
        }