10 #include "atp/AtpCommon.h" 14 #include <opencv2/xfeatures2d.hpp> 18 static const int DEFAULT_CMP_PATCH_SIZING_FACTOR = 2;
19 static const double DEFAULT_NOMINAL_POSITION_ERROR = 50;
49 double nominalGsd = (gsd.
x + gsd.
y)/2.0;
53 m_generator->getRefIVT()->getImageGeometry()->getProjection());
55 m_generator->getCmpIVT()->getImageGeometry()->getProjection());
60 double total_error = ref_ce + cmp_ce;
72 static const char* MODULE =
"ossimDescriptorSource::getTile() ";
76 CINFO<<
"\n\n"<< MODULE <<
" -- tileRect: "<<tileRect<<endl;
87 CINFO << MODULE <<
" ERROR: wrong number of inputs " <<
getNumberOfInputs() <<
" when expecting at least 2 \n";
100 if (ref_tile->getDataObjectStatus() ==
OSSIM_EMPTY)
102 CWARN << MODULE <<
" ERROR: could not get REF tile with rect " << refRect <<
"\n";
106 ref_tile->
write(
"REF_TILE.RAS");
112 CWARN << MODULE <<
" ERROR: could not get CMP tile with rect " << cmpRect <<
"\n";
116 cmp_tile->
write(
"CMP_TILE.RAS");
123 cv::Mat queryImg = cv::cvarrToMat(refImage);
124 cv::Mat trainImg = cv::cvarrToMat(cmpImage);
127 vector<cv::KeyPoint> kpA;
128 vector<cv::KeyPoint> kpB;
136 cv::Ptr<cv::Feature2D> detector;
137 if(descriptorType ==
"AKAZE")
138 detector = cv::AKAZE::create();
139 else if(descriptorType ==
"KAZE")
140 detector = cv::KAZE::create();
141 else if(descriptorType ==
"ORB")
142 detector = cv::ORB::create();
143 else if(descriptorType ==
"SURF")
144 detector = cv::xfeatures2d::SURF::create();
145 else if(descriptorType ==
"SIFT")
146 detector = cv::xfeatures2d::SIFT::create();
149 CWARN << MODULE <<
" WARNING: No such descriptor as " << descriptorType <<
"\n";
154 detector->detectAndCompute(queryImg, cv::noArray(), kpA, desA);
155 detector->detectAndCompute(trainImg, cv::noArray(), kpB, desB);
160 detector->detect(queryImg, kpA);
161 detector->detect(trainImg, kpB);
165 CINFO <<
"DETECTIONS: "<<kpA.size() <<
", "<<kpB.size() << endl;
170 if (kpA.size() > maxNumFeatures)
172 sort(kpA.begin(), kpA.end(),
sortFunc);
173 kpA.resize(maxNumFeatures);
185 detector->compute(queryImg, kpA, desA);
186 detector->compute(trainImg, kpB, desB);
194 CINFO <<
"\nDETECT:\n kpA.size = " << kpA.size() << endl;
195 CINFO <<
" kpb.size = " << kpA.size() << endl;
196 CINFO <<
"\nCOMPUTE:\n desA.size = " << desA.size() << endl;
197 CINFO <<
" desB.size = " << desB.size() << endl;
201 std::vector< std::vector<cv::DMatch> > matches;
202 if(!(desA.empty() || desB.empty()))
210 transform(matcherType.begin(), matcherType.end(), matcherType.begin(),::toupper);
212 shared_ptr<cv::DescriptorMatcher> matcher;
213 if(matcherType ==
"FLANN")
215 if(desA.type()!=CV_32F)
216 desA.convertTo(desA, CV_32F);
217 if(desB.type()!=CV_32F)
218 desB.convertTo(desB, CV_32F);
220 matcher.reset(
new cv::FlannBasedMatcher);
222 else if(matcherType ==
"BF")
224 if(desA.type()!=CV_8U)
225 desA.convertTo(desA, CV_8U);
226 if(desB.type()!=CV_8U)
227 desB.convertTo(desB, CV_8U);
231 if(ErrorFunction ==
"NORM_L1"){
232 normType = cv::NORM_L1;
233 }
else if(ErrorFunction ==
"NORM_L2") {
234 normType = cv::NORM_L2;
235 }
else if(ErrorFunction ==
"NORM_HAMMING") {
236 normType = cv::NORM_HAMMING;
239 if(descriptorUsed ==
"SURF" || descriptorUsed ==
"SIFT"){
240 normType = cv::NORM_L2;
242 normType = cv::NORM_HAMMING;
246 matcher.reset(
new cv::BFMatcher(normType,
true));
250 CWARN << MODULE <<
" WARNING: No such matcher as " << matcherType <<
"\n";
254 matcher->knnMatch(desA, desB, matches, k);
257 float minDistance = INT_MAX;
258 float maxDistance = 0;
261 for (
auto &featureMatches : matches)
263 for (
auto &match : featureMatches)
265 if (minDistance >match.distance)
266 minDistance = match.distance;
267 if (maxDistance < match.distance)
268 maxDistance = match.distance;
274 float delta = maxDistance - minDistance;
277 multimap<double, shared_ptr<AutoTiePoint> > tpMap;
282 for (
auto &featureMatches : matches)
284 if (featureMatches.empty())
288 cv::KeyPoint cv_A = kpA[(featureMatches[0]).queryIdx];
291 ossimDpt refImgPt (refRect.ul().x + cv_A.pt.x, refRect.ul().y + cv_A.pt.y);
292 atp->setRefImagePt(refImgPt);
296 for (
auto &match : featureMatches)
298 cv_B = kpB[(match).trainIdx];
299 ossimDpt cmpImgPt (cmpRect.ul().x + cv_B.pt.x, cmpRect.ul().y + cv_B.pt.y);
300 double strength_j = 1.0 - (match.distance-minDistance)/delta;
301 if (strength_j > strength)
302 strength = strength_j;
303 atp->addImageMatch(cmpImgPt, strength_j);
307 tpMap.insert(pair<
double, shared_ptr<AutoTiePoint> >(1.0-strength, atp));
313 CINFO<<
" Detections R,C: "<<kpA.size() <<
", "<<kpB.size() << endl;
314 CINFO<<
" Matches (Before filtering): "<<matches.size()<<endl;
321 auto tp_iter = tpMap.begin();
322 while ((tp_iter != tpMap.end()) && (
n < N))
330 CINFO<<
" After capping to max num features ("<<N<<
"), num TPs in tile = "<<
n<<endl;
virtual const double & getNominalPosError() const
Returns the estimated Absolute horizontal position error (CE90) of the sensor model.
JsonParam & getParameter(const char *paramName)
Returns a parameter (might be a null parameter if paramName not found in the configuration.
static ossimString upcase(const ossimString &aString)
virtual void setImageRectangle(const ossimIrect &rect)
Base class for all automatic tiepoints.
struct ATP::ossimDescriptorSource::SortFunc sortFunc
std::shared_ptr< AtpGenerator > m_generator
unsigned int asUint() const
virtual ossimDataObjectStatus getDataObjectStatus() const
Base class for tile sources performing auto tie point extraction.
unsigned int m_cmpPatchInflation
bool paramExists(const char *paramName) const
const ossimIrect & expand(const ossimIpt &padding)
virtual bool write(const ossimFilename &f) const
Writes tile to stream.
virtual void initialize()
std::string asString() const
virtual void initialize()
std::vector< ossimRefPtr< ossimConnectableObject > > ConnectableObjectList
os2<< "> n<< " > nendobj n
Base class for OSSIM-based ATP generators.
unsigned int ossim_uint32
virtual ~ossimDescriptorSource()
THESE FUNCTIONS REQUIRE OPENCV.
ossimRefPtr< ossimImageData > m_tile
bool diagnosticLevel(unsigned int level) const
Convenience method returns TRUE if the currently set diagnostic level is <= level.
IplImage * convertToIpl(const ossimImageData *data)
Converts an ossimImageData pointer to an IplImage for use in OpenCV.
virtual ossim_uint32 getNumberOfInputs() const
Returns the number of input objects.
static AtpConfig & instance()
Singleton implementation.
virtual ossimRefPtr< ossimImageData > getTile(const ossimIrect &origin, ossim_uint32 rLevel=0)
Derived classes implement their particular tiepoint matching algorithms for the requested tile...
Singleton class maintaining parameters affecting the automatic tie point generation.