void cvUpdateTracks(CvBlobs const &blobs, CvTracks &tracks, const double thDistance, const unsigned int thInactive, const unsigned int thActive) { CV_FUNCNAME("cvUpdateTracks"); __CV_BEGIN__; unsigned int nBlobs = blobs.size(); unsigned int nTracks = tracks.size(); // Proximity matrix: // Last row/column is for ID/label. // Last-1 "/" is for accumulation. CvID *close = new unsigned int[(nBlobs+2)*(nTracks+2)]; // XXX Must be same type than CvLabel. try { // Inicialization: unsigned int i=0; for (CvBlobs::const_iterator it = blobs.begin(); it!=blobs.end(); ++it, i++) { AB(i) = 0; IB(i) = it->second->label; } CvID maxTrackID = 0; unsigned int j=0; for (CvTracks::const_iterator jt = tracks.begin(); jt!=tracks.end(); ++jt, j++) { AT(j) = 0; IT(j) = jt->second->id; if (jt->second->id > maxTrackID) maxTrackID = jt->second->id; } // Proximity matrix calculation and "used blob" list inicialization: for (i=0; i<nBlobs; i++) for (j=0; j<nTracks; j++) if (C(i, j) = (distantBlobTrack(B(i), T(j)) < thDistance)) { AB(i)++; AT(j)++; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Detect inactive tracks for (j=0; j<nTracks; j++) { unsigned int c = AT(j); if (c==0) { //cout << "Inactive track: " << j << endl; // Inactive track. CvTrack *track = T(j); track->inactive++; track->label = 0; } } // Detect new tracks for (i=0; i<nBlobs; i++) { unsigned int c = AB(i); if (c==0) { //cout << "Blob (new track): " << maxTrackID+1 << endl; //cout << *B(i) << endl; // New track. maxTrackID++; CvBlob *blob = B(i); CvTrack *track = new CvTrack; track->id = maxTrackID; track->label = blob->label; track->minx = blob->minx; track->miny = blob->miny; track->maxx = blob->maxx; track->maxy = blob->maxy; track->centroid = blob->centroid; track->lifetime = 0; track->active = 0; track->inactive = 0; tracks.insert(CvIDTrack(maxTrackID, track)); } } // Clustering for (j=0; j<nTracks; j++) { unsigned int c = AT(j); if (c) { list<CvTrack*> tt; tt.push_back(T(j)); list<CvBlob*> bb; getClusterForTrack(j, close, nBlobs, nTracks, blobs, tracks, bb, tt); // Select track CvTrack *track; unsigned int area = 0; for (list<CvTrack*>::const_iterator it=tt.begin(); it!=tt.end(); ++it) { CvTrack *t = *it; unsigned int a = (t->maxx-t->minx)*(t->maxy-t->miny); if (a>area) { area = a; track = t; } } // Select blob CvBlob *blob; area = 0; //cout << "Matching blobs: "; for (list<CvBlob*>::const_iterator it=bb.begin(); it!=bb.end(); ++it) { CvBlob *b = *it; //cout << b->label << " "; if (b->area>area) { area = b->area; blob = b; } } //cout << endl; // Update track //cout << "Matching: track=" << track->id << ", blob=" << blob->label << endl; 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) track->active = 0; track->inactive = 0; // Others to inactive for (list<CvTrack*>::const_iterator it=tt.begin(); it!=tt.end(); ++it) { CvTrack *t = *it; if (t!=track) { //cout << "Inactive: track=" << t->id << endl; t->inactive++; t->label = 0; } } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// for (CvTracks::iterator jt=tracks.begin(); jt!=tracks.end();) if ((jt->second->inactive>=thInactive)||((jt->second->inactive)&&(thActive)&&(jt->second->active<thActive))) { delete jt->second; tracks.erase(jt++); } else { jt->second->lifetime++; if (!jt->second->inactive) jt->second->active++; ++jt; } } catch (...) { delete[] close; throw; // TODO: OpenCV style. } delete[] close; __CV_END__; }
void cvUpdateTracks(CvBlobs &b, CvTracks &t, const double thDistance, const unsigned int thInactive) { CV_FUNCNAME("cvUpdateTracks"); __BEGIN__; unsigned int nBlobs = b.size(); unsigned int nTracks = t.size(); // Proximity matrix: // Last row/column is for ID/label. // Last-1 "/" is for accumulation. CvID *close = new unsigned int[(nBlobs+2)*(nTracks+2)]; // XXX Must be same type than CvLabel. // Access to matrix #define C(blob, track) close[((blob) + (track)*(nBlobs+2))] // Access to accumulators #define AB(label) C((label), (nTracks)) #define AT(id) C((nBlobs), (id)) // Access to identifications #define IB(label) C((label), (nTracks)+1) #define IT(id) C((nBlobs)+1, (id)) // Access to registers #define B(label) b[IB(label)] #define T(id) t[IT(id)] try { // Inicialization: unsigned int i=0; for (CvBlobs::const_iterator it = b.begin(); it!=b.end(); ++it, i++) { AB(i) = 0; IB(i) = it->second->label; } CvID maxTrackID = 0; unsigned int j=0; for (CvTracks::const_iterator jt = t.begin(); jt!=t.end(); ++jt, j++) { AT(j) = 0; IT(j) = jt->second->id; if (jt->second->id > maxTrackID) maxTrackID = jt->second->id; } // Proximity matrix calculation: for (i=0; i<nBlobs; i++) for (j=0; j<nTracks; j++) { if (C(i, j) = (distantBlobTrack(B(i), T(j)) < thDistance)) { AB(i)++; AT(j)++; } } // Run over tracks: for (j=0; j<nTracks; j++) { //unsigned int c = C(nBlobs, j); unsigned int c = AT(j); if (c == 1) { // Match track-blob // Search for the blob for (i=0; (i<nBlobs)&&(!C(i, j)); i++) {} // Update track CvBlob *blob = B(i); CvTrack *track = T(j); track->label = blob->label; track->centroid = blob->centroid; track->minx = blob->minx; track->miny = blob->miny; track->maxx = blob->maxx; track->maxy = blob->maxy; track->inactive = 0; } else if (c > 1) { // Track divides CvTrack *track = T(j); track->inactive++; track->label=0; // Create new tracks for (i=0; i<nBlobs; i++) { if (C(i, j)) { maxTrackID++; CvBlob *blob = B(i); CvTrack *track = new CvTrack; track->id = maxTrackID; track->label = blob->label; track->minx = blob->minx; track->miny = blob->miny; track->maxx = blob->maxx; track->maxy = blob->maxy; track->centroid = blob->centroid; track->inactive = 0; t.insert(CvIDTrack(maxTrackID, track)); } } } else // if (c == 0) { // Inactive track CvTrack *track = T(j); track->inactive++; track->label = 0; } } // Run over blobs: for (i=0; i<nBlobs; i++) { //unsigned int c = C(i, nTracks); unsigned int c = AB(i); if (c == 0) { // New track maxTrackID++; CvBlob *blob = B(i); CvTrack *track = new CvTrack; track->id = maxTrackID; track->label = blob->label; track->minx = blob->minx; track->miny = blob->miny; track->maxx = blob->maxx; track->maxy = blob->maxy; track->centroid = blob->centroid; track->inactive = 0; t.insert(CvIDTrack(maxTrackID, track)); } else if (c > 1) { // Tracks joins // New track maxTrackID++; CvBlob *blob = B(i); CvTrack *track = new CvTrack; track->id = maxTrackID; track->label = blob->label; track->minx = blob->minx; track->miny = blob->miny; track->maxx = blob->maxx; track->maxy = blob->maxy; track->centroid = blob->centroid; track->inactive = 0; t.insert(CvIDTrack(maxTrackID, track)); // Others tracks inactives for (j=0; j<nTracks; j++) { T(j)->inactive++; T(j)->label = 0; } } } for (CvTracks::iterator jt=t.begin(); jt!=t.end();) if (jt->second->inactive>=thInactive) { delete jt->second; t.erase(jt++); } else ++jt; } catch (...) { delete[] close; throw; // TODO: OpenCV style. } delete[] close; __END__; }