contrib/oxl/mvl/NViewMatches.cxx
Go to the documentation of this file.
00001 // This is oxl/mvl/NViewMatches.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 //  \file
00007 
00008 #include "NViewMatches.h"
00009 
00010 #include <vcl_cassert.h>
00011 #include <vcl_cstdlib.h> // for vcl_abort()
00012 #include <vcl_fstream.h>
00013 #include <vul/vul_awk.h>
00014 #include <vul/vul_printf.h>
00015 
00016 /////////////////////////////////////////////////////////////////////////////
00017 
00018 vcl_ostream& operator<<(vcl_ostream& s, const NViewMatch& c)
00019 {
00020   for (unsigned i = 0; i < c.size(); ++i)
00021     vul_printf(s, "%-4d ", c[i]);
00022 
00023   return s;
00024 }
00025 
00026 //: Return true if B is consistent with this match.
00027 //  Matches are consistent if they are identical in all non-wildcard positions.
00028 //  However, it additionally requires that they share at least min_overlap
00029 //  non-wildcard positions.
00030 bool NViewMatch::matches(const NViewMatch& b, int min_overlap) const
00031 {
00032   unsigned l = size();
00033 
00034   if (l != b.size()) {
00035     vcl_cerr << "NViewMatch::matches(B): matching vectors of different lengths\n";
00036     return false;
00037   }
00038 
00039   int overlap = 0;
00040   for (unsigned i = 0; i < l; ++i)
00041     if ((*this)[i] != NViewMatch::nomatch && b[i] != NViewMatch::nomatch) {
00042       if ((*this)[i] != b[i])
00043         return false;
00044       ++overlap;
00045     }
00046   return overlap >= min_overlap;
00047 }
00048 
00049 //: Fill any wildcard positions with the corresponding position in B.
00050 void NViewMatch::incorporate(const NViewMatch& b)
00051 {
00052   unsigned l = size();
00053   for (unsigned i = 0; i < l; ++i)
00054     if ((*this)[i] == NViewMatch::nomatch)
00055       (*this)[i] = b[i];
00056 }
00057 
00058 //: Check for any inconsistencies between matches
00059 bool NViewMatch::is_consistent(const NViewMatch& b) const
00060 {
00061   unsigned l = size();
00062   for (unsigned i = 0; i < l; ++i)
00063     if ((*this)[i] != NViewMatch::nomatch && b[i] != NViewMatch::nomatch)
00064       if ((*this)[i] != b[i])
00065         return false;
00066   return true;
00067 }
00068 
00069 //: Count how many non-wildcard entries are in this NViewMatch
00070 int NViewMatch::count_observations() const
00071 {
00072   unsigned l = size();
00073   int c = 0;
00074   for (unsigned i = 0; i < l; ++i)
00075     if ((*this)[i] != NViewMatch::nomatch)
00076       ++c;
00077   return c;
00078 }
00079 
00080 /////////////////////////////////////////////////////////////////////////////
00081 
00082 // Default ctor
00083 NViewMatches::NViewMatches():
00084   _min_overlap(2)
00085 {
00086 }
00087 
00088 NViewMatches::NViewMatches(vcl_istream& s)
00089 {
00090   load(s);
00091 }
00092 
00093 NViewMatches::NViewMatches(const char* filename)
00094 {
00095   load(filename);
00096 }
00097 
00098 NViewMatches::NViewMatches(int nviews, int min_overlap):
00099   _nviews(nviews), _min_overlap(min_overlap)
00100 {
00101 }
00102 
00103 NViewMatches::~NViewMatches() {
00104   //  delete _indx_array;
00105 }
00106 
00107 void NViewMatches::clear()
00108 {
00109   resize(0);
00110 }
00111 
00112 bool NViewMatches::load(const char* filename)
00113 {
00114   vcl_ifstream s(filename);
00115   if (!s.good()) {
00116     vcl_cerr << "NViewMatches::load(" << filename << ") - bad filename\n";
00117     return false;
00118   }
00119   return load(s);
00120 }
00121 
00122 bool NViewMatches::load(vcl_istream& s)
00123 {
00124   clear();
00125   for (vul_awk awk(s); awk; ++awk) {
00126     // On first line, set _nviews to field count
00127     // On subsequent lines, check the field count matches the first line.
00128     if (awk.NR() == 1)
00129       _nviews = awk.NF();
00130     else
00131       if (awk.NF() != _nviews) {
00132         vcl_cerr << "NViewMatches::load() ERROR: only " << awk.NF() << " fields on line " << awk.NR() << vcl_endl;
00133         return false;
00134       }
00135 
00136     // Build NViewMatch from this line and add it.
00137     NViewMatch v(_nviews);
00138     for (int j = 0; j < _nviews; ++j) {
00139       char const* cp = awk[j];
00140       if (cp[0] == '*')
00141         v[j] = NViewMatch::nomatch;
00142       else
00143         v[j] = atoi(cp);
00144     }
00145     push_back(v);
00146   }
00147 
00148   return true;
00149 }
00150 
00151 bool NViewMatches::save(vcl_ostream& s)
00152 {
00153   for (unsigned i = 0; i < size(); ++i)
00154     s << (*this)[i] << "\n";
00155   return s.good() != 0;
00156 }
00157 
00158 bool NViewMatches::save(const char* filename)
00159 {
00160   vcl_ofstream o(filename);
00161   return save(o);
00162 }
00163 
00164 //: Count how many matches are consistent with \argfont{match}
00165 int NViewMatches::count_matches(const NViewMatch& match)
00166 {
00167   int nmatches = 0;
00168   for (unsigned i = 0; i < size(); ++i)
00169     if ((*this)[i].matches(match,_min_overlap))
00170       ++nmatches;
00171   return nmatches;
00172 }
00173 
00174 //: Return an array of the indices that match the given match
00175 vcl_vector<int> NViewMatches::get_matches(const NViewMatch& match)
00176 {
00177   vcl_vector<int> ret;
00178   for (unsigned i = 0; i < size(); ++i)
00179     if (operator[](i).matches(match,_min_overlap))
00180       ret.push_back(i);
00181   return ret;
00182 }
00183 
00184 //: Add a new nview match to the set.
00185 // If it is just an update of an existing match (filling in a wildcard),
00186 // merge it.  Otherwise add it at the end.
00187 //
00188 // If the new match is consistent with two existing consistent matches
00189 // then all 3 are merged.
00190 //
00191 // If the new match is consistent with two existing inconsistent matches
00192 // they are both removed.
00193 //
00194 // Returns the index of the match into which the new match was merged, or
00195 // the index of the new match if it was consistent with nothing.
00196 // Returns -1 if inconsistency was found.
00197 
00198 int NViewMatches::incorporate(const NViewMatch& newtrack)
00199 {
00200   int nmatches = 0;
00201   iterator merged = end();
00202   vcl_abort(); // This routine is untested.....
00203   for (iterator i = begin(); i != end(); ++i) {
00204     if ((*i).matches(newtrack,_min_overlap)) {
00205       if (nmatches == 0) {
00206         // This is the first consistent match found for newtrack
00207         (*i).incorporate(newtrack);
00208         ++nmatches;
00209         merged = i;
00210       } else {
00211         if ((*i).is_consistent(*merged)) {
00212           vcl_cerr << "Merge : " << (*i) << vcl_endl;
00213           vcl_cerr << "        " << (*merged) << vcl_endl;
00214           // A further consistent match, so merge the two match tracks
00215           (*merged).incorporate((*i));
00216           erase(i);
00217           --i; // step back so we don't skip any matches
00218           ++nmatches;
00219         } else {
00220           // Two matches are inconsistent so remove them both and return -1
00221           //  vcl_cerr << "NViewMatches::incorporate(): Doh! Found inconsistent matches - removing them\n";
00222           erase(i);
00223           erase(merged);
00224           return -1;
00225         }
00226       }
00227     }
00228   }
00229   if (nmatches == 0) {
00230     push_back(newtrack);
00231     return size() - 1;
00232   }
00233 
00234 //  if (nmatches > 1) {
00235 //    vcl_cerr << "NViewMatches::incorporate(): " << nmatches << " consistent matches merged\n";
00236 //  }
00237 
00238   return merged - begin();
00239 }
00240 
00241 //: Build an NViewMatch from the triplet (base_view..base_view+2)
00242 NViewMatch NViewMatches::make_triplet_match(int base_view, int c1, int c2, int c3)
00243 {
00244   assert(base_view+2 < _nviews);
00245   NViewMatch newtrack(_nviews);
00246   newtrack[base_view] = c1;
00247   newtrack[base_view+1] = c2;
00248   newtrack[base_view+2] = c3;
00249   return newtrack;
00250 }
00251 
00252 //: Build an NViewMatch from the triplet (base_view..base_view+2), and incorporate.
00253 int NViewMatches::incorporate_triplet(int base_view, int c1, int c2, int c3)
00254 {
00255   assert(base_view+2 < _nviews);
00256   NViewMatch newtrack(_nviews);
00257   newtrack[base_view] = c1;
00258   newtrack[base_view+1] = c2;
00259   newtrack[base_view+2] = c3;
00260   return incorporate(newtrack);
00261 }
00262 
00263 // Should ALWAYS be called before using the match matrix!
00264 // Efficiently checks for inconsistencies and removes them.
00265 void NViewMatches::remove_inconsistencies() {
00266 }