Changeset View
Changeset View
Standalone View
Standalone View
libmv/autotrack/tracks.cc
| Context not available. | |||||
| #include <algorithm> | #include <algorithm> | ||||
| #include <vector> | #include <vector> | ||||
| #include <iterator> | #include <iterator> | ||||
| #include <set> | |||||
| #include "libmv/numeric/numeric.h" | #include "libmv/numeric/numeric.h" | ||||
| Context not available. | |||||
| markers_ = other.markers_; | markers_ = other.markers_; | ||||
| } | } | ||||
| Tracks::Tracks(const vector<Marker>& markers) : markers_(markers) {} | Tracks::Tracks(const TrackMarkersMap& markers) : markers_(markers) {} | ||||
| bool Tracks::GetMarker(int clip, int frame, int track, Marker* marker) const { | bool Tracks::GetMarker(int clip, int frame, int track, Marker* marker) const { | ||||
| for (int i = 0; i < markers_.size(); ++i) { | TrackMarkersMap::const_iterator foundTrack = markers_.find(track); | ||||
| if (markers_[i].clip == clip && | if (foundTrack == markers_.end()) { | ||||
| markers_[i].frame == frame && | return false; | ||||
| markers_[i].track == track) { | } | ||||
| *marker = markers_[i]; | ClipMarkersMap::const_iterator foundClip = foundTrack->second.find(clip); | ||||
| return true; | if (foundClip == foundTrack->second.end()) { | ||||
| } | return false; | ||||
| } | |||||
| FrameMarkerMap::const_iterator foundFrame = foundClip->second.find(frame); | |||||
| if (foundFrame == foundClip->second.end()) { | |||||
| return false; | |||||
| } else { | |||||
| *marker = foundFrame->second; | |||||
| return true; | |||||
| } | } | ||||
| return false; | |||||
| } | } | ||||
| void Tracks::GetMarkersForTrack(int track, vector<Marker>* markers) const { | void Tracks::GetMarkersForTrack(int track, vector<Marker>* markers) const { | ||||
| for (int i = 0; i < markers_.size(); ++i) { | TrackMarkersMap::const_iterator foundTrack = markers_.find(track); | ||||
| if (track == markers_[i].track) { | if (foundTrack == markers_.end()) { | ||||
| markers->push_back(markers_[i]); | return; | ||||
| } | |||||
| for (ClipMarkersMap::const_iterator it = foundTrack->second.begin(); it != foundTrack->second.end(); ++it) { | |||||
| for (FrameMarkerMap::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) { | |||||
| markers->push_back(it2->second); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| void Tracks::GetMarkersForTrackInClip(int clip, | void Tracks::GetMarkersForTrackInClip(int clip, | ||||
| int track, | int track, | ||||
| vector<Marker>* markers) const { | vector<Marker>* markers) const { | ||||
| for (int i = 0; i < markers_.size(); ++i) { | TrackMarkersMap::const_iterator foundTrack = markers_.find(track); | ||||
| if (clip == markers_[i].clip && | if (foundTrack == markers_.end()) { | ||||
| track == markers_[i].track) { | return; | ||||
| markers->push_back(markers_[i]); | } | ||||
| } | ClipMarkersMap::const_iterator foundClip = foundTrack->second.find(clip); | ||||
| if (foundClip == foundTrack->second.end()) { | |||||
| return; | |||||
| } | |||||
| for (FrameMarkerMap::const_iterator it2 = foundClip->second.begin(); it2 != foundClip->second.end(); ++it2) { | |||||
| markers->push_back(it2->second); | |||||
| } | } | ||||
| } | } | ||||
| void Tracks::GetMarkersInFrame(int clip, | void Tracks::GetMarkersInFrame(int clip, | ||||
| int frame, | int frame, | ||||
| vector<Marker>* markers) const { | vector<Marker>* markers) const { | ||||
| for (int i = 0; i < markers_.size(); ++i) { | for (TrackMarkersMap::const_iterator it = markers_.begin(); it!=markers_.end(); ++it) { | ||||
| if (markers_[i].clip == clip && | ClipMarkersMap::const_iterator foundClip = it->second.find(clip); | ||||
| markers_[i].frame == frame) { | if (foundClip == it->second.end()) { | ||||
| markers->push_back(markers_[i]); | continue; | ||||
| } | |||||
| FrameMarkerMap::const_iterator foundFrame = foundClip->second.find(frame); | |||||
| if (foundFrame == foundClip->second.end()) { | |||||
| continue; | |||||
| } else { | |||||
| markers->push_back(foundFrame->second); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| struct MarkerIteratorCompareLess | |||||
| { | |||||
| bool operator() (const FrameMarkerMap::const_iterator & lhs, | |||||
| const FrameMarkerMap::const_iterator & rhs) const | |||||
| { | |||||
| if (lhs->second.track < rhs->second.track) { | |||||
| return true; | |||||
| } else if (lhs->second.track > rhs->second.track) { | |||||
| return false; | |||||
| } else { | |||||
| if (lhs->second.clip < rhs->second.clip) { | |||||
| return true; | |||||
| } else if (lhs->second.clip > rhs->second.clip) { | |||||
| return false; | |||||
| } else { | |||||
| if (lhs->second.frame < rhs->second.frame) { | |||||
| return true; | |||||
| } else if (lhs->second.frame > rhs->second.frame) { | |||||
| return false; | |||||
| } else { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| }; | |||||
| typedef std::set<FrameMarkerMap::const_iterator, MarkerIteratorCompareLess> FrameMarkersIteratorSet; | |||||
| void Tracks::GetMarkersForTracksInBothImages(int clip1, int frame1, | void Tracks::GetMarkersForTracksInBothImages(int clip1, int frame1, | ||||
| int clip2, int frame2, | int clip2, int frame2, | ||||
| vector<Marker>* markers) const { | vector<Marker>* markers) const { | ||||
| std::vector<int> image1_tracks; | FrameMarkersIteratorSet image1_tracks; | ||||
| std::vector<int> image2_tracks; | FrameMarkersIteratorSet image2_tracks; | ||||
| // Collect the tracks in each of the two images. | // Collect the tracks in each of the two images. | ||||
| for (int i = 0; i < markers_.size(); ++i) { | |||||
| int clip = markers_[i].clip; | for (TrackMarkersMap::const_iterator it = markers_.begin(); it!=markers_.end(); ++it) { | ||||
| int frame = markers_[i].frame; | ClipMarkersMap::const_iterator foundClip = it->second.find(clip1); | ||||
| if (clip == clip1 && frame == frame1) { | if (foundClip == it->second.end()) { | ||||
| image1_tracks.push_back(markers_[i].track); | continue; | ||||
| } else if (clip == clip2 && frame == frame2) { | } | ||||
| image2_tracks.push_back(markers_[i].track); | FrameMarkerMap::const_iterator foundFrame = foundClip->second.find(frame1); | ||||
| if (foundFrame == foundClip->second.end()) { | |||||
| continue; | |||||
| } else { | |||||
| image1_tracks.insert(foundFrame); | |||||
| } | |||||
| } | |||||
| for (TrackMarkersMap::const_iterator it = markers_.begin(); it!=markers_.end(); ++it) { | |||||
| ClipMarkersMap::const_iterator foundClip = it->second.find(clip2); | |||||
| if (foundClip == it->second.end()) { | |||||
| continue; | |||||
| } | |||||
| FrameMarkerMap::const_iterator foundFrame = foundClip->second.find(frame2); | |||||
| if (foundFrame == foundClip->second.end()) { | |||||
| continue; | |||||
| } else { | |||||
| image2_tracks.insert(foundFrame); | |||||
| } | } | ||||
| } | } | ||||
| // Intersect the two sets to find the tracks of interest. | // Intersect the two sets to find the tracks of interest. | ||||
| std::sort(image1_tracks.begin(), image1_tracks.end()); | |||||
| std::sort(image2_tracks.begin(), image2_tracks.end()); | for (FrameMarkersIteratorSet::const_iterator it = image1_tracks.begin(); it != image1_tracks.end(); ++it) { | ||||
| std::vector<int> intersection; | FrameMarkersIteratorSet::const_iterator foundInImage2Tracks = image2_tracks.find(*it); | ||||
| std::set_intersection(image1_tracks.begin(), image1_tracks.end(), | if (foundInImage2Tracks != image2_tracks.end()) { | ||||
| image2_tracks.begin(), image2_tracks.end(), | markers->push_back((*it)->second); | ||||
| std::back_inserter(intersection)); | |||||
| // Scan through and get the relevant tracks from the two images. | |||||
| for (int i = 0; i < markers_.size(); ++i) { | |||||
| // Save markers that are in either frame and are in our candidate set. | |||||
| if (((markers_[i].clip == clip1 && | |||||
| markers_[i].frame == frame1) || | |||||
| (markers_[i].clip == clip2 && | |||||
| markers_[i].frame == frame2)) && | |||||
| std::binary_search(intersection.begin(), | |||||
| intersection.end(), | |||||
| markers_[i].track)) { | |||||
| markers->push_back(markers_[i]); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| void Tracks::AddMarker(const Marker& marker) { | void Tracks::AddMarker(const Marker& marker) { | ||||
| // TODO(keir): This is quadratic for repeated insertions. Fix this by adding | ClipMarkersMap& tracks = markers_[marker.track]; | ||||
| // a smarter data structure like a set<>. | FrameMarkerMap& frames = tracks[marker.clip]; | ||||
| for (int i = 0; i < markers_.size(); ++i) { | frames[marker.frame] = marker; | ||||
| if (markers_[i].clip == marker.clip && | |||||
| markers_[i].frame == marker.frame && | |||||
| markers_[i].track == marker.track) { | |||||
| markers_[i] = marker; | |||||
| return; | |||||
| } | |||||
| } | |||||
| markers_.push_back(marker); | |||||
| } | } | ||||
| void Tracks::SetMarkers(vector<Marker>* markers) { | void Tracks::SetMarkers(TrackMarkersMap* markers) { | ||||
| std::swap(markers_, *markers); | std::swap(markers_, *markers); | ||||
| } | } | ||||
| bool Tracks::RemoveMarker(int clip, int frame, int track) { | bool Tracks::RemoveMarker(int clip, int frame, int track) { | ||||
| int size = markers_.size(); | TrackMarkersMap::iterator foundTrack = markers_.find(track); | ||||
| for (int i = 0; i < markers_.size(); ++i) { | if (foundTrack == markers_.end()) { | ||||
| if (markers_[i].clip == clip && | return false; | ||||
| markers_[i].frame == frame && | } | ||||
| markers_[i].track == track) { | ClipMarkersMap::iterator foundClip = foundTrack->second.find(clip); | ||||
| markers_[i] = markers_[size - 1]; | if (foundClip == foundTrack->second.end()) { | ||||
| markers_.resize(size - 1); | return false; | ||||
| return true; | } | ||||
| } | FrameMarkerMap::iterator foundFrame = foundClip->second.find(frame); | ||||
| if (foundFrame == foundClip->second.end()) { | |||||
| return false; | |||||
| } else { | |||||
| foundClip->second.erase(foundFrame); | |||||
| return true; | |||||
| } | } | ||||
| return false; | |||||
| } | } | ||||
| void Tracks::RemoveMarkersForTrack(int track) { | void Tracks::RemoveMarkersForTrack(int track) { | ||||
| int size = 0; | TrackMarkersMap::iterator foundTrack = markers_.find(track); | ||||
| for (int i = 0; i < markers_.size(); ++i) { | if (foundTrack == markers_.end()) { | ||||
| if (markers_[i].track != track) { | return; | ||||
| markers_[size++] = markers_[i]; | |||||
| } | |||||
| } | } | ||||
| markers_.resize(size); | markers_.erase(foundTrack); | ||||
| } | } | ||||
| int Tracks::MaxClip() const { | int Tracks::MaxClip() const { | ||||
| int max_clip = 0; | int max_clip = 0; | ||||
| for (int i = 0; i < markers_.size(); ++i) { | for (TrackMarkersMap::const_iterator it = markers_.begin(); it!=markers_.end(); ++it) { | ||||
| max_clip = std::max(markers_[i].clip, max_clip); | if (!it->second.empty()) { | ||||
| max_clip = std::max(it->second.rbegin()->first, max_clip); | |||||
| } | |||||
| } | } | ||||
| return max_clip; | return max_clip; | ||||
| } | } | ||||
| int Tracks::MaxFrame(int clip) const { | int Tracks::MaxFrame(int clip) const { | ||||
| int max_frame = 0; | int max_frame = 0; | ||||
| for (int i = 0; i < markers_.size(); ++i) { | for (TrackMarkersMap::const_iterator it = markers_.begin(); it!=markers_.end(); ++it) { | ||||
| if (markers_[i].clip == clip) { | ClipMarkersMap::const_iterator foundClip = it->second.find(clip); | ||||
| max_frame = std::max(markers_[i].frame, max_frame); | if (foundClip == it->second.end()) { | ||||
| continue; | |||||
| } | |||||
| if (!foundClip->second.empty()) { | |||||
| max_frame = std::max(foundClip->second.rbegin()->first, max_frame); | |||||
| } | } | ||||
| } | } | ||||
| return max_frame; | return max_frame; | ||||
| } | } | ||||
| int Tracks::MaxTrack() const { | int Tracks::MaxTrack() const { | ||||
| int max_track = 0; | if (!markers_.empty()) { | ||||
| for (int i = 0; i < markers_.size(); ++i) { | return markers_.rbegin()->first; | ||||
| max_track = std::max(markers_[i].track, max_track); | } else { | ||||
| return 0; | |||||
| } | } | ||||
| return max_track; | |||||
| } | } | ||||
| int Tracks::NumMarkers() const { | int Tracks::NumMarkers() const { | ||||
| Context not available. | |||||