OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimTieMeasurementGenerator.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------
2 //
3 // License: See top level LICENSE.txt file.
4 //
5 // Author: David Hicks
6 //
7 // Description: Automatic tie measurement extraction.
8 //
9 //----------------------------------------------------------------------------
10 // $Id$
11 
13 #include <ossim/base/ossimString.h>
14 #include <ossim/base/ossimNotify.h>
15 #include <ossim/base/ossimTrace.h>
16 #include <ossim/base/ossimIrect.h>
17 #include <ossim/base/ossimRefPtr.h>
22 
24 
25 #include <opencv/highgui.h>
26 #include <opencv2/core/core.hpp>
27 #include <opencv2/highgui/highgui.hpp>
28 #include <opencv2/flann/flann.hpp>
29 #include <opencv2/features2d.hpp>
30 #include <opencv2/imgproc.hpp>
31 // Note: These are purposely commented out to indicate non-use.
32 // #include <opencv2/nonfree/nonfree.hpp>
33 // #include <opencv2/nonfree/features2d.hpp>
34 // Note: These are purposely commented out to indicate non-use.
35 
36 #include <vector>
37 #include <iostream>
38 
39 static ossimTrace traceExec ("ossimTieMeasurementGenerator:exec");
40 static ossimTrace traceDebug ("ossimTieMeasurementGenerator:debug");
41 
42 
43 //*****************************************************************************
44 // METHOD: ossimTieMeasurementGenerator::ossimTieMeasurementGenerator()
45 //
46 // Constructor.
47 //*****************************************************************************
49  :
50  m_initOK(false),
51  m_src(0),
52  m_igxA(0),
53  m_igxB(0),
54  m_imgA(),
55  m_imgB(),
56  m_numMeasurements(0),
57  m_maxMatches(5),
58  m_spIndexA(0),
59  m_spIndexB(1),
60  m_patchSizeA(),
61  m_patchSizeB(),
62  m_validBox(false),
63  m_useGrid(false),
64  m_showCvWindow(false),
65  m_patchRefA(),
66  m_patchRefB(),
67  m_measA(),
68  m_measB(),
69  m_distEditFactor(0),
70  m_detectorName("ORB"),
71  m_detector(),
72  m_extractorName("ORB"),
73  m_extractor(),
74  m_matcherName("BruteForce-Hamming"),
75  m_matcher(),
76  m_rep(0),
77  m_maxCvWindowDim(500),
78  m_cvWindowName("Correlation Patch")
79 {
80  if (traceExec())
81  {
83  << "\nDEBUG: ...ossimTieMeasurementGenerator::constructor" << std::endl;
84  }
85 }
86 
87 
88 //*****************************************************************************
89 // METHOD: ossimTieMeasurementGenerator::ossimTieMeasurementGenerator()
90 //
91 // Initializer.
92 //*****************************************************************************
94 {
95  if (traceExec())
96  {
98  << "DEBUG: ...ossimTieMeasurementGenerator::init" << std::endl;
99  }
100 
101  m_initOK = true;
102  ossimString ts;
103  ossim::getFormattedTime("%a %m.%d.%y %H:%M:%S", false, ts);
104 
105  m_rep = &report;
106 
107 
108  // Initial report output
109  *m_rep << "\nossimTieMeasurementGenerator Report ";
110  *m_rep << ts;
111  *m_rep << "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
112  *m_rep << std::endl;
113 
114  // Set default grid size
115  setGridSize(ossimIpt(1,1));
116 
117  try{
118  // Set default detector, extractor, matcher
122 
123  }
124  catch(...)
125  {
126  m_initOK = false;
127  }
128 
129  return m_initOK;
130 }
131 
132 
133 //*****************************************************************************
134 // DESTRUCTOR: ~ossimTieMeasurementGenerator()
135 //
136 //*****************************************************************************
138 {
139  if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG)
140  << "DEBUG: ~ossimTieMeasurementGenerator(): returning..." << std::endl;
141 }
142 
143 
144 //*****************************************************************************
145 // METHOD: ossimTieMeasurementGenerator::refreshCollectionTraits()
146 //
147 // Collection trait initializer.
148 //*****************************************************************************
150 {
151  bool initOK = true;
152 
153  if (m_useGrid)
154  {
155  int gridRows = m_gridSize.y;
156  int gridCols = m_gridSize.x;
157  //cv::ORB::create("");
158  }
159 
160  return initOK;
161 }
162 
163 
164 //*****************************************************************************
165 // METHOD: ossimTieMeasurementGenerator::run()
166 //
167 //
168 //*****************************************************************************
170 {
171  bool runOK = true;
172 
173  // Refresh collection traits before run
174  runOK = refreshCollectionTraits();
175  if(!m_detector) runOK = false;
176  if(!m_extractor) runOK = false;
177  if (runOK)
178  {
179  // ossimIrect constructor center-based constructor
180  // -> center view coordinates: m_patchRefA,m_patchRefB
183 
184  if (traceDebug())
185  {
187  << "DEBUG: ...ossimTieMeasurementGenerator::run" << std::endl;
188  ossimNotify(ossimNotifyLevel_DEBUG)<<" m_patchRefA: "<<m_patchRefA<<" size: "<<m_patchSizeA<<std::endl;
189  ossimNotify(ossimNotifyLevel_DEBUG)<<" m_patchRefB: "<<m_patchRefB<<" size: "<<m_patchSizeB<<std::endl;
190  ossimNotify(ossimNotifyLevel_DEBUG)<<" rectA = "<<rectA<<endl;
191  ossimNotify(ossimNotifyLevel_DEBUG)<<" rectB = "<<rectB<<endl;
192  ossimNotify(ossimNotifyLevel_DEBUG)<<" m_src A ossimScalarType = "<<m_src[m_spIndexA]->getOutputScalarType()<<endl;
193  ossimNotify(ossimNotifyLevel_DEBUG)<<" m_src B ossimScalarType = "<<m_src[m_spIndexB]->getOutputScalarType()<<endl;
194  }
195 
196  // Get the patches
197  ossimRefPtr<ossimImageData> idA = m_src[m_spIndexA]->getTile(rectA);
198  ossimRefPtr<ossimImageData> idB = m_src[m_spIndexB]->getTile(rectB);
199 
200  // Create the OpenCV images
201  m_imgA.create(cv::Size(rectA.width(), rectA.height()), CV_8UC1);
202  m_imgB.create(cv::Size(rectB.width(), rectB.height()), CV_8UC1);
203 
204  memcpy(m_imgA.ptr(), (void*) idA->getBuf(), rectA.area());
205  memcpy(m_imgB.ptr(), (void*) idB->getBuf(), rectB.area());
206 
207  if(m_imgA.empty())
208  {
209  *m_rep << "cv::Mat A creation failed..."<<std::endl;;
210  runOK = false;
211  }
212  else if(m_imgB.empty())
213  {
214  *m_rep << "cv::Mat B creation failed..."<<std::endl;;
215  runOK = false;
216  }
217  else
218  {
219  // Detector
220  vector<cv::KeyPoint> keypointsA;
221  vector<cv::KeyPoint> keypointsB;
222  m_detector->detect(m_imgA, keypointsA);
223  m_detector->detect(m_imgB, keypointsB);
224 
225  // Extractor
226  // 32 byte uchar arrays CV_8U (0) ..........
227  // cout << desc.rows << " " << desc.cols << " " << desc.type() << std::endl;
228  // uchar d = desc.at<uchar>(row,col);
229  cv::Mat descriptorsA;
230  cv::Mat descriptorsB;
231  m_extractor->compute(m_imgA, keypointsA, descriptorsA);
232  m_extractor->compute(m_imgB, keypointsB, descriptorsB);
233 
234  // Execute matcher
235  // TODO add cross-check process here?
236  //----------
237  // BruteForceMatcher<L2<float> > descriptorMatcher;
238  // vector<DMatch> filteredMatches12, matches12, matches21;
239  // descriptorMatcher.match( descriptors1, descriptors2, matches12 );
240  // descriptorMatcher.match( descriptors2, descriptors1, matches21 );
241  // for( size_t i = 0; i < matches12.size(); i++ )
242  // {
243  // DMatch forward = matches12[i];
244  // DMatch backward = matches21[forward.trainIdx];
245  // if( backward.trainIdx == forward.queryIdx )
246  // filteredMatches12.push_back( forward );
247  // }
248  //----------
249  std::vector<cv::DMatch> matches;
250  std::vector<cv::DMatch> matchesAB;
251  m_matcher->match(descriptorsA, descriptorsB, matchesAB);
252 
253  matches = matchesAB;
254 
255  // Symmetry
256  // void symmetryTest(const std::vector<cv::DMatch> &matches1,const std::vector<cv::DMatch> &matches2,std::vector<cv::DMatch>& symMatches)
257  // {
258  // symMatches.clear();
259  // for (vector<DMatch>::const_iterator matchIterator1= matches1.begin();matchIterator1!= matches1.end(); ++matchIterator1)
260  // {
261  // for (vector<DMatch>::const_iterator matchIterator2= matches2.begin();matchIterator2!= matches2.end();++matchIterator2)
262  // {
263  // if ((*matchIterator1).queryIdx ==(*matchIterator2).trainIdx &&(*matchIterator2).queryIdx ==(*matchIterator1).trainIdx)
264  // {
265  // symMatches.push_back(DMatch((*matchIterator1).queryIdx,(*matchIterator1).trainIdx,(*matchIterator1).distance));
266  // break;
267  // }
268  // }
269  // }
270  // }
271 
272  *m_rep<<" Match resulted in "<<descriptorsA.rows<<" points..."<<std::endl;
273 
274  //-- Calculate max and min distances between keypoints
275  double maxDist = 0;
276  double minDist = 500;
277  int maxRows = matches.size();
278  if(maxRows > descriptorsA.rows) maxRows = descriptorsA.rows;
279  for( int i = 0; i < maxRows; i++ )
280  {
281  double dist = matches[i].distance;
282  if( dist < minDist ) minDist = dist;
283  if( dist > maxDist ) maxDist = dist;
284  }
285 
286  //-- Check for "good" matches (i.e. whose distance is less than 2*minDist )
287  //-- TODO -> radiusMatch can also be used here?
288  m_distEditFactor = 3; //TODO
289  std::vector<cv::DMatch> goodMatches;
290  for( int i = 0; i < maxRows; i++ )
291  {
292  if( matches[i].distance < m_distEditFactor*minDist )
293  {
294  goodMatches.push_back( matches[i]);
295  }
296  }
297  *m_rep<<" Distance filter ("<<std::setw(1)<<m_distEditFactor<<"X min) resulted in "<<goodMatches.size()<<" points..."<<std::endl;
298  *m_rep<<" -- Max dist : "<<maxDist<<std::endl;
299  *m_rep<<" -- Min dist : "<<minDist<<std::endl;
300 
301  if (m_maxMatches<(int)goodMatches.size())
302  {
303  nth_element(goodMatches.begin(),goodMatches.begin()+m_maxMatches,goodMatches.end());
304  goodMatches.erase(goodMatches.begin()+m_maxMatches,goodMatches.end());
305  }
306 
307  // Load measurements
308  *m_rep<<"\n Selected top "<<goodMatches.size()<<"..."<<std::endl;
309  *m_rep<<" n queryIdx trainIdx imgIdx distance A B"<<std::endl;
310  *m_rep<<"---- -------- -------- ------ -------- ------------ ------------"<<std::endl;
311 
312  for( ossim_uint32 i = 0; i < goodMatches.size(); ++i )
313  {
314  double xA = keypointsA[goodMatches[i].queryIdx].pt.x;
315  double yA = keypointsA[goodMatches[i].queryIdx].pt.y;
316  double xB = keypointsB[goodMatches[i].trainIdx].pt.x;
317  double yB = keypointsB[goodMatches[i].trainIdx].pt.y;
318 
319  *m_rep<<std::setw(4)<<i+1<<" "
320  <<std::setw(8)<<goodMatches[i].queryIdx<<" "
321  <<std::setw(8)<<goodMatches[i].trainIdx<<" "
322  <<std::setw(6)<<goodMatches[i].imgIdx<<" "
323  <<std::fixed<<std::setprecision(1)<<std::setw(8)
324  <<goodMatches[i].distance<<" ("
325  <<std::fixed<<std::setprecision(0)
326  <<std::setw(4)<<xA << ", "
327  <<std::setw(4)<<yA <<") ("
328  <<std::setw(4)<<xB << ", "
329  <<std::setw(4)<<yB <<") "
330  <<std::endl;
331 
332  // View coordinates
333  ossimDpt vptA(xA, yA);
334  ossimDpt vptB(xB, yB);
335  vptA += m_patchRefA - m_patchSizeA/2;
336  vptB += m_patchRefB - m_patchSizeB/2;
337 
338  // Image coordinates
339  ossimDpt iptA;
340  ossimDpt iptB;
341  m_igxA->viewToImage(vptA, iptA);
342  m_igxB->viewToImage(vptB, iptB);
343 
344  m_measA.push_back(iptA);
345  m_measB.push_back(iptB);
347  }
348 
349 
350  // Pop up the results window
351  if (m_showCvWindow)
352  {
353  showCvResultsWindow(keypointsA, keypointsB, goodMatches);
354  }
355  }
356 
357  }
358  else
359  {
360  *m_rep << "An error occurred in collection trait initialization..."<<std::endl;
361  *m_rep << "Measurement collection could not be executed."<<std::endl;
362  }
363 
364  summarizeRun();
365 
366  return runOK;
367 }
368 
369 
371 {
372  cv::Ptr<cv::Feature2D> feature2d;
373  if (name == "FAST")
374  feature2d = cv::FastFeatureDetector::create();
375  else if (name == "ORB")
376  feature2d = cv::ORB::create();
377  else if (name == "BRISK")
378  feature2d = cv::BRISK::create();
379  else if (name == "MSER")
380  feature2d = cv::MSER::create();
381  else if (name == "GFTT")
382  feature2d = cv::GFTTDetector::create();
383  else if (name == "HARRIS")
384  {
385  cv::Ptr<cv::GFTTDetector> d = cv::GFTTDetector::create();
386  d->setHarrisDetector(true);
387  feature2d = d;
388  }
389  else if (name == "SimpleBlob")
390  feature2d = cv::SimpleBlobDetector::create();
391  else if (name == "AKAZE")
392  feature2d = cv::AKAZE::create();
393  else if (name == "KAZE")
394  feature2d = cv::KAZE::create();
395  else if (name == "AGAST")
396  feature2d = cv::AgastFeatureDetector::create();
397 
398  return feature2d;
399 }
400 
401 //*****************************************************************************
402 // METHOD: ossimTieMeasurementGenerator::setFeatureDetector()
403 // Set the feature detector
404 //
405 // The following detector types are supported:
406 // "FAST" – FastFeatureDetector
407 // "SIFT" – SIFT (nonfree module)
408 // "SURF" – SURF (nonfree module)
409 // "ORB" – ORB
410 // "BRISK" – BRISK
411 // "MSER" – MSER
412 // "GFTT" – GoodFeaturesToTrackDetector
413 // "HARRIS" – GoodFeaturesToTrackDetector with Harris detector enabled
414 // "Dense" – DenseFeatureDetector
415 // "SimpleBlob" – SimpleBlobDetector
416 // Also a combined format is supported: feature detector adapter name
417 // ( "Grid" – GridAdaptedFeatureDetector, "Pyramid" – PyramidAdaptedFeatureDetector )
418 //+ feature detector name (see above), for example: "GridFAST", "PyramidSTAR".
419 //*****************************************************************************
421 {
422  bool createOK = false;
423  m_detectorName = name;
424  m_detector = createFeature2D(name);
425 
426  if( m_detector != 0 )
427  {
428  createOK = true;
429 // std::vector<std::string> parameters;
430 // m_detector->getParams(parameters);
431 // if (traceDebug())
432 // {
433 // ossimNotify(ossimNotifyLevel_DEBUG)
434 // << "DEBUG: ...detector..." << std::endl;
435 // for (int i = 0; i < (int) parameters.size(); i++)
436 // ossimNotify(ossimNotifyLevel_DEBUG)<<" "<<parameters[i]<<std::endl;
437 // }
438  }
439 
440  return createOK;
441 }
442 
443 //*****************************************************************************
444 // METHOD: ossimTieMeasurementGenerator::setDescriptorExtractor()
445 // Set the descriptor-extractor
446 //
447 // The current implementation supports the following types of a descriptor extractor:
448 // Not Used "SIFT" – SIFT (nonfree module)
449 // Not Used "SURF" – SURF (nonfree module)
450 // "ORB" – ORB
451 // "BRISK" – BRISK
452 // "BRIEF" – BriefDescriptorExtractor
453 // A combined format is also supported: descriptor extractor adapter name
454 //( "Opponent" – OpponentColorDescriptorExtractor ) + descriptor extractor name
455 //(see above), for example: "OpponentSIFT" .
456 //
457 // cv::Algorithm::set, cv::Algorithm::getParams
458 //featureDetector->set("someParam", someValue)
459 //*****************************************************************************
461 {
462  bool createOK = false;
463  m_extractorName = name;
465 
466  if( m_extractor != 0 )
467  {
468  createOK = true;
469 // std::vector<std::string> parameters;
470 // m_extractor->getParams(parameters);
471 // if (traceDebug())
472 // {
473 // ossimNotify(ossimNotifyLevel_DEBUG)
474 // << "DEBUG: ...extractor..." << std::endl;
475 // for (int i = 0; i < (int) parameters.size(); i++)
476 // ossimNotify(ossimNotifyLevel_DEBUG)<<" "<<parameters[i]<<std::endl;
477 // }
478  }
479 
480  return createOK;
481 }
482 
483 //*****************************************************************************
484 // METHOD: ossimTieMeasurementGenerator::getDescriptorMatcher()
485 // Set the descriptor-matcher
486 //
487 // Descriptor matcher type. Now the following matcher types are supported:
488 // BruteForce-Hamming
489 // BruteForce-HammingLUT
490 // FlannBased
491 //
492 // The current decriptor-matcher compatibility table (updated for this note) is the following:
493 // BruteForce BruteForce-L1 FlannBased BruteForce-Hamming BruteForce-HammingLUT
494 // Not Used SURF YES YES YES NO NO
495 // Not Used SIFT YES YES YES NO NO
496 // ORB NO NO YES(Lsh) YES YES
497 // BRIEF NO NO YES(Lsh) YES YES
498 // FREAK NO NO YES(Lsh) YES YES
499 // The ORB and BRIEF descriptors and BruteForce-Hamming and BruteForce-HammingLUT
500 // matching schemes generate or accept binary-string descriptors (CV_8U), while
501 // the other descriptors and matching schemes generate or accept vectors of floating
502 // point values (CV_32F). It is possible to mix and match the descriptors more by
503 // converting the data format of the descriptor matrix prior to matching, but this can
504 // sometimes lead to very poor matching results, so attempt it with caution.
505 //*****************************************************************************
507 {
508  bool createOK = false;
509  m_matcherName = name;
510 
511  if (m_matcherName == "FlannBased")
512  {
513  // Set LshIndexParams(int table_number, int key_size, int multi_probe_level)
514  m_matcher = new cv::FlannBasedMatcher(new cv::flann::LshIndexParams(20,10,2));
515  }
516  else
517  {
518  m_matcher = cv::DescriptorMatcher::create(m_matcherName.string());
519  }
520 
521  if( m_matcher != 0 )
522  {
523  createOK = true;
524 // std::vector<std::string> parameters;
525 // m_matcher->getParams(parameters);
526 // if (traceDebug())
527 // {
528 // ossimNotify(ossimNotifyLevel_DEBUG)
529 // << "DEBUG: ...matcher..." << std::endl;
530 // for (int i = 0; i < (int) parameters.size(); i++)
531 // ossimNotify(ossimNotifyLevel_DEBUG)<<" "<<parameters[i]<<std::endl;
532 // }
533  }
534 
535  // TODO: Garrett: this was causing core dumps so I commented it out. Also, it appears that in the docs
536  // the default for crossCheck argument in the base constructor is false.
537  // Set crossCheck
538  //m_matcher->set("crossCheck", false);
539 
540 
541  return createOK;
542 }
543 
544 
545 //*****************************************************************************
546 // METHOD: ossimTieMeasurementGenerator::setGridSize()
547 //
548 //*****************************************************************************
550 {
551  bool setOK = false;
552 
553  if (gridDimensions.x>0 && gridDimensions.y>0)
554  {
555  m_gridSize = gridDimensions;
556  setOK = true;
557  }
558 
559  return setOK;
560 }
561 
562 
563 bool ossimTieMeasurementGenerator::setImageList(std::vector<ossimImageSource*> src)
564 {
565  m_src.clear();
566 
567  // Load the image source pointers
568  // Note: The source pointer vector may contain more than
569  // two images, but only the first two are used
570  // in the auto measurement process.
571  for (ossim_uint32 n=0; n<src.size(); ++n)
572  m_src.push_back(src[n]);
573 
574  m_spIndexA = 0;
575  m_spIndexB = 1;
576 }
577 
578 bool ossimTieMeasurementGenerator::setROIs(std::vector<ossimIrect> roi)
579 {
580  // The image list must be defined first!
581  if (m_src.size() != roi.size())
582  return false;
583 
584  m_validBox = false;
585 
586  // Save reference points (patch centers)
587  roi[m_spIndexA].getCenter(m_patchRefA);
588  roi[m_spIndexB].getCenter(m_patchRefB);
589 
590  // Save dimensions (patch sizes)
591  m_patchSizeA.x = roi[m_spIndexA].width();
592  m_patchSizeA.y = roi[m_spIndexA].height();
593  m_patchSizeB.x = roi[m_spIndexB].width();
594  m_patchSizeB.y = roi[m_spIndexB].height();
595 
596  // Set the IvtGeometryXforms
597  ossimIvtGeomXformVisitor visitorA;
598  m_src[m_spIndexA]->accept(visitorA);
599  if (visitorA.getTransformList().size() == 1)
600  {
601  m_igxA = visitorA.getTransformList()[0].get();
602  }
603  ossimIvtGeomXformVisitor visitorB;
604  m_src[m_spIndexB]->accept(visitorB);
605  if (visitorB.getTransformList().size() == 1)
606  {
607  m_igxB = visitorB.getTransformList()[0].get();
608  }
609 
610  m_validBox = true;
611 
612  if (traceDebug())
613  {
615  << "DEBUG: ...ossimTieMeasurementGenerator::setBox" << std::endl;
616  ossimNotify(ossimNotifyLevel_DEBUG)<<" m_spIndexA = "<<m_spIndexA<<std::endl;
617  ossimNotify(ossimNotifyLevel_DEBUG)<<" m_spIndexB = "<<m_spIndexB<<std::endl;
618  ossimNotify(ossimNotifyLevel_DEBUG)<<" m_patchRefA = "<<m_patchRefA<<std::endl;
619  ossimNotify(ossimNotifyLevel_DEBUG)<<" m_patchRefB = "<<m_patchRefB<<std::endl;
620  ossimNotify(ossimNotifyLevel_DEBUG)<<" m_patchSizeA = "<<m_patchSizeA<<std::endl;
621  ossimNotify(ossimNotifyLevel_DEBUG)<<" m_patchSizeB = "<<m_patchSizeB<<std::endl;
622  }
623 
624  return m_validBox;
625 }
626 
627 
628 //*****************************************************************************
629 // METHOD: ossimTieMeasurementGenerator::setMaxMatches()
630 //
631 //*****************************************************************************
633 {
634  bool setOK = false;
635 
636  if (maxMatches > 0)
637  {
638  m_maxMatches = maxMatches;
639  setOK = true;
640  }
641 
642  return setOK;
643 }
644 
645 
646 //*****************************************************************************
647 // METHOD: ossimTieMeasurementGenerator::pointIndexedAt()
648 //
649 //*****************************************************************************
651  (const ossim_uint32 imgIdx, const ossim_uint32 measIdx)
652 {
653  if ((int)measIdx<m_numMeasurements && imgIdx<2)
654  {
655  if (imgIdx == 0)
656  {
657  if (m_spIndexA == 0)
658  return m_measA[measIdx];
659  else
660  return m_measB[measIdx];
661  }
662  else
663  {
664  if (m_spIndexA == 1)
665  return m_measA[measIdx];
666  else
667  return m_measB[measIdx];
668  }
669  }
670  else
671  {
672  ossimDpt bad;
673  bad.makeNan();
674  return bad;
675  }
676 }
677 
678 
679 //*****************************************************************************
680 // METHOD: ossimTieMeasurementGenerator::summarizeRun()
681 //
682 //*****************************************************************************
684 {
685  *m_rep<<"\n Configuration..."<<std::endl;
686  *m_rep<<" Detector: "<<getFeatureDetector()<<std::endl;
687  *m_rep<<" Descriptor: "<<getDescriptorExtractor()<<std::endl;
688  *m_rep<<" Matcher: "<<getDescriptorMatcher()<<std::endl;
689  *m_rep<<" Patch size: "<<m_patchSizeA<<std::endl;
690  *m_rep<<" Grid size: "<<m_gridSize<<std::endl;
691 
692  ossimString ts;
693  ossim::getFormattedTime("%a %m.%d.%y %H:%M:%S", false, ts);
694  *m_rep << "\n";
695  *m_rep << "\n" << ts;
696  *m_rep << "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
697  *m_rep << std::endl;
698 }
699 
700 
701 //*****************************************************************************
702 // METHOD: ossimTieMeasurementGenerator::showCvResultsWindow()
703 //
704 //*****************************************************************************
706  std::vector<cv::KeyPoint> keypointsA,
707  std::vector<cv::KeyPoint> keypointsB,
708  std::vector<cv::DMatch> goodMatches)
709 {
710  //-- Draw only "good" matches
711  // DEFAULT
712  // DRAW_OVER_OUTIMG
713  // NOT_DRAW_SINGLE_POINTS
714  // DRAW_RICH_KEYPOINTS
715  cv::namedWindow(m_cvWindowName.string());
716  cv::Mat imgMatch;
717  cv::drawMatches(m_imgA, keypointsA, m_imgB, keypointsB, goodMatches, imgMatch,
718  cv::Scalar::all(-1), cv::Scalar::all(-1), vector<char>(), cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
719 
720  // Scale down the results window if necessary using a somewhat arbitrary factor for now
723  double sFac = 1.0;
724  if (rRatio <= cRatio)
725  {
726  if (rRatio < 1.0)
727  sFac = rRatio;
728  }
729  else
730  {
731  if (cRatio< 1.0)
732  sFac = cRatio;
733  }
734  cv::Mat imgMatchOut;
735  cv::resize(imgMatch, imgMatchOut, cv::Size(), sFac, sFac);
736  cv::imshow(m_cvWindowName.string(), imgMatchOut);
737 }
738 
739 
740 //*****************************************************************************
741 // METHOD: ossimTieMeasurementGenerator::closeCvWindow()
742 //
743 //*****************************************************************************
744 void ossimTieMeasurementGenerator::closeCvWindow(const bool waitKeyPress)
745 {
746  if (waitKeyPress)
747  {
748  cv::waitKey();
749  }
750 
751  cv::destroyWindow(m_cvWindowName.string());
752 }
ossimRefPtr< ossimIvtGeomXform > m_igxA
ossim_uint32 height() const
Definition: ossimIrect.h:487
cv::Ptr< cv::DescriptorExtractor > m_extractor
virtual bool setROIs(std::vector< ossimIrect > roi)
bool setDescriptorMatcher(const ossimString &name)
ossimRefPtr< ossimIvtGeomXform > m_igxB
void showCvResultsWindow(std::vector< cv::KeyPoint > keypointsA, std::vector< cv::KeyPoint > keypointsB, std::vector< cv::DMatch > goodMatches)
bool init(std::ostream &report=cout)
void viewToImage(const ossimDpt &viewPt, ossimDpt &ipt)
void closeCvWindow(const bool waitKeyPress=false)
bool setFeatureDetector(const ossimString &name)
OSSIM_DLL void getFormattedTime(const std::string &format, bool gmtFlag, std::string &result)
Gets the current time.
os2<< "> n<< " > nendobj n
unsigned int ossim_uint32
bool setDescriptorExtractor(const ossimString &name)
ossim_uint32 width() const
Definition: ossimIrect.h:500
cv::Ptr< cv::Feature2D > createFeature2D(const ossimString &name)
bool setMaxMatches(const int &maxMatches)
#define max(a, b)
Definition: auxiliary.h:76
ossim_int32 y
Definition: ossimIpt.h:142
bool setGridSize(const ossimIpt &gridDimensions)
virtual const void * getBuf() const
ossimDpt pointIndexedAt(const ossim_uint32 imgIdx, const ossim_uint32 measIdx)
ossim_uint32 area() const
Definition: ossimIrect.h:396
virtual bool setImageList(std::vector< ossimImageSource *> src)
std::vector< ossimImageSource * > m_src
ossim_int32 x
Definition: ossimIpt.h:141
cv::Ptr< cv::DescriptorMatcher > m_matcher
float distance(double lat1, double lon1, double lat2, double lon2, int units)
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
void makeNan()
Definition: ossimDpt.h:65
std::basic_ostream< char > ostream
Base class for char output streams.
Definition: ossimIosFwd.h:23
const std::string & string() const
Definition: ossimString.h:414