/// <summary> /// Updates list of tracks based on current blobs. /// </summary> /// <param name="blobs">List of blobs.</param> /// <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 & CVPR'01. December, 2001. /// (http://www.research.ibm.com/peoplevision/PETS2001.pdf) /// </remarks> public static void UpdateTracks(CvBlobs blobs, CvTracks tracks, double thDistance, int thInactive, int thActive) { if (blobs == null) { throw new ArgumentNullException("blobs"); } blobs.UpdateTracks(tracks, thDistance, thInactive, thActive); }
/// <summary> /// Prints tracks information. /// </summary> /// <param name="tracks">List of tracks.</param> /// <param name="imgSource">Input image (depth=IPL_DEPTH_8U and num. channels=3).</param> /// <param name="imgDest">Output image (depth=IPL_DEPTH_8U and num. channels=3).</param> /// <param name="mode">Render mode. By default is CV_TRACK_RENDER_ID.</param> public static void RenderTracks(CvTracks tracks, Mat imgSource, Mat imgDest, RenderTracksMode mode) { if (tracks == null) { throw new ArgumentNullException(nameof(tracks)); } tracks.Render(imgSource, imgDest, mode); }
/// <summary> /// Prints tracks information. /// </summary> /// <param name="tracks">List of tracks.</param> /// <param name="imgSource">Input image (depth=IPL_DEPTH_8U and num. channels=3).</param> /// <param name="imgDest">Output image (depth=IPL_DEPTH_8U and num. channels=3).</param> /// <param name="mode">Render mode. By default is CV_TRACK_RENDER_ID.</param> /// <param name="font">OpenCV font for print on the image.</param> public static void RenderTracks(CvTracks tracks, IplImage imgSource, IplImage imgDest, RenderTracksMode mode, CvFont font) { if (tracks == null) { throw new ArgumentNullException("tracks"); } tracks.Render(imgSource, imgDest, mode, font); }
/// <summary> /// Prints tracks information. /// </summary> /// <param name="tracks">List of tracks.</param> /// <param name="imgSource">Input image (depth=IPL_DEPTH_8U and num. channels=3).</param> /// <param name="imgDest">Output image (depth=IPL_DEPTH_8U and num. channels=3).</param> public static void RenderTracks(CvTracks tracks, Mat imgSource, Mat imgDest) { if (tracks == null) { throw new ArgumentNullException("tracks"); } tracks.Render(imgSource, imgDest); }
/// <summary> /// Prints tracks information. /// </summary> /// <param name="tracks">List of tracks.</param> /// <param name="imgSource">Input image (depth=IPL_DEPTH_8U and num. channels=3).</param> /// <param name="imgDest">Output image (depth=IPL_DEPTH_8U and num. channels=3).</param> public static void RenderTracks(CvTracks tracks, IplImage imgSource, IplImage imgDest) { if (tracks == null) { throw new ArgumentNullException(nameof(tracks)); } tracks.Render(imgSource, imgDest); }
/// <summary> /// Prints tracks information. /// </summary> /// <param name="tracks">List of tracks.</param> /// <param name="imgSource">Input image (depth=IPL_DEPTH_8U and num. channels=3).</param> /// <param name="imgDest">Output image (depth=IPL_DEPTH_8U and num. channels=3).</param> /// <param name="mode">Render mode. By default is CV_TRACK_RENDER_ID.</param> /// <param name="textColor"></param> /// <param name="fontFace"></param> /// <param name="fontScale"></param> /// <param name="thickness"></param> public static void RenderTracks(CvTracks tracks, Mat imgSource, Mat imgDest, RenderTracksMode mode, Scalar textColor, HersheyFonts fontFace = HersheyFonts.HersheySimplex, double fontScale = 1d, int thickness = 1) { if (tracks == null) { throw new ArgumentNullException(nameof(tracks)); } tracks.Render(imgSource, imgDest, mode, textColor, fontFace, fontScale, thickness); }
private static void GetClusterForTrack(int trackPos, ProximityMatrix close, int nBlobs, int nTracks, CvBlobs blobs, CvTracks tracks, List <CvBlob> bb, List <CvTrack> tt) { for (int i = 0; i < nBlobs; i++) { if (close[i, trackPos] != 0) { bb.Add(blobs[i]); int c = close.AB[i]; close[i, trackPos] = 0; close.AB[i]--; close.AT[trackPos]--; if (c > 1) { GetClusterForBlob(i, close, nBlobs, nTracks, blobs, tracks, bb, tt); } } } }
private static void GetClusterForTrack(int trackPos, ProximityMatrix close, int nBlobs, int nTracks, CvBlobs blobs, CvTracks tracks, List <CvBlob> bb, List <CvTrack> tt) { retry: var retryList = new List <int>(); for (int i = 0; i < nBlobs; i++) { if (close[i, trackPos] != 0) { int ib = close.IB[i]; bb.Add(blobs[ib]); int c = close.AB[i]; close[i, trackPos] = 0; close.AB[i]--; close.AT[trackPos]--; if (c > 1) { retryList.Add(i); //GetClusterForBlob(i, close, nBlobs, nTracks, blobs, tracks, bb, tt); } } } if (retryList.Count > 0) { foreach (int i in retryList) { GetClusterForBlob(i, close, nBlobs, nTracks, blobs, tracks, bb, tt); } goto retry; } }
private static void GetClusterForBlob(int blobPos, ProximityMatrix close, int nBlobs, int nTracks, CvBlobs blobs, CvTracks tracks, List <CvBlob> bb, List <CvTrack> tt) { for (int j = 0; j < nTracks; j++) { if (close[blobPos, j] != 0) { tt.Add(tracks[j]); int c = close.AT[j]; close[blobPos, j] = 0; close.AB[blobPos]--; close.AT[j]--; if (c > 1) { GetClusterForTrack(j, close, nBlobs, nTracks, blobs, tracks, bb, tt); } } } }
/// <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 & 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++; } } } }
/// <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> /// <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 & CVPR'01. December, 2001. /// (http://www.research.ibm.com/peoplevision/PETS2001.pdf) /// </remarks> public void UpdateTracks(CvTracks tracks, double thDistance, int thInactive) { UpdateTracks(tracks, thDistance, thInactive, 0); }
private static void GetClusterForBlob(int blobPos, ProximityMatrix close, int nBlobs, int nTracks, CvBlobs blobs, CvTracks tracks, List <CvBlob> bb, List <CvTrack> tt) { retry: var retryList = new List <int>(); for (int j = 0; j < nTracks; j++) { if (close[blobPos, j] != 0) { int it = close.IT[j]; tt.Add(tracks[it]); int c = close.AT[j]; close[blobPos, j] = 0; close.AB[blobPos]--; close.AT[j]--; if (c > 1) { retryList.Add(j); //GetClusterForTrack(j, close, nBlobs, nTracks, blobs, tracks, bb, tt); } } } if (retryList.Count > 0) { foreach (int j in retryList) { GetClusterForTrack(j, close, nBlobs, nTracks, blobs, tracks, bb, tt); } goto retry; } }