bazar  1.3.1
yape.cpp
Go to the documentation of this file.
1 /*
2 Copyright 2005, 2006 Computer Vision Lab,
3 Ecole Polytechnique Federale de Lausanne (EPFL), Switzerland.
4 All rights reserved.
5 
6 This file is part of BazAR.
7 
8 BazAR is free software; you can redistribute it and/or modify it under the
9 terms of the GNU General Public License as published by the Free Software
10 Foundation; either version 2 of the License, or (at your option) any later
11 version.
12 
13 BazAR is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
15 PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License along with
18 BazAR; if not, write to the Free Software Foundation, Inc., 51 Franklin
19 Street, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21 /*
22 * Author:
23 * Vincent Lepetit <[email protected]>
24 * 2004/2005
25 */
26 
27 #include <algorithm>
28 #include <iostream>
29 #include <fstream>
30 
31 using namespace std;
32 
33 #include <stdlib.h>
34 #include <math.h>
35 
36 #include <starter.h>
37 #include "yape.h"
38 
39 const unsigned int yape_bin_size = 1000;
40 const int yape_tmp_points_array_size = 10000;
41 
42 bool operator <(const keypoint &p1, const keypoint &p2)
43 {
44  return p1.score > p2.score;
45 }
46 
47 yape::yape(int _width, int _height)
48 {
49  width = _width;
50  height = _height;
51 
52  radius = 7;
53  tau = 10;
54  minimal_neighbor_number = 4;
55 
56  activate_bins();
57  set_bins_number(4, 4);
58 
59  disactivate_subpixel();
60 
61  set_minimal_neighbor_number(3);
62 
63  init_for_monoscale();
64 }
65 
67 {
68  if (Dirs) delete Dirs;
69  if (Dirs_nb) delete[] Dirs_nb;
70  if (scores) cvReleaseImage(&scores);
71  if (filtered_image) cvReleaseImage(&filtered_image);
72 }
73 
74 int yape::static_detect(IplImage * image, keypoint * points, int max_point_number, int _radius, int _tau)
75 {
76  yape * pe = new yape(image->width, image->height);
77 
78  pe->set_radius(_radius);
79  pe->set_tau(_tau);
80  int point_number = pe->detect(image, points, max_point_number);
81 
82  delete pe;
83 
84  return point_number;
85 }
86 
87 void yape::set_radius(int _radius)
88 {
89  radius = _radius;
90 }
91 
92 void yape::set_tau(int _tau)
93 {
94  tau = _tau;
95 }
96 
98 {
99  scores = cvCreateImage(cvSize(width, height), IPL_DEPTH_16S, 1);
100  filtered_image = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
101 
102  Dirs = new dir_table;
103  memset(Dirs,0,sizeof(dir_table));
104  Dirs_nb = new int[yape_max_radius];
105  memset(Dirs_nb,0,sizeof(int)*yape_max_radius);
106  for(int R = 1; R < yape_max_radius; R++)
107  precompute_directions(filtered_image, Dirs->t[R], &(Dirs_nb[R]), R);
108 }
109 
111 {
112  if (use_bins)
113  for(int i = 0; i < bin_nb_u; i++)
114  for(int j = 0; j < bin_nb_v; j++)
115  {
116  bins[i][j].clear();
117  bins[i][j].reserve(yape_bin_size);
118  }
119  else
120  {
121  tmp_points.clear();
122  tmp_points.reserve(yape_tmp_points_array_size);
123  }
124 }
125 
126 void yape::precompute_directions(IplImage * image, short * _Dirs, int * _Dirs_nb, int R)
127 {
128  int widthStep = image->widthStep;
129 
130  int i = 0;
131  int x, y;
132 
133  x = R;
134  for(y = 0; y < x; y++, i++)
135  {
136  x = int(sqrt(double(R * R - y * y)) + 0.5);
137  _Dirs[i] = short(x + widthStep * y);
138  }
139  for(x-- ; x < y && x >= 0; x--, i++)
140  {
141  y = int(sqrt(double(R * R - x * x)) + 0.5);
142  _Dirs[i] = short(x + widthStep * y);
143  }
144  for( ; -x < y; x--, i++)
145  {
146  y = int(sqrt(double(R * R - x * x)) + 0.5);
147  _Dirs[i] = short(x + widthStep * y);
148  }
149  for(y-- ; y >= 0; y--, i++)
150  {
151  x = int(-sqrt(double(R * R - y * y)) - 0.5);
152  _Dirs[i] = short(x + widthStep * y);
153  }
154  for(; y > x; y--, i++)
155  {
156  x = int(-sqrt(double(R * R - y * y)) - 0.5);
157  _Dirs[i] = short(x + widthStep * y);
158  }
159  for(x++ ; x <= 0; x++, i++)
160  {
161  y = int(-sqrt(double(R * R - x * x)) - 0.5);
162  _Dirs[i] = short(x + widthStep * y);
163  }
164  for( ; x < -y; x++, i++)
165  {
166  y = int(-sqrt(double(R * R - x * x)) - 0.5);
167  _Dirs[i] = short(x + widthStep * y);
168  }
169  for(y++ ; y < 0; y++, i++)
170  {
171  x = int(sqrt(double(R * R - y * y)) + 0.5);
172  _Dirs[i] = short(x + widthStep * y);
173  }
174 
175  *_Dirs_nb = i;
176  _Dirs[i] = _Dirs[0];
177  _Dirs[i + 1] = _Dirs[1];
178 }
179 
180 void yape::save_image_of_detected_points(char * name, IplImage * image, keypoint * points, int points_nb)
181 {
182  IplImage * color_image = mcvGrayToColor(image);
183 
184  for(int i = 0; i < points_nb; i++) {
185  int s = (int)points[i].scale;
186  float x = PyrImage::convCoordf(points[i].u, s, 0);
187  float y = PyrImage::convCoordf(points[i].v, s, 0);
188  float l = PyrImage::convCoordf(32.0f, s, 0);
189 
190  mcvCircle(color_image, int(x), int(y), (int)l, mcvRainbowColor(s % 7));
191  }
192 
193  mcvSaveImage(name, color_image);
194 }
195 
196 bool yape::double_check(IplImage * image, int x, int y, short * dirs, unsigned char dirs_nb)
197 {
198  unsigned char * I = (unsigned char *)(image->imageData + y * image->widthStep);
199  int Ip = I[x] + tau;
200  int Im = I[x] - tau;
201  int A;
202 
203  for(A = dirs_nb / 2 - 2; A <= dirs_nb / 2 + 2; A++)
204  for(int i = 0; i < dirs_nb - A; i++)
205  {
206  if (I[x+dirs[i]] > Im && I[x+dirs[i]] < Ip && I[x+dirs[i+A]] > Im && I[x+dirs[i+A]] < Ip)
207  return false;
208  }
209 
210  return true;
211 }
212 
213 #define A_INF (A < Im)
214 #define A_SUP (A > Ip)
215 #define A_NOT_INF (A >= Im)
216 #define A_NOT_SUP (A <= Ip)
217 
218 #define B0_INF (B0 < Im)
219 #define B0_SUP (B0 > Ip)
220 #define B0_NOT_INF (B0 >= Im)
221 #define B0_NOT_SUP (B0 <= Ip)
222 
223 #define B1_INF (B1 < Im)
224 #define B1_SUP (B1 > Ip)
225 #define B1_NOT_INF (B1 >= Im)
226 #define B1_NOT_SUP (B1 <= Ip)
227 
228 #define B2_INF (B2 < Im)
229 #define B2_SUP (B2 > Ip)
230 #define B2_NOT_INF (B2 >= Im)
231 #define B2_NOT_SUP (B2 <= Ip)
232 
233 #define GET_A() A = I[x+dirs[a]]
234 #define GET_B0() B0 = I[x+dirs[b]]
235 #define GET_B1() b++; B1 = I[x+dirs[b]]
236 #define GET_B2() b++; B2 = I[x+dirs[b]]
237 
238 #define GOTO_STATE(s) { score -= A + B1; state = (s); break; }
239 #define GOTO_END_NOT_AN_INTEREST_POINT { /*stats_iter[a]++;*/ Scores[x] = 0; return; }
240 #define PUT_B2_IN_B1_AND_GET_B2() B1 = B2; GET_B2()
241 
242 #define B1_NOT_INF_B2_NOT_INF 0
243 #define B1_NOT_SUP_B2_NOT_SUP 1
244 #define B1_INF_B2_INF 2
245 #define B1_SUP_B2_SUP 3
246 #define B1_INF_B2_NOT_SUP 4
247 #define B1_SUP_B2_NOT_INF 5
248 #define B1_SUP_B2_INF 6
249 #define B1_INF_B2_SUP 7
250 #define B1_EQUAL_B2_NOT_SUP 8
251 #define B1_EQUAL_B2_NOT_INF 9
252 
253 void yape::perform_one_point(const unsigned char * I, const int x, short * Scores,
254  const int Im, const int Ip,
255  const short * dirs, const unsigned char opposite, const unsigned char dirs_nb)
256 {
257  int score = 0;
258  unsigned char a = 0, b = opposite - 1;
259  int A, B0, B1, B2;
260  unsigned char state;
261 
262  // WE KNOW THAT NOT(A ~ I0 & B1 ~ I0):
263  GET_A();
264  if (A_NOT_SUP) {
265  if (A_NOT_INF) { // A ~ I0
266  GET_B0();
267  if (B0_NOT_SUP) {
269  else {
270  GET_B1();
271  if (B1_SUP) {
272  GET_B2();
273  if (B2_SUP) state = B1_SUP_B2_SUP;
274  else if (B2_INF) state = B1_SUP_B2_INF;
275  else GOTO_END_NOT_AN_INTEREST_POINT // A ~ I0, B2 ~ I0
276  }
277  else/* if (B1_INF)*/ {
278  GET_B2();
279  if (B2_SUP) state = B1_INF_B2_SUP;
280  else if (B2_INF) state = B1_INF_B2_INF;
281  else GOTO_END_NOT_AN_INTEREST_POINT // A ~ I0, B2 ~ I0
282  }
283  //else GOTO_END_NOT_AN_INTEREST_POINT // A ~ I0, B1 ~ I0
284  }
285  }
286  else { // B0 < I0
287  GET_B1();
288  if (B1_SUP) {
289  GET_B2();
290  if (B2_SUP) state = B1_SUP_B2_SUP;
291  else if (B2_INF) state = B1_SUP_B2_INF;
292  else GOTO_END_NOT_AN_INTEREST_POINT // A ~ I0, B2 ~ I0
293  }
294  else if (B1_INF) {
295  GET_B2();
296  if (B2_SUP) state = B1_INF_B2_SUP;
297  else if (B2_INF) state = B1_INF_B2_INF;
298  else GOTO_END_NOT_AN_INTEREST_POINT // A ~ I0, B2 ~ I0
299  }
300  else GOTO_END_NOT_AN_INTEREST_POINT // A ~ I0, B1 ~ I0
301  }
302  }
303  else { // A > I0
304  GET_B0();
306  GET_B1();
308  GET_B2();
310  state = B1_NOT_SUP_B2_NOT_SUP;
311  }
312  }
313  else // A < I0
314  {
315  GET_B0();
317  GET_B1();
319  GET_B2();
321  state = B1_NOT_INF_B2_NOT_INF;
322  }
323 
324  for(a = 1; a <= opposite; a++)
325  {
326  GET_A();
327 
328  switch(state)
329  {
331  if (A_SUP) {
335  }
336  if (A_INF) {
342  }
343  // A ~ I0
350 
352  if (A_INF) {
356  }
357  if (A_SUP) {
363  }
364  // A ~ I0
371 
372  case B1_INF_B2_INF:
375  if (A_INF)
376  {
379  }
380  // A ~ I0
383  GOTO_END_NOT_AN_INTEREST_POINT // A ~ I0, B2 ~ I0
384 
385  case B1_SUP_B2_SUP:
388  if (A_SUP) {
391  }
392  // A ~ I0
396 
397  case B1_INF_B2_NOT_SUP:
399  if (A_INF) {
403  }
409 
410  case B1_SUP_B2_NOT_INF:
412  if (A_SUP) {
416  }
417  // A ~ I0
423 
424  case B1_INF_B2_SUP:
428  // A ~ I0
431  GOTO_END_NOT_AN_INTEREST_POINT // A ~ I0, B2 ~ I0
432 
433  case B1_SUP_B2_INF:
437  // A ~ I0
440  GOTO_END_NOT_AN_INTEREST_POINT // A ~ I0, B2 ~ I0
441 
442  case B1_EQUAL_B2_NOT_SUP:
443  if (A_SUP) {
448  }
449  if (A_INF) {
453  }
455 
456  case B1_EQUAL_B2_NOT_INF:
457  if (A_INF) {
462  }
463  if (A_SUP) {
467  }
469 
470  default:
471  cout << "PB default" << endl;
472  } // switch(state)
473  } // for(a...)
474 
475  Scores[x] = short(score + dirs_nb * I[x]);
476 }
477 
478 int yape::detect(IplImage * image, keypoint * points, int max_point_number, IplImage * _filtered_image)
479 {
480  IplImage * used_filtered_image;
481 
482  if (_filtered_image == 0)
483  {
484  int gaussian_filter_size = 3;
485 
486  if (radius >= 5) gaussian_filter_size = 5;
487  if (radius >= 7) gaussian_filter_size = 7;
488  cvSmooth(image, filtered_image, CV_GAUSSIAN, gaussian_filter_size, gaussian_filter_size);
489 
490  used_filtered_image = filtered_image;
491  }
492  else
493  used_filtered_image = _filtered_image;
494 
495  reserve_tmp_arrays();
496 
497  raw_detect(used_filtered_image);
498 
499  get_local_maxima(image, radius, 0);
500 
501  int points_nb = pick_best_points(points, max_point_number);
502 
503  if (use_subpixel)
504  for(int i = 0; i < points_nb; i++)
505  subpix_refine(used_filtered_image, points + i);
506 
507  return points_nb;
508 }
509 
510 static unsigned mymin(unsigned a, unsigned b)
511 {
512  return (a<b ? a:b);
513 }
514 
518 int yape::pick_best_points(keypoint * points, unsigned int max_point_number)
519 {
520  if (use_bins)
521  {
522  unsigned int N = 0;
523  for(int i = 0; i < bin_nb_u; i++)
524  {
525  for(int j = 0; j < bin_nb_v; j++)
526  {
527  if (bins[i][j].size() > 0){
528  sort(bins[i][j].begin(), bins[i][j].end());
529  N += bins[i][j].size();
530  }
531  }
532  }
533 
534  N = max_point_number;
535  unsigned int N_per_bin = N / (bin_nb_u * bin_nb_v);
536  int points_nb = 0;
537  for(int i = 0; i < bin_nb_u; i++)
538  {
539  for(int j = 0; j < bin_nb_v; j++)
540  {
541  for(unsigned int k = 0; k < mymin(N_per_bin, bins[i][j].size()); k++, points_nb++)
542  points[points_nb] = bins[i][j][k];
543  }
544  }
545 
546  return points_nb;
547  }
548  else
549  if (tmp_points.size() > 0)
550  {
551  sort(tmp_points.begin(), tmp_points.end());
552 
553  int score_threshold = 0;
554 
555  int tot_pts = tmp_points.size()<max_point_number ? tmp_points.size() : max_point_number;
556 
557  int points_nb = 0;
558  for(points_nb = 0;
559  points_nb<tot_pts && tmp_points[points_nb].score>score_threshold;
560  points_nb++)
561  points[points_nb] = tmp_points[points_nb];
562 
563  return points_nb;
564  }
565 
566  return 0;
567 }
568 
573 void yape::raw_detect(IplImage *im) {
574  unsigned int R = radius;
575  short * dirs = Dirs->t[R];
576  unsigned char dirs_nb = (unsigned char)(Dirs_nb[R]);
577  unsigned char opposite = dirs_nb / 2;
578 
579  CvRect roi = cvGetImageROI(im);
580 
581  if (roi.x < int(R+1)) roi.x = R+1;
582  if (roi.y < int(R+1)) roi.y = R+1;
583  if ((roi.x + roi.width) > int(im->width-R-2)) roi.width = im->width - R - roi.x - 2;
584  if ((roi.y + roi.height) > int(im->height-R-2)) roi.height = im->height - R - roi.y - 2;
585 
586  unsigned int xend = roi.x + roi.width;
587  unsigned int yend = roi.y + roi.height;
588 
589  for(unsigned int y = roi.y; y < yend; y++)
590  {
591  unsigned char * I = (unsigned char *)(im->imageData + y*im->widthStep);
592  short * Scores = (short *)(scores->imageData + y*scores->widthStep);
593 
594  for(unsigned int x = roi.x; x < xend; x++)
595  {
596  int Ip = I[x] + tau;
597  int Im = I[x] - tau;
598 
599  if (Im<I[x+R] && I[x+R]<Ip && Im<I[x-R] && I[x-R]<Ip)
600  Scores[x] = 0;
601  else
602  perform_one_point(I, x, Scores, Im, Ip, dirs, opposite, dirs_nb);
603  }
604  }
605 }
606 
607 #define Dx 1
608 #define Dy next_line
609 
610 #define W (-Dx)
611 #define E (+Dx)
612 #define N (-Dy)
613 #define S (+Dy)
614 
615 #define MINIMAL_SCORE (0 / radius)
616 
617 inline bool yape::third_check(const short * Sb, const int next_line)
618 {
619  int n = 0;
620 
621  if (Sb[E] != 0) n++;
622  if (Sb[W] != 0) n++;
623  if (Sb[S] != 0) n++;
624  if (Sb[S+E] != 0) n++;
625  if (Sb[S+W] != 0) n++;
626  if (Sb[N] != 0) n++;
627  if (Sb[N+E] != 0) n++;
628  if (Sb[N+W] != 0) n++;
629 
630  return n >= minimal_neighbor_number;
631 }
632 
633 // Test if a pixel is a local maxima in a given neighborhood.
634 static inline bool is_local_maxima(const short *p, int neighborhood, const IplImage *scores)
635 {
636 #ifdef CONSIDER_ABS_VALUE_ONLY
637  unsigned v = abs(p[0]);
638  if (v < 5) return false;
639 
640  int step = scores->widthStep / 2;
641 
642  p -= step*neighborhood;
643  for (int y= -neighborhood; y<=neighborhood; ++y) {
644  for (int x= -neighborhood; x<=neighborhood; ++x) {
645  if (abs(p[x]) > v)
646  return false;
647  }
648  p += step;
649  }
650  return true;
651 #else
652  int v = p[0];
653 
654  int step = scores->widthStep / 2;
655 
656  if (v > 0) {
657  p -= step*neighborhood;
658  for (int y= -neighborhood; y<=neighborhood; ++y) {
659  for (int x= -neighborhood; x<=neighborhood; ++x) {
660  if (p[x] > v)
661  return false;
662  }
663  p += step;
664  }
665  } else {
666  p -= step*neighborhood;
667  for (int y= -neighborhood; y<=neighborhood; ++y) {
668  for (int x= -neighborhood; x<=neighborhood; ++x) {
669  if (p[x] < v)
670  return false;
671  }
672  p += step;
673  }
674  }
675 
676  return true;
677 
678 #endif
679 }
680 
684 int yape::get_local_maxima(IplImage * image, int R, float scale /*, keypoint * points, int max_number_of_points*/)
685 {
686  int nbpts=0;
687 
688  const int next_line = scores->widthStep / sizeof(short);
689  int h = scores->height;
690  int w = scores->width;
691 
692  CvRect roi = cvGetImageROI(image);
693 
694  if (roi.x < int(R+1)) roi.x = R+1;
695  if (roi.y < int(R+1)) roi.y = R+1;
696  if ((roi.x + roi.width) > int(scores->width-R-2)) roi.width = scores->width - R - roi.x - 2;
697  if ((roi.y + roi.height) > int(scores->height-R-2)) roi.height = scores->height - R - roi.y - 2;
698 
699  unsigned int xend = roi.x + roi.width;
700  unsigned int yend = roi.y + roi.height;
701 
702  for(unsigned int y = roi.y; y < yend; y++)
703  {
704  short * Scores = (short *)(scores->imageData + y * scores->widthStep);
705 
706  for(unsigned int x = roi.x; x < xend; x++)
707  {
708  short * Sb = Scores + x;
709 
710  // skip 0 score pixels
711  if (abs(Sb[0]) < 5)
712  ++x; // if this pixel is 0, the next one will not be good enough. Skip it.
713  else
714  {
715  if (third_check(Sb, next_line) && is_local_maxima(Sb, R, scores))
716  {
717  keypoint p;
718  p.u = float(x);
719  p.v = float(y);
720  p.scale = scale;
721  p.score = float(abs(Sb[0]));
722 
723  if (use_bins)
724  {
725  int bin_u_index = (bin_nb_u * x) / w;
726  int bin_v_index = (bin_nb_v * y) / h;
727 
728  if (bin_u_index >= bin_nb_u)
729  bin_u_index = bin_nb_u - 1;
730  if (bin_v_index >= bin_nb_v)
731  bin_v_index = bin_nb_v - 1;
732 
733  if (bins[bin_u_index][bin_v_index].size() < yape_bin_size)
734  bins[bin_u_index][bin_v_index].push_back(p);
735  }
736  else
737  tmp_points.push_back(p);
738 
739  nbpts++;
740  x += R-1;
741  }
742  }
743  }
744  }
745  return nbpts;
746 }
747 
749 // Sub-pixel / sub-scale accuracy.
751 
752 static float fit_quadratic_2x2(float x[2], float L[3][3])
753 {
754  float H[2][2];
755  float b[2];
756 
757  b[0] = -(L[1][2] - L[1][0]) / 2.0f;
758  b[1] = -(L[2][1] - L[0][1]) / 2.0f;
759 
760  H[0][0] = L[1][0] - 2.0f * L[1][1] + L[1][2];
761  H[1][1] = L[0][1] - 2.0f * L[1][1] + L[2][1];
762  H[0][1] = H[1][0] = (L[0][0] - L[0][2] - L[2][0] + L[2][2]) / 4.0f;
763 
764  float t4 = 1/(H[0][0]*H[1][1]-H[0][1]*H[1][0]);
765  x[0] = H[1][1]*t4*b[0]-H[0][1]*t4*b[1];
766  x[1] = -H[1][0]*t4*b[0]+H[0][0]*t4*b[1];
767 
768  return 0.5f * (b[0] * x[0] + b[1] * x[1]);
769 }
770 
771 void yape::subpix_refine(IplImage *im, keypoint *p)
772 {
773  float L[3][3];
774 
775  int px = (int) p->u;
776  int py = (int) p->v;
777  int dirs_nb = Dirs_nb[radius];
778  short * dirs = Dirs->t[radius];
779 
780  if ((px<= radius) || (px >= (scores->width-radius)) || (py <= radius) || (py >= (scores->height-radius)))
781  return;
782 
783  unsigned char * I = (unsigned char *) (im->imageData + py*im->widthStep) + px;
784  short * s = (short *) (scores->imageData + py*scores->widthStep) + px;
785  int line = scores->widthStep/sizeof(short);
786 
787  for (int y=0; y<3; ++y) {
788  int offset = (y-1)*line - 1;
789  for (int x=0; x<3; ++x) {
790  if (s[ offset + x]==0) {
791  // Compute Laplacian
792  int score = 0;
793  for (int d=0; d<dirs_nb; ++d)
794  score += I[offset + x + dirs[d]];
795  L[y][x] = -float(score - dirs_nb*(int)I[offset + x]);
796  } else {
797  L[y][x] = (float)s[ offset + x];
798  }
799  }
800  }
801 
802  float delta[2];
803  p->score += fit_quadratic_2x2(delta, L);
804 
805  if ((delta[0] >= -1) && (delta[0] <= 1))
806  p->u += delta[0];
807  else
808  p->u+=0.5f;
809  if ((delta[1] >= -1) && (delta[1] <= 1))
810  p->v += delta[1];
811  else
812  p->v+=0.5f;
813 }
814 
816 // PyrYape implementation
818 
823 pyr_yape::pyr_yape(int w, int h, int nbLev)
824 : yape (w,h)
825 {
826  internal_pim = 0;
827  pscores = new PyrImage(scores, nbLev);
828  pDirs[0] = Dirs;
829  pDirs_nb[0] = Dirs_nb;
830  equalize = false;
831 
832  PyrImage pim(cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1),nbLev);
833 
834  for (int i=1; i<nbLev; i++) {
835  pDirs[i] = new dir_table;
836  pDirs_nb[i] = new int[yape_max_radius];
837  for(int R = 1; R < yape_max_radius; R++)
838  precompute_directions(pim[i], pDirs[i]->t[R], &(pDirs_nb[i][R]), R);
839  }
840 }
841 
843 {
844  if (internal_pim) delete internal_pim;
845 
846  for (int i=0; i<pscores->nbLev; i++) {
847  delete pDirs[i];
848  delete[] pDirs_nb[i];
849  }
850  Dirs=0;
851  Dirs_nb=0;
852  delete pscores;
853  pscores = 0;
854  scores = 0;
855 }
856 
858 {
859  scores = pscores->images[l];
860  Dirs = pDirs[l];
861  Dirs_nb = pDirs_nb[l];
862 }
863 
867 int pyr_yape::detect(PyrImage *image, keypoint *points, int max_point_number)
868 {
870 
871  for (int i=image->nbLev-1; i>=0; --i)
872  {
873  select_level(i);
874  raw_detect(image->images[i]);
875  get_local_maxima(image->images[i], radius, float(i));
876  }
877 
878  int n = pick_best_points(points, max_point_number);
879  for (int i = 0; i < n; i++) {
880  int l =(int)points[i].scale;
881  select_level(l);
882  subpix_refine(image->images[l], points + i);
883  }
884 
885  return n;
886 }
887 
903 int pyr_yape::pyramidBlurDetect(IplImage *im, keypoint *points, int max_point_number, PyrImage *caller_pim)
904 {
905  assert(im->nChannels == 1);
906 
907  PyrImage *pim;
908 
909  if (caller_pim == 0)
910  {
911  if (internal_pim && ((internal_pim->images[0]->width != im->width)
912  || (internal_pim->images[0]->height != im->height)))
913  {
914  delete internal_pim;
915  internal_pim = 0;
916  }
917 
918  if (internal_pim == 0)
919  internal_pim = new PyrImage(cvCreateImage(cvGetSize(im), IPL_DEPTH_8U, 1), pscores->nbLev);
920 
921  pim = internal_pim;
922  }
923  else
924  {
925  pim = caller_pim;
926  assert (im->width == caller_pim->images[0]->width);
927  }
928 
929  int gaussian_filter_size = 3;
930  if (radius >= 5) gaussian_filter_size = 5;
931  if (radius >= 7) gaussian_filter_size = 7;
932  cvSmooth(im, pim->images[0], CV_GAUSSIAN, gaussian_filter_size, gaussian_filter_size);
933 
934  pim->build();
935 
936  return detect(pim, points, max_point_number);
937 }
938 
939 void pyr_yape::save_image_of_detected_points(char * name, IplImage * image, keypoint * points, int points_nb)
940 {
941  IplImage * point_image = mcvGrayToColor(image);
942  for(int i = 0; i < points_nb; i++)
943  mcvCircle(point_image,
944  (int)PyrImage::convCoordf(points[i].u, (int)points[i].scale, 0),
945  (int)PyrImage::convCoordf(points[i].v, (int)points[i].scale, 0),
946  PyrImage::convCoord(2 * radius, (int)points[i].scale, 0), mcvRainbowColor((int)points[i].scale), 1);
947  mcvSaveImage(name, point_image);
948  cvReleaseImage(&point_image);
949 }
950 
951 void pyr_yape::stat_points(keypoint *points, int nb_pts)
952 {
953  int *histogram = new int[pscores->nbLev];
954 
955  for (int l=0; l< pscores->nbLev; ++l) histogram[l]=0;
956 
957  for (int i=0; i<nb_pts; ++i)
958  histogram[(int)(points[i].scale)]++;
959 
960  for (int l=0; l< pscores->nbLev; ++l)
961  cout << "Level " << l << ": " << histogram[l] << " keypoints ("
962  << 100.0f * (float)histogram[l]/(float)nb_pts << "%)\n";
963 
964  delete[] histogram;
965 }
966