Isis 3.0 Programmer Reference
Back | Home
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 "Camera.h"
32 #include "Projection.h"
33 #include "SpecialPixel.h"
34 #include "SmtkMatcher.h"
35 
36 
37 namespace Isis {
38 
40  SmtkMatcher::SmtkMatcher() : m_lhCube(0), m_rhCube(0), m_gruen(),
41  m_offImage(0), m_spiceErr(0),
42  m_useAutoReg(true) {
44  }
45 
47  SmtkMatcher::SmtkMatcher(const QString &regdef) : m_lhCube(0),
48  m_rhCube(0),
49  m_gruen(0),
50  m_offImage(0),
51  m_spiceErr(0),
52  m_useAutoReg(true) {
53  setGruenDef(regdef);
55  }
56 
58  SmtkMatcher::SmtkMatcher(const QString &regdef, Cube *lhCube,
59  Cube *rhCube) : m_lhCube(lhCube),
60  m_rhCube(rhCube),
61  m_gruen(0), m_offImage(0),
62  m_spiceErr(0),
63  m_useAutoReg(true) {
64  setGruenDef(regdef);
66  }
67 
70  gsl_rng_free(r);
71  }
72 
73 
75  void SmtkMatcher::setImages(Cube *lhCube, Cube *rhCube) {
76  m_lhCube = lhCube;
77  m_rhCube = rhCube;
78  return;
79  }
80 
93  void SmtkMatcher::setGruenDef(const QString &regdef) {
94  Pvl reg(regdef);
95  m_gruen = std::auto_ptr<Gruen> (new Gruen(reg)); // Deallocation automatic
96  return;
97  }
98 
116  bool SmtkMatcher::isValid(const Coordinate &pnt) {
117  validate(); // cubs and cameras
118  Coordinate pnt2 = getLatLon(lhCamera(), pnt);
119  if (pnt2.isValid()) {
120  pnt2 = getLineSample(rhCamera(), pnt2);
121  }
122  return (pnt2.isValid());
123  }
124 
147  void SmtkMatcher::setWriteSubsearchChipPattern(const QString &fileptrn) {
148  validate();
149  m_gruen->WriteSubsearchChips(fileptrn);
150  }
151 
164  SmtkQStackIter SmtkMatcher::FindSmallestEV(SmtkQStack &stack) {
165  SmtkQStackIter best(stack.begin()), current(stack.begin());
166  while ( current != stack.end() ) {
167  if (current.value().GoodnessOfFit() < best.value().GoodnessOfFit() ) {
168  best = current;
169  }
170  ++current;
171  }
172  return (best);
173  }
174 
175 
197  SmtkQStackIter SmtkMatcher::FindExpDistEV(SmtkQStack &stack,
198  const double &seedsample,
199  const double &minEV,
200  const double &maxEV) {
201 
202  if (stack.isEmpty()) return (stack.end());
203  SmtkQStackIter best(stack.begin()), current(stack.begin());
204 
205  // Random number generator must scale between 0 and 1
206  double randNum = gsl_rng_uniform (r);
207  double t1 = -std::log(1.0 - randNum *
208  (1.0 - std::exp(-seedsample)))/seedsample;
209  double pt = minEV + t1*(maxEV-minEV);
210  double best_ev(DBL_MAX);
211  while ( current != stack.end() ) {
212  double test_ev(std::fabs(current.value().GoodnessOfFit()-pt));
213  if ( test_ev < best_ev) {
214  best = current;
215  best_ev = test_ev; // differs from ISIS2 which saved current eigenvalue
216  }
217  ++current;
218  }
219  return (best);
220  }
221 
235  bool SmtkMatcher::isValid(const SmtkPoint &spnt) {
236  bool valid(true);
237 
238  if (!spnt.isValid()) {
239  std::cout << "Point status is invalid!\n";
240  valid = false;
241  }
242 
243  // Is valid in left image?
244  if (!inCube(lhCamera(), spnt.getLeft())) {
245  std::cout << "Left point (" << spnt.getLeft().getLine() << ","
246  << spnt.getLeft().getSample() << ") is invalid!\n";
247  valid = false;
248  }
249 
250  // Is valud in right image?
251  if (!inCube(rhCamera(), spnt.getRight())) {
252  std::cout << "Right point (" << spnt.getRight().getLine() << ","
253  << spnt.getRight().getSample() << ") is invalid!\n";
254  valid = false;
255  }
256 
257  return (valid);
258  }
259 
266  const AffineRadio &affrad) {
267  return (Register(PointGeometry(lpnt), PointGeometry(), affrad));
268  }
269 
281  const AffineRadio &affrad) {
282  return (Register(PointGeometry(pnts.getLeft()),
283  PointGeometry(pnts.getRight()), affrad));
284  }
285 
286 
287 
310  const AffineRadio &affrad) {
311 
312  // If point is already registered don't do it again.
313  if (spnt.isRegistered()) { return (spnt); }
314 
315  PointGeometry left = PointGeometry(spnt.getLeft());
316  PointGeometry right = PointGeometry(spnt.getRight());
317 
318  return (Register(left, right, affrad));
319  }
320 
321 
349  const PointGeometry &rpg,
350  const AffineRadio &affrad) {
351 
352  // Validate object state
353  validate();
354 
355  // Test if the left point is defined. This will throw an error if this
356  // situation occurs
357  if (!lpg.getPoint().isValid()) {
358  QString mess = "Left point is not defined which is required";
360  }
361 
362  // First we need a lat,lon from the left image to find the same place in
363  // the right image.
364  Coordinate lpnt = lpg.getPoint();
365  Coordinate lgeom = lpg.getGeometry();
366  if (!lgeom.isValid()) {
367  lgeom = getLatLon(lhCamera(), lpnt);
368  }
369 
370  // Construct geometry and check validity
371  PointGeometry left = PointGeometry(lpnt, lgeom);
372  if (!left.isValid()) {
373  m_offImage++;
374  return ( SmtkPoint(PointPair(lpnt), PointPair(lgeom)) );
375  }
376 
377  // Validate the right point
378  Coordinate rpnt = rpg.getPoint();
379  Coordinate rgeom = rpg.getGeometry();
380  if ( !rpnt.isValid() ) {
381  if (rgeom.isValid()) {
382  rpnt = getLineSample(rhCamera(), rgeom);
383  }
384  else {
385  rpnt = getLineSample(rhCamera(), lgeom);
386  rgeom = lgeom;
387  }
388  }
389  else if (!rgeom.isValid() ){
390  rgeom = getLatLon(rhCamera(), rpnt);
391  }
392 
393  // Construct and for good right geometry
394  PointGeometry right = PointGeometry(rpnt, rgeom);
395  if (!right.isValid()) {
396  m_spiceErr++;
397  return (SmtkPoint(PointPair(lpnt, rpnt), PointPair(lgeom, rgeom)));
398  }
399 
400  try {
401  // These calls are computationally expensive... can we fix it?
402  m_gruen->PatternChip()->TackCube(lpnt.getSample(), lpnt.getLine());
403  m_gruen->PatternChip()->Load(*m_lhCube);
404  m_gruen->SearchChip()->TackCube(rpnt.getSample(), rpnt.getLine());
405  m_gruen->SearchChip()->Load(*m_rhCube, *m_gruen->PatternChip(),
406  *m_lhCube);
407  }
408  catch (IException &) {
409  m_offImage++; // Failure to load is assumed an offimage error
410  return (SmtkPoint(PointPair(lpnt,rpnt), PointPair(lgeom,rgeom)));
411  }
412 
413  // Register the points with incoming affine/radiometric parameters
414  m_gruen->setAffineRadio(affrad);
415  return (makeRegisteredPoint(left, right, m_gruen.get()));
416  }
417 
443  const Coordinate &right) {
444 
445  // Check out left image point
446  Coordinate lgeom = getLatLon(lhCamera(), left);
447  if (!lgeom.isValid() ) {
448  m_offImage ++;
449  return (SmtkPoint(PointPair(left,right), PointPair(lgeom)));
450  }
451 
452  // Check out right image point
453  Coordinate rgeom = getLatLon(rhCamera(), right);
454  if (!rgeom.isValid() ) {
455  m_offImage ++;
456  return (SmtkPoint(PointPair(left,right), PointPair(lgeom,rgeom)));
457  }
458 
459  // Make the point
460  SmtkPoint spnt = SmtkPoint(PointPair(left,right), PointPair(lgeom,rgeom));
461  spnt.m_matchpt.m_analysis.setZeroState();
462  spnt.m_isValid = true;
463  return (spnt);
464  }
465 
466 
483  const Coordinate &left) {
484 
485  // Computes local chip location (chipLoc) with Affine. This gives offset
486  // in right pixel space. Simply add result to right point to get the
487  // new cloned right point.
488  Coordinate offset = left - point.getLeft();
489  Coordinate right = point.getRight() + point.getAffine().getPoint(offset);
490  PointPair cpoint = PointPair(left, right);
491 
492  MatchPoint mpt = point.m_matchpt;
493  mpt.m_point = cpoint;
494 
495  // Currently will not have any valid geometry
496  SmtkPoint spnt = SmtkPoint(mpt, PointGeometry(right), PointPair());
497  spnt.m_registered = false;
498  spnt.m_isValid = inCube(lhCamera(), left) && inCube(rhCamera(), right);
499  return (spnt);
500  }
501 
513  gsl_rng_env_setup();
514  T = gsl_rng_default;
515  r = gsl_rng_alloc (T);
516  return;
517  }
532  bool SmtkMatcher::validate(const bool &throwError) const {
533  bool isGood(true);
534  if (!m_lhCube) isGood = false;
535  if (!m_rhCube) isGood = false;
536  if (!m_gruen.get()) isGood = false;
537  if ((!isGood) && throwError) {
538  QString mess = "Images/match algorithm not initialized!";
540  }
541  return (isGood);
542  }
543 
555  bool SmtkMatcher::inCube(const Camera &camera, const Coordinate &pnt) const {
556  if (!pnt.isValid()) return (false);
557  if ( (pnt.getSample() < 0.5) || (pnt.getLine() < 0.5) ) return false;
558  if ( (pnt.getSample() > (camera.Samples() + 0.5)) ||
559  (pnt.getLine() > (camera.Lines() + 0.5)) ) {
560  return false;
561  }
562 
563  return true;
564  }
565 
566 
578  // Check if pixel coordinate is in the left image
579  Coordinate geom;
580  if (pnt.isValid()) {
581  if (inCube(camera, pnt)) {
582  if ( camera.SetImage(pnt.getSample(), pnt.getLine()) ) {
583  double latitude = camera.UniversalLatitude();
584  double longitude = camera.UniversalLongitude();
585  geom.setLatLon(latitude, longitude);
586  }
587  }
588  }
589  return (geom);
590  }
591 
603  const Coordinate &geom) {
604  // Check if pixel coordinate is in the left image
605  Coordinate pnt;
606  if (geom.isValid()) {
607  if ( camera.SetUniversalGround(geom.getLatitude(), geom.getLongitude()) ) {
608  if ( camera.InCube() ) {
609  pnt.setLineSamp(camera.Line(), camera.Sample());
610  }
611  }
612  }
613  return (pnt);
614  }
615 
636  const PointGeometry &right,
637  Gruen *gruen) {
638 
639  if (gruen->Register() != AutoReg::SuccessSubPixel) {
640  return (SmtkPoint(PointPair(left.getPoint(),right.getPoint()),
641  PointPair(left.getGeometry(), right.getGeometry())));
642  }
643 
644  // Registration point data
645  MatchPoint match = gruen->getLastMatch();
646 
647  // Compute new right coordinate data
648  Coordinate rcorr = Coordinate(gruen->CubeLine(), gruen->CubeSample());
649  Coordinate rgeom = getLatLon(rhCamera(), rcorr);
650  PointGeometry rpoint = PointGeometry(rcorr, rgeom);
651 
652  // Get left and original right geometry
653  PointPair pgeom = PointPair(left.getGeometry(), right.getGeometry());
654 
655  // Create SMTK point and determine status/validity
656  SmtkPoint spnt = SmtkPoint(match, rpoint, pgeom);
657 
658  // Check for valid mapping
659  if ( !rpoint.isValid() ) {
660  m_offImage++;
661  spnt.m_isValid = false;
662  }
663  else {
664  // Check for distance error
665  double dist = (rcorr - right.getPoint()).getDistance();
666  if (dist > gruen->getSpiceConstraint()) {
667  m_spiceErr++;
668  spnt.m_isValid = false;
669  }
670  else {
671  spnt.m_isValid = match.isValid();
672  }
673  }
674 
675  return (spnt);
676  }
677 
678 }
Success registering to sub-pixel accuracy.
Definition: AutoReg.h:191
MatchPoint getLastMatch() const
Returns the register state of the last successful Gruen match.
Definition: Gruen.h:136
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.
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
void setImages(Cube *lhImage, Cube *rhImage)
Assign cubes for matching.
Definition: SmtkMatcher.cpp:75
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
bool isRegistered() const
Returns registration status.
Definition: SmtkPoint.h:150
SmtkMatcher()
Construct default matcher.
Definition: SmtkMatcher.cpp:40
bool InCube()
This returns true if the current Sample() or Line() value is outside of the cube (meaning the point m...
Definition: Camera.cpp:2681
static GSLUtility * getInstance()
Return a reference to the GSL (singleton) object.
Definition: GSLUtility.cpp:66
double UniversalLatitude() const
Returns the planetocentric latitude, in degrees, at the surface intersection point in the body fixed ...
Definition: Sensor.cpp:225
const Coordinate & getLeft() const
Returns the left point.
Definition: SmtkPoint.h:115
const Coordinate & getRight() const
Returns the registered right coordinate.
Definition: SmtkPoint.h:129
const AffineRadio & getAffine() const
Returns the affine transform and radiometic results.
Definition: SmtkPoint.h:134
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:154
void setLatLon(const double &latitude, const double &longitude)
Use Latitude/Longitude interface.
Definition: GruenTypes.h:78
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:93
Coordinate getPoint(const Coordinate &location) const
Applies the affine transfrom to a point and returns result.
Definition: GruenTypes.h:288
bool SetUniversalGround(const double latitude, const double longitude)
Sets the lat/lon values to get the sample/line values.
Definition: Camera.cpp:392
double UniversalLongitude() const
Returns the positive east, 0-360 domain longitude, in degrees, at the surface intersection point in t...
Definition: Sensor.cpp:248
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:166
double CubeSample() const
Return the search chip cube sample that best matched.
Definition: AutoReg.h:350
int Samples() const
Returns the number of samples in the image.
Definition: Camera.cpp:2836
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:38
double Sample()
Returns the current sample number.
Definition: Camera.cpp:2752
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
Container for cube-like labels.
Definition: Pvl.h:135
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...
bool inCube(const Camera &camera, const Coordinate &point) const
Determines if the line/sample is within physical cube boundaries.
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.
double getSpiceConstraint() const
Returns the SPICE tolerance constraint as read from config file.
Definition: Gruen.h:108
void setWriteSubsearchChipPattern(const QString &fileptrn="SmtkMatcher")
Set file pattern for output subsearch chips.
double Line()
Returns the current line number.
Definition: Camera.cpp:2772
Isis exception class.
Definition: IException.h:99
double CubeLine() const
Return the search chip cube line that best matched.
Definition: AutoReg.h:355
bool isValid() const
Indicates the smtk portion of the point is valid.
Definition: SmtkPoint.h:87
int Lines() const
Returns the number of lines in the image.
Definition: Camera.cpp:2846
~SmtkMatcher()
Free random number generator in destructor.
Definition: SmtkMatcher.cpp:69
bool validate(const bool &throwError=true) const
Validates the state of the Camera and Gruen algoritm.
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.
bool isValid() const
Check for goodness.
Definition: GruenTypes.h:123
IO Handler for Isis Cubes.
Definition: Cube.h:158

U.S. Department of the Interior | U.S. Geological Survey
ISIS | Privacy & Disclaimers | Astrogeology Research Program
To contact us, please post comments and questions on the ISIS Support Center
File Modified: 07/12/2023 23:29:17