findzc.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /**
  2. * \file findzc.c
  3. *
  4. * \brief Zero Crossing functions.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or (at
  9. * your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. *
  20. * \author GRASS GIS Development Team
  21. * \author Brad Douglas - rez at touchofmadness com
  22. *
  23. * \date 2006
  24. */
  25. #include <stdio.h>
  26. #include <math.h>
  27. /** \def TINY Defined as 1.0e-3 */
  28. #define TINY 1.0e-3
  29. /**
  30. * \fn int G_math_findzc (double conv[], int size, double zc[], double thresh, int num_orients)
  31. *
  32. * \brief Finds locations and orientations of zero crossings.
  33. *
  34. * Finds the locations and orientations of zero crossings in the input
  35. * array <b>conv</b>, which is the result of the convolution of the
  36. * Marr-Hildreth operator with the image. The output array is <b>zc</b>,
  37. * which is non-zero only at zero crossing pixels. At those pixels, the
  38. * value is 1 + (orientation), where orientation is a value from 0 to
  39. * <b>num_orients</b>.
  40. *
  41. * \param[in] conv input
  42. * \param[in] size size of largest matrix column or row
  43. * \param[out] zc output
  44. * \param[in] thresh magnitude threshold
  45. * \param[in] num_orients
  46. * \return int always returns 0
  47. */
  48. int
  49. G_math_findzc(double conv[], int size, double zc[], double thresh,
  50. int num_orients)
  51. {
  52. int i, j, p;
  53. /* go through entire conv image - but skip border rows and cols */
  54. for (i = 1; i < size - 1; i++) {
  55. for (p = i * size + 1, j = 1; j < size - 1; j++, p++) {
  56. int nbr[4];
  57. int ni;
  58. /* examine the 4-neighbors of position p */
  59. nbr[0] = p - 1; /* left */
  60. nbr[1] = p + 1; /* right */
  61. nbr[2] = p - size; /* up */
  62. nbr[3] = p + size; /* down */
  63. zc[p] = 0;
  64. for (ni = 0; ni < 4; ni++) {
  65. /* condition for a zc: sign is different than a neighbor
  66. * and the absolute value is less than that neighbor.
  67. * Also, threshold magnitudes to eliminate noise
  68. */
  69. if ((((conv[p] > 0) && (conv[nbr[ni]] < 0)) ||
  70. ((conv[p] < 0) && (conv[nbr[ni]] > 0))) &&
  71. (fabs(conv[p]) < fabs(conv[nbr[ni]])) &&
  72. (fabs(conv[p] - conv[nbr[ni]]) > thresh)) {
  73. double ang;
  74. int dir;
  75. /* found a zc here, get angle of gradient */
  76. if (fabs(conv[nbr[1]] - conv[nbr[0]]) < TINY) {
  77. ang = M_PI_2;
  78. if (conv[nbr[2]] - conv[nbr[3]] < 0)
  79. ang = -ang;
  80. }
  81. else
  82. ang = atan2(conv[nbr[2]] - conv[nbr[3]],
  83. conv[nbr[1]] - conv[nbr[0]]);
  84. /* scale -PI..PI to 0..num_orients - 1 */
  85. dir =
  86. num_orients * ((ang + M_PI) / (M_PI * 2.0)) + 0.4999;
  87. /* shift scale so that 0 (not 8) is straight down */
  88. dir = (3 * num_orients / 4 + dir) % num_orients;
  89. /* add to differentiate between no zc and an orientation */
  90. zc[p] = 1 + dir;
  91. break; /* quit looking at neighbors */
  92. }
  93. } /* for ni */
  94. } /* for p */
  95. }
  96. return 0;
  97. }