Isis 3 Programmer Reference
SmtkMatcher.cpp
Go to the documentation of this file.
1 
24 #include <cmath>
25 #include <cstdlib>
26 #include <ctime>
27 #include <sstream>
28 #include <iostream>
29 #include <iomanip>
30 
31 #include <QSharedPointer>
32 
33 #include "Camera.h"
34 #include "Projection.h"
35 #include "SpecialPixel.h"
36 #include "SmtkMatcher.h"
37 
38 
39 namespace Isis {
40 
42  SmtkMatcher::SmtkMatcher() : m_lhCube(0), m_rhCube(0), m_gruen(),
43  m_offImage(0), m_spiceErr(0),
44  m_useAutoReg(true) {
46  }
47 
49  SmtkMatcher::SmtkMatcher(const QString &regdef) : m_lhCube(0),
50  m_rhCube(0),
51  m_gruen(0),
52  m_offImage(0),
53  m_spiceErr(0),
54  m_useAutoReg(true) {
55  setGruenDef(regdef);
57  }
58 
60  SmtkMatcher::SmtkMatcher(const QString &regdef, Cube *lhCube,
61  Cube *rhCube) : m_lhCube(lhCube),
62  m_rhCube(rhCube),
63  m_gruen(0), m_offImage(0),
64  m_spiceErr(0),
65  m_useAutoReg(true) {
66  setGruenDef(regdef);
68  }
69 
72  gsl_rng_free(r);
73  }
74 
75 
77  void SmtkMatcher::setImages(Cube *lhCube, Cube *rhCube) {
78  m_lhCube = lhCube;
79  m_rhCube = rhCube;
80  return;
81  }
82 
95  void SmtkMatcher::setGruenDef(const QString &regdef) {
96  Pvl reg(regdef);
97  m_gruen = QSharedPointer<Gruen> (new Gruen(reg)); // Deallocation automatic
98  return;
99  }
100 
118  bool SmtkMatcher::isValid(const Coordinate &pnt) {
119  validate(); // cubs and cameras
120  Coordinate pnt2 = getLatLon(lhCamera(), pnt);
121  if (pnt2.isValid()) {
122  pnt2 = getLineSample(rhCamera(), pnt2);
123  }
124  return (pnt2.isValid());
125  }
126 
149  void SmtkMatcher::setWriteSubsearchChipPattern(const QString &fileptrn) {
150  validate();
151  m_gruen->WriteSubsearchChips(fileptrn);
152  }
153 
166  SmtkQStackIter SmtkMatcher::FindSmallestEV(SmtkQStack &stack) {
167  SmtkQStackIter best(stack.begin()), current(stack.begin());
168  while ( current != stack.end() ) {
169  if (current.value().GoodnessOfFit() < best.value().GoodnessOfFit() ) {
170  best = current;
171  }
172  ++current;
173  }
174  return (best);
175  }
176 
177 
199  SmtkQStackIter SmtkMatcher::FindExpDistEV(SmtkQStack &stack,
200  const double &seedsample,
201  const double &minEV,
202  const double &maxEV) {
203 
204  if (stack.isEmpty()) return (stack.end());
205  SmtkQStackIter best(stack.begin()), current(stack.begin());
206 
207  // Random number generator must scale between 0 and 1
208  double randNum = gsl_rng_uniform (r);
209  double t1 = -std::log(1.0 - randNum *
210  (1.0 - std::exp(-seedsample)))/seedsample;
211  double pt = minEV + t1*(maxEV-minEV);
212  double best_ev(DBL_MAX);
213  while ( current != stack.end() ) {
214  double test_ev(std::fabs(current.value().GoodnessOfFit()-pt));
215  if ( test_ev < best_ev) {
216  best = current;
217  best_ev = test_ev; // differs from ISIS2 which saved current eigenvalue
218  }
219  ++current;
220  }
221  return (best);
222  }
223 
237  bool SmtkMatcher::isValid(const SmtkPoint &spnt) {
238  bool valid(true);
239 
240  if (!spnt.isValid()) {
241  std::cout << "Point status is invalid!\n";
242  valid = false;
243  }
244 
245  // Is valid in left image?
246  if (!inCube(lhCamera(), spnt.getLeft())) {
247  std::cout << "Left point (" << spnt.getLeft().getLine() << ","
248  << spnt.getLeft().getSample() << ") is invalid!\n";
249  valid = false;
250  }
251 
252  // Is valud in right image?
253  if (!inCube(rhCamera(), spnt.getRight())) {
254  std::cout << "Right point (" << spnt.getRight().getLine() << ","
255  << spnt.getRight().getSample() << ") is invalid!\n";
256  valid = false;
257  }
258 
259  return (valid);
260  }
261 
268  const AffineRadio &affrad) {
269  return (Register(PointGeometry(lpnt), PointGeometry(), affrad));
270  }
271 
283  const AffineRadio &affrad) {
284  return (Register(PointGeometry(pnts.getLeft()),
285  PointGeometry(pnts.getRight()), affrad));
286  }
287 
288 
289 
312  const AffineRadio &affrad) {
313 
314  // If point is already registered don't do it again.
315  if (spnt.isRegistered()) { return (spnt); }
316 
317  PointGeometry left = PointGeometry(spnt.getLeft());
318  PointGeometry right = PointGeometry(spnt.getRight());
319 
320  return (Register(left, right, affrad));
321  }
322 
323 
351  const PointGeometry &rpg,
352  const AffineRadio &affrad) {
353 
354  // Validate object state
355  validate();
356 
357  // Test if the left point is defined. This will throw an error if this
358  // situation occurs
359  if (!lpg.getPoint().isValid()) {
360  QString mess = "Left point is not defined which is required";
362  }
363 
364  // First we need a lat,lon from the left image to find the same place in
365  // the right image.
366  Coordinate lpnt = lpg.getPoint();
367  Coordinate lgeom = lpg.getGeometry();
368  if (!lgeom.isValid()) {
369  lgeom = getLatLon(lhCamera(), lpnt);
370  }
371 
372  // Construct geometry and check validity
373  PointGeometry left = PointGeometry(lpnt, lgeom);
374  if (!left.isValid()) {
375  m_offImage++;
376  return ( SmtkPoint(PointPair(lpnt), PointPair(lgeom)) );
377  }
378 
379  // Validate the right point
380  Coordinate rpnt = rpg.getPoint();
381  Coordinate rgeom = rpg.getGeometry();
382  if ( !rpnt.isValid() ) {
383  if (rgeom.isValid()) {
384  rpnt = getLineSample(rhCamera(), rgeom);
385  }
386  else {
387  rpnt = getLineSample(rhCamera(), lgeom);
388  rgeom = lgeom;
389  }
390  }
391  else if (!rgeom.isValid() ){
392  rgeom = getLatLon(rhCamera(), rpnt);
393  }
394 
395  // Construct and for good right geometry
396  PointGeometry right = PointGeometry(rpnt, rgeom);
397  if (!right.isValid()) {
398  m_spiceErr++;
399  return (SmtkPoint(PointPair(lpnt, rpnt), PointPair(lgeom, rgeom)));
400  }
401 
402  try {
403  // These calls are computationally expensive... can we fix it?
404  m_gruen->PatternChip()->TackCube(lpnt.getSample(), lpnt.getLine());
405  m_gruen->PatternChip()->Load(*m_lhCube);
406  m_gruen->SearchChip()->TackCube(rpnt.getSample(), rpnt.getLine());
407  m_gruen->SearchChip()->Load(*m_rhCube, *m_gruen->PatternChip(),
408  *m_lhCube);
409  }
410  catch (IException &) {
411  m_offImage++; // Failure to load is assumed an offimage error
412  return (SmtkPoint(PointPair(lpnt,rpnt), PointPair(lgeom,rgeom)));
413  }
414 
415  // Register the points with incoming affine/radiometric parameters
416  m_gruen->setAffineRadio(affrad);
417  return (makeRegisteredPoint(left, right, m_gruen.data()));
418  }
419 
445  const Coordinate &right) {
446 
447  // Check out left image point
448  Coordinate lgeom = getLatLon(lhCamera(), left);
449  if (!lgeom.isValid() ) {
450  m_offImage ++;
451  return (SmtkPoint(PointPair(left,right), PointPair(lgeom)));
452  }
453 
454  // Check out right image point
455  Coordinate rgeom = getLatLon(rhCamera(), right);
456  if (!rgeom.isValid() ) {
457  m_offImage ++;
458  return (SmtkPoint(PointPair(left,right), PointPair(lgeom,rgeom)));
459  }
460 
461  // Make the point
462  SmtkPoint spnt = SmtkPoint(PointPair(left,right), PointPair(lgeom,rgeom));
463  spnt.m_matchpt.m_analysis.setZeroState();
464  spnt.m_isValid = true;
465  return (spnt);
466  }
467 
468 
485  const Coordinate &left) {
486 
487  // Computes local chip location (chipLoc) with Affine. This gives offset
488  // in right pixel space. Simply add result to right point to get the
489  // new cloned right point.
490  Coordinate offset = left - point.getLeft();
491  Coordinate right = point.getRight() + point.getAffine().getPoint(offset);
492  PointPair cpoint = PointPair(left, right);
493 
494  MatchPoint mpt = point.m_matchpt;
495  mpt.m_point = cpoint;
496 
497  // Currently will not have any valid geometry
498  SmtkPoint spnt = SmtkPoint(mpt, PointGeometry(right), PointPair());
499  spnt.m_registered = false;
500  spnt.m_isValid = inCube(lhCamera(), left) && inCube(rhCamera(), right);
501  return (spnt);
502  }
503 
515  gsl_rng_env_setup();
516  T = gsl_rng_default;
517  r = gsl_rng_alloc (T);
518  return;
519  }
534  bool SmtkMatcher::validate(const bool &throwError) const {
535  bool isGood(true);
536  if (!m_lhCube) isGood = false;
537  if (!m_rhCube) isGood = false;
538  if (!m_gruen.data()) isGood = false;
539  if ((!isGood) && throwError) {
540  QString mess = "Images/match algorithm not initialized!";
542  }
543  return (isGood);
544  }
545 
557  bool SmtkMatcher::inCube(const Camera &camera, const Coordinate &pnt) const {
558  if (!pnt.isValid()) return (false);
559  if ( (pnt.getSample() < 0.5) || (pnt.getLine() < 0.5) ) return false;
560  if ( (pnt.getSample() > (camera.Samples() + 0.5)) ||
561  (pnt.getLine() > (camera.Lines() + 0.5)) ) {
562  return false;
563  }
564 
565  return true;
566  }
567 
568 
580  // Check if pixel coordinate is in the left image
581  Coordinate geom;
582  if (pnt.isValid()) {
583  if (inCube(camera, pnt)) {
584  if ( camera.SetImage(pnt.getSample(), pnt.getLine()) ) {
585  double latitude = camera.UniversalLatitude();
586  double longitude = camera.UniversalLongitude();
587  geom.setLatLon(latitude, longitude);
588  }
589  }
590  }
591  return (geom);
592  }
593 
605  const Coordinate &geom) {
606  // Check if pixel coordinate is in the left image
607  Coordinate pnt;
608  if (geom.isValid()) {
609  if ( camera.SetUniversalGround(geom.getLatitude(), geom.getLongitude()) ) {
610  if ( camera.InCube() ) {
611  pnt.setLineSamp(camera.Line(), camera.Sample());
612  }
613  }
614  }
615  return (pnt);
616  }
617 
638  const PointGeometry &right,
639  Gruen *gruen) {
640 
641  if (gruen->Register() != AutoReg::SuccessSubPixel) {
642  return (SmtkPoint(PointPair(left.getPoint(),right.getPoint()),
643  PointPair(left.getGeometry(), right.getGeometry())));
644  }
645 
646  // Registration point data
647  MatchPoint match = gruen->getLastMatch();
648 
649  // Compute new right coordinate data
650  Coordinate rcorr = Coordinate(gruen->CubeLine(), gruen->CubeSample());
651  Coordinate rgeom = getLatLon(rhCamera(), rcorr);
652  PointGeometry rpoint = PointGeometry(rcorr, rgeom);
653 
654  // Get left and original right geometry
655  PointPair pgeom = PointPair(left.getGeometry(), right.getGeometry());
656 
657  // Create SMTK point and determine status/validity
658  SmtkPoint spnt = SmtkPoint(match, rpoint, pgeom);
659 
660  // Check for valid mapping
661  if ( !rpoint.isValid() ) {
662  m_offImage++;
663  spnt.m_isValid = false;
664  }
665  else {
666  // Check for distance error
667  double dist = (rcorr - right.getPoint()).getDistance();
668  if (dist > gruen->getSpiceConstraint()) {
669  m_spiceErr++;
670  spnt.m_isValid = false;
671  }
672  else {
673  spnt.m_isValid = match.isValid();
674  }
675  }
676 
677  return (spnt);
678  }
679 
680 }
Success registering to sub-pixel accuracy.
Definition: AutoReg.h:197
bool isValid() const
Indicates the smtk portion of the point is valid.
Definition: SmtkPoint.h:87
void setZeroState()
Resets eigenvalues to 0.
Definition: GruenTypes.h:419
SmtkPoint Clone(const SmtkPoint &point, const Coordinate &left)
Clone a point set from a nearby (left image) point and Gruen affine.
Coordinate getPoint(const Coordinate &location) const
Applies the affine transfrom to a point and returns result.
Definition: GruenTypes.h:288
SmtkQStackIter FindExpDistEV(SmtkQStack &stack, const double &seedsample, const double &minEV, const double &maxEV)
Find the best eigen value using exponential distribution formula.
Define a generic Y/X container.
Definition: GruenTypes.h:69
double UniversalLatitude() const
Returns the planetocentric latitude, in degrees, at the surface intersection point in the body fixed ...
Definition: Sensor.cpp:225
bool validate(const bool &throwError=true) const
Validates the state of the Camera and Gruen algoritm.
void setImages(Cube *lhImage, Cube *rhImage)
Assign cubes for matching.
Definition: SmtkMatcher.cpp:77
SmtkPoint Create(const Coordinate &left, const Coordinate &right)
Create a valid, unregistered SmtkPoint.
Define a point set of left, right and geometry at that location.
Definition: GruenTypes.h:187
SmtkMatcher()
Construct default matcher.
Definition: SmtkMatcher.cpp:42
const Coordinate & getRight() const
Returns the registered right coordinate.
Definition: SmtkPoint.h:129
bool InCube()
This returns true if the current Sample() or Line() value is outside of the cube (meaning the point m...
Definition: Camera.cpp:2631
static GSLUtility * getInstance()
Return a reference to the GSL (singleton) object.
Definition: GSLUtility.cpp:66
AutoReg::RegisterStatus Register()
Walk the pattern chip through the search chip to find the best registration.
Definition: AutoReg.cpp:600
Coordinate getLineSample(Camera &camera, const Coordinate &geom)
Compute line,sample from latitude, longitude.
Container for a point and its geometry.
Definition: SmtkPoint.h:41
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:162
void setLatLon(const double &latitude, const double &longitude)
Use Latitude/Longitude interface.
Definition: GruenTypes.h:78
bool isRegistered() const
Returns registration status.
Definition: SmtkPoint.h:150
const AffineRadio & getAffine() const
Returns the affine transform and radiometic results.
Definition: SmtkPoint.h:134
SmtkPoint makeRegisteredPoint(const PointGeometry &left, const PointGeometry &right, Gruen *gruen)
Create an SmtkPoint from Gruen match result.
void setGruenDef(const QString &regdef)
Initialize Gruen algorithm with definitions in Pvl file provided.
Definition: SmtkMatcher.cpp:95
double CubeSample() const
Return the search chip cube sample that best matched.
Definition: AutoReg.h:356
double getSpiceConstraint() const
Returns the SPICE tolerance constraint as read from config file.
Definition: Gruen.h:108
bool SetUniversalGround(const double latitude, const double longitude)
Sets the lat/lon values to get the sample/line values.
Definition: Camera.cpp:396
bool SetImage(const double sample, const double line)
Sets the sample/line values of the image to get the lat/lon values.
Definition: Camera.cpp:170
bool inCube(const Camera &camera, const Coordinate &point) const
Determines if the line/sample is within physical cube boundaries.
MatchPoint getLastMatch() const
Returns the register state of the last successful Gruen match.
Definition: Gruen.h:136
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
const Coordinate & getLeft() const
Returns the left point.
Definition: SmtkPoint.h:115
double Sample()
Returns the current sample number.
Definition: Camera.cpp:2702
Coordinate getLatLon(Camera &camera, const Coordinate &pnt)
Compute latitude, longitude from line,sample.
void setLineSamp(const double &line, const double &sample)
Use the Line/Sample interface.
Definition: GruenTypes.h:85
double CubeLine() const
Return the search chip cube line that best matched.
Definition: AutoReg.h:361
bool isValid() const
Check for goodness.
Definition: GruenTypes.h:123
Container for cube-like labels.
Definition: Pvl.h:135
double UniversalLongitude() const
Returns the positive east, 0-360 domain longitude, in degrees, at the surface intersection point in t...
Definition: Sensor.cpp:248
Container for affine and radiometric parameters.
Definition: GruenTypes.h:258
SmtkPoint Register(const Coordinate &lpnt, const AffineRadio &affrad=AffineRadio())
This method takes a sample, line from the left-hand image and tries to find the matching point in the...
Structure containing comprehensive registration info/results.
Definition: GruenTypes.h:449
Gruen pattern matching algorithm.
Definition: Gruen.h:90
SmtkQStackIter FindSmallestEV(SmtkQStack &stack)
Find the smallest eigen value on the given stack.
void setWriteSubsearchChipPattern(const QString &fileptrn="SmtkMatcher")
Set file pattern for output subsearch chips.
double Line()
Returns the current line number.
Definition: Camera.cpp:2722
int Lines() const
Returns the number of lines in the image.
Definition: Camera.cpp:2798
int Samples() const
Returns the number of samples in the image.
Definition: Camera.cpp:2788
Isis exception class.
Definition: IException.h:107
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
~SmtkMatcher()
Free random number generator in destructor.
Definition: SmtkMatcher.cpp:71
void randomNumberSetup()
Initialize the random number generator.
Container for SMTK match points
Definition: SmtkPoint.h:71
bool isValid(const Coordinate &pnt)
Determine if a point is valid in both left/right images.
IO Handler for Isis Cubes.
Definition: Cube.h:170