gdal_simplesurf.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. /******************************************************************************
  2. * Project: GDAL
  3. * Purpose: Correlator
  4. * Author: Andrew Migal, migal.drew@gmail.com
  5. *
  6. ******************************************************************************
  7. * Copyright (c) 2012, Andrew Migal
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a
  10. * copy of this software and associated documentation files (the "Software"),
  11. * to deal in the Software without restriction, including without limitation
  12. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13. * and/or sell copies of the Software, and to permit persons to whom the
  14. * Software is furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included
  17. * in all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  22. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  24. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  25. * DEALINGS IN THE SOFTWARE.
  26. ****************************************************************************/
  27. /**
  28. * @file
  29. * @author Andrew Migal migal.drew@gmail.com
  30. * @brief Class for searching corresponding points on images.
  31. */
  32. #ifndef GDALSIMPLESURF_H_
  33. #define GDALSIMPLESURF_H_
  34. #include "gdal_priv.h"
  35. #include "cpl_conv.h"
  36. #include <list>
  37. /**
  38. * @brief Class of "feature point" in raster. Used by SURF-based algorithm.
  39. *
  40. * @details This point presents coordinates of distinctive pixel in image.
  41. * In computer vision, feature points - the most "strong" and "unique"
  42. * pixels (or areas) in picture, which can be distinguished from others.
  43. * For more details, see FAST corner detector, SIFT, SURF and similar algorithms.
  44. */
  45. class GDALFeaturePoint
  46. {
  47. public:
  48. /**
  49. * Standard constructor. Initializes all parameters with negative numbers
  50. * and allocates memory for descriptor.
  51. */
  52. GDALFeaturePoint();
  53. /**
  54. * Copy constructor
  55. * @param fp Copied instance of GDALFeaturePoint class
  56. */
  57. GDALFeaturePoint(const GDALFeaturePoint& fp);
  58. /**
  59. * Create instance of GDALFeaturePoint class
  60. *
  61. * @param nX X-coordinate (pixel)
  62. * @param nY Y-coordinate (line)
  63. * @param nScale Scale which contains this point (2, 4, 8, 16 and so on)
  64. * @param nRadius Half of the side of descriptor area
  65. * @param nSign Sign of Hessian determinant for this point
  66. *
  67. * @note This constructor normally is invoked by SURF-based algorithm,
  68. * which provides all necessary parameters.
  69. */
  70. GDALFeaturePoint(int nX, int nY, int nScale, int nRadius, int nSign);
  71. virtual ~GDALFeaturePoint();
  72. GDALFeaturePoint& operator=(const GDALFeaturePoint& point);
  73. /**
  74. * Provide access to point's descriptor.
  75. *
  76. * @param nIndex Position of descriptor's value.
  77. * nIndex should be within range from 0 to DESC_SIZE (in current version - 64)
  78. *
  79. * @return Reference to value of descriptor in 'nIndex' position.
  80. * If index is out of range then behaviour is undefined.
  81. */
  82. double& operator[](int nIndex);
  83. // Descriptor length
  84. static const int DESC_SIZE = 64;
  85. /**
  86. * Fetch X-coordinate (pixel) of point
  87. *
  88. * @return X-coordinate in pixels
  89. */
  90. int GetX();
  91. /**
  92. * Set X coordinate of point
  93. *
  94. * @param nX X coordinate in pixels
  95. */
  96. void SetX(int nX);
  97. /**
  98. * Fetch Y-coordinate (line) of point.
  99. *
  100. * @return Y-coordinate in pixels.
  101. */
  102. int GetY();
  103. /**
  104. * Set Y coordinate of point.
  105. *
  106. * @param nY Y coordinate in pixels.
  107. */
  108. void SetY(int nY);
  109. /**
  110. * Fetch scale of point.
  111. *
  112. * @return Scale for this point.
  113. */
  114. int GetScale();
  115. /**
  116. * Set scale of point.
  117. *
  118. * @param nScale Scale for this point.
  119. */
  120. void SetScale(int nScale);
  121. /**
  122. * Fetch radius of point.
  123. *
  124. * @return Radius for this point.
  125. */
  126. int GetRadius();
  127. /**
  128. * Set radius of point.
  129. *
  130. * @param nRadius Radius for this point.
  131. */
  132. void SetRadius(int nRadius);
  133. /**
  134. * Fetch sign of Hessian determinant of point.
  135. *
  136. * @return Sign for this point.
  137. */
  138. int GetSign();
  139. /**
  140. * Set sign of point.
  141. *
  142. * @param nSign Sign of Hessian determinant for this point.
  143. */
  144. void SetSign(int nSign);
  145. private:
  146. // Coordinates of point in image
  147. int nX;
  148. int nY;
  149. // --------------------
  150. int nScale;
  151. int nRadius;
  152. int nSign;
  153. // Descriptor array
  154. double *padfDescriptor;
  155. };
  156. /**
  157. * @author Andrew Migal migal.drew@gmail.com
  158. * @brief Integral image class (summed area table).
  159. * @details Integral image is a table for fast computing the sum of
  160. * values in rectangular subarea. In more detail, for 2-dimensional array
  161. * of numbers this class provides capabilty to get sum of values in
  162. * rectangular arbitrary area with any size in constant time.
  163. * Integral image is constructed from grayscale picture.
  164. */
  165. class GDALIntegralImage
  166. {
  167. public:
  168. GDALIntegralImage();
  169. virtual ~GDALIntegralImage();
  170. /**
  171. * Compute integral image for specified array. Result is stored internally.
  172. *
  173. * @param padfImg Pointer to 2-dimensional array of values
  174. * @param nHeight Number of rows in array
  175. * @param nWidth Number of columns in array
  176. */
  177. void Initialize(const double **padfImg, int nHeight, int nWidth);
  178. /**
  179. * Fetch value of specified position in integral image.
  180. *
  181. * @param nRow Row of this position
  182. * @param nCol Column of this position
  183. *
  184. * @return Value in specified position or zero if parameters are out of range.
  185. */
  186. double GetValue(int nRow, int nCol);
  187. /**
  188. * Get sum of values in specified rectangular grid. Rectangle is constructed
  189. * from left top point.
  190. *
  191. * @param nRow Row of left top point of rectangle
  192. * @param nCol Column of left top point of rectangle
  193. * @param nWidth Width of rectangular area (number of columns)
  194. * @param nHeight Heigth of rectangular area (number of rows)
  195. *
  196. * @return Sum of values in specified grid.
  197. */
  198. double GetRectangleSum(int nRow, int nCol, int nWidth, int nHeight);
  199. /**
  200. * Get value of horizontal Haar wavelet in specified square grid.
  201. *
  202. * @param nRow Row of left top point of square
  203. * @param nCol Column of left top point of square
  204. * @param nSize Side of the square
  205. *
  206. * @return Value of horizontal Haar wavelet in specified square grid.
  207. */
  208. double HaarWavelet_X(int nRow, int nCol, int nSize);
  209. /**
  210. * Get value of vertical Haar wavelet in specified square grid.
  211. *
  212. * @param nRow Row of left top point of square
  213. * @param nCol Column of left top point of square
  214. * @param nSize Side of the square
  215. *
  216. * @return Value of vertical Haar wavelet in specified square grid.
  217. */
  218. double HaarWavelet_Y(int nRow, int nCol, int nSize);
  219. /**
  220. * Fetch height of integral image.
  221. *
  222. * @return Height of integral image (number of rows).
  223. */
  224. int GetHeight();
  225. /**
  226. * Fetch width of integral image.
  227. *
  228. * @return Width of integral image (number of columns).
  229. */
  230. int GetWidth();
  231. private:
  232. double **pMatrix;
  233. int nWidth;
  234. int nHeight;
  235. };
  236. /**
  237. * @author Andrew Migal migal.drew@gmail.com
  238. * @brief Class for computation and storage of Hessian values in SURF-based algorithm.
  239. *
  240. * @details SURF-based algorithm normally uses this class for searching
  241. * feature points on raster images. Class also contains traces of Hessian matrices
  242. * to provide fast computations.
  243. */
  244. class GDALOctaveLayer
  245. {
  246. public:
  247. GDALOctaveLayer();
  248. /**
  249. * Create instance with provided parameters.
  250. *
  251. * @param nOctave Number of octave which contains this layer
  252. * @param nInterval Number of position in octave
  253. *
  254. * @note Normally constructor is invoked only by SURF-based algorithm.
  255. */
  256. GDALOctaveLayer(int nOctave, int nInterval);
  257. virtual ~GDALOctaveLayer();
  258. /**
  259. * Perform calculation of Hessian determinats and their signs
  260. * for specified integral image. Result is stored internally.
  261. *
  262. * @param poImg Integral image object, which provides all necessary
  263. * data for computation
  264. *
  265. * @note Normally method is invoked only by SURF-based algorithm.
  266. */
  267. void ComputeLayer(GDALIntegralImage *poImg);
  268. /**
  269. * Octave which contains this layer (1,2,3...)
  270. */
  271. int octaveNum;
  272. /**
  273. * Length of the side of filter
  274. */
  275. int filterSize;
  276. /**
  277. * Length of the border
  278. */
  279. int radius;
  280. /**
  281. * Scale for this layer
  282. */
  283. int scale;
  284. /**
  285. * Image width in pixels
  286. */
  287. int width;
  288. /**
  289. * Image height in pixels
  290. */
  291. int height;
  292. /**
  293. * Hessian values for image pixels
  294. */
  295. double **detHessians;
  296. /**
  297. * Hessian signs for speeded matching
  298. */
  299. int **signs;
  300. };
  301. /**
  302. * @author Andrew Migal migal.drew@gmail.com
  303. * @brief Class for handling octave layers in SURF-based algorithm.
  304. * @details Class contains OctaveLayers and provides capability to construct octave space and distinguish
  305. * feature points. Normally this class is used only by SURF-based algorithm.
  306. */
  307. class GDALOctaveMap
  308. {
  309. public:
  310. /**
  311. * Create octave space. Octave numbers are start with one. (1, 2, 3, 4, ... )
  312. *
  313. * @param nOctaveStart Number of bottom octave
  314. * @param nOctaveEnd Number of top octave. Should be equal or greater than OctaveStart
  315. */
  316. GDALOctaveMap(int nOctaveStart, int nOctaveEnd);
  317. virtual ~GDALOctaveMap();
  318. /**
  319. * Calculate Hessian values for octave space
  320. * (for all stored octave layers) using specified integral image
  321. * @param poImg Integral image instance which provides necessary data
  322. * @see GDALOctaveLayer
  323. */
  324. void ComputeMap(GDALIntegralImage *poImg);
  325. /**
  326. * Method makes decision that specified point
  327. * in middle octave layer is maximum among all points
  328. * from 3x3x3 neighbourhood (surrounding points in
  329. * bottom, middle and top layers). Provided layers should be from the same octave's interval.
  330. * Detects feature points.
  331. *
  332. * @param row Row of point, which is candidate to be feature point
  333. * @param col Column of point, which is candidate to be feature point
  334. * @param bot Bottom octave layer
  335. * @param mid Middle octave layer
  336. * @param top Top octave layer
  337. * @param threshold Threshold for feature point recognition. Detected feature point
  338. * will have Hessian value greater than this provided threshold.
  339. *
  340. * @return TRUE if candidate was evaluated as feature point or FALSE otherwise.
  341. */
  342. bool PointIsExtremum(int row, int col, GDALOctaveLayer *bot,
  343. GDALOctaveLayer *mid, GDALOctaveLayer *top, double threshold);
  344. /**
  345. * 2-dimensional array of octave layers
  346. */
  347. GDALOctaveLayer ***pMap;
  348. /**
  349. * Value for constructing internal octave space
  350. */
  351. static const int INTERVALS = 4;
  352. /**
  353. * Number of bottom octave
  354. */
  355. int octaveStart;
  356. /**
  357. * Number of top octave. Should be equal or greater than OctaveStart
  358. */
  359. int octaveEnd;
  360. };
  361. /**
  362. * @author Andrew Migal migal.drew@gmail.com
  363. * @brief Class for searching corresponding points on images.
  364. * @details Provides capability for detection feature points
  365. * and finding equal points on different images.
  366. * Class implements simplified version of SURF algorithm (Speeded Up Robust Features).
  367. * As original, this realization is scale invariant, but sensitive to rotation.
  368. * Images should have similar rotation angles (maximum difference is up to 10-15 degrees),
  369. * otherwise algorithm produces incorrect and very unstable results.
  370. */
  371. class GDALSimpleSURF
  372. {
  373. private:
  374. /**
  375. * Class stores indexes of pair of point
  376. * and distance between them.
  377. */
  378. class MatchedPointPairInfo
  379. {
  380. public:
  381. MatchedPointPairInfo(int nInd_1, int nInd_2, double dfDist)
  382. {
  383. ind_1 = nInd_1;
  384. ind_2 = nInd_2;
  385. euclideanDist = dfDist;
  386. }
  387. int ind_1;
  388. int ind_2;
  389. double euclideanDist;
  390. };
  391. public:
  392. /**
  393. * Prepare class according to specified parameters. Octave numbers affects
  394. * to amount of detected points and their robustness.
  395. * Range between bottom and top octaves also affects to required time of detection points
  396. * (if range is large, algorithm should perform more operations).
  397. * @param nOctaveStart Number of bottom octave. Octave numbers starts with one
  398. * @param nOctaveEnd Number of top octave. Should be equal or greater than OctaveStart
  399. *
  400. * @note
  401. * Every octave finds points with specific size. For small images
  402. * use small octave numbers, for high resolution - large.
  403. * For 1024x1024 images it's normal to use any octave numbers from range 1-6.
  404. * (for example, octave start - 1, octave end - 3, or octave start - 2, octave end - 2.)
  405. * For larger images, try 1-10 range or even higher.
  406. * Pay attention that number of detected point decreases quickly per octave
  407. * for particular image. Algorithm finds more points in case of small octave numbers.
  408. * If method detects nothing, reduce bottom bound of octave range.
  409. *
  410. * NOTICE that every octave requires time to compute. Use a little range
  411. * or only one octave if execution time is significant.
  412. */
  413. GDALSimpleSURF(int nOctaveStart, int nOctaveEnd);
  414. virtual ~GDALSimpleSURF();
  415. /**
  416. * Convert image with RGB channels to grayscale using "luminosity" method.
  417. * Result is used in SURF-based algorithm, but may be used anywhere where
  418. * grayscale images with nice contrast are required.
  419. *
  420. * @param red Image's red channel
  421. * @param green Image's green channel
  422. * @param blue Image's blue channel
  423. * @param nXSize Width of initial image
  424. * @param nYSize Height of initial image
  425. * @param padfImg Array for resulting grayscale image
  426. * @param nHeight Height of resulting image
  427. * @param nWidth Width of resulting image
  428. *
  429. * @return CE_None or CE_Failure if error occurs.
  430. */
  431. static CPLErr ConvertRGBToLuminosity(
  432. GDALRasterBand *red,
  433. GDALRasterBand *green,
  434. GDALRasterBand *blue,
  435. int nXSize, int nYSize,
  436. double **padfImg, int nHeight, int nWidth);
  437. /**
  438. * Find feature points using specified integral image.
  439. *
  440. * @param poImg Integral image to be used
  441. * @param dfThreshold Threshold for feature point recognition. Detected feature point
  442. * will have Hessian value greater than this provided threshold.
  443. *
  444. * @note Typical threshold's value is 0,001. But this value
  445. * can be various in each case and depends on image's nature.
  446. * For example, value can be 0.002 or 0.005.
  447. * Fill free to experiment with it.
  448. * If threshold is high, than number of detected feature points is small,
  449. * and vice versa.
  450. */
  451. std::vector<GDALFeaturePoint>*
  452. ExtractFeaturePoints(GDALIntegralImage *poImg, double dfThreshold);
  453. /**
  454. * Find corresponding points (equal points in two collections).
  455. *
  456. * @param poMatchPairs Resulting collection for matched points
  457. * @param poSecondCollect Points on the first image
  458. * @param poSecondCollect Points on the second image
  459. * @param dfThreshold Value from 0 to 1. Threshold affects to number of
  460. * matched points. If threshold is lower, amount of corresponding
  461. * points is larger, and vice versa
  462. *
  463. * @return CE_None or CE_Failure if error occurs.
  464. */
  465. static CPLErr MatchFeaturePoints(
  466. std::vector<GDALFeaturePoint*> *poMatchPairs,
  467. std::vector<GDALFeaturePoint> *poFirstCollect,
  468. std::vector<GDALFeaturePoint> *poSecondCollect,
  469. double dfThreshold);
  470. private:
  471. /**
  472. * Compute euclidean distance between descriptors of two feature points.
  473. * It's used in comparison and matching of points.
  474. *
  475. * @param firstPoint First feature point to be compared
  476. * @param secondPoint Second feature point to be compared
  477. *
  478. * @return Euclidean distance between descriptors.
  479. */
  480. static double GetEuclideanDistance(
  481. GDALFeaturePoint &firstPoint, GDALFeaturePoint &secondPoint);
  482. /**
  483. * Set provided distance values to range from 0 to 1.
  484. *
  485. * @param poList List of distances to be normalized
  486. */
  487. static void NormalizeDistances(std::list<MatchedPointPairInfo> *poList);
  488. /**
  489. * Compute descriptor for specified feature point.
  490. *
  491. * @param poPoint Feature point instance
  492. * @param poImg image where feature point was found
  493. */
  494. void SetDescriptor(GDALFeaturePoint *poPoint, GDALIntegralImage *poImg);
  495. private:
  496. int octaveStart;
  497. int octaveEnd;
  498. GDALOctaveMap *poOctMap;
  499. };
  500. #endif /* GDALSIMPLESURF_H_ */