Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
CornerDetectorSusan.cpp
1 /*
2 This file is distributed as part of the BIAS library (Basic ImageAlgorithmS)
3 but it has not been developed by the authors of BIAS.
4 
5 For copyright, author and license information see below.
6 */
7 
8 
9 /* {{{ Copyright etc. */
10 
11 /**********************************************************************\
12 
13  SUSAN Version 2l by Stephen Smith
14  Oxford Centre for Functional Magnetic Resonance Imaging of the Brain,
15  Department of Clinical Neurology, Oxford University, Oxford, UK
16  (Previously in Computer Vision and Image Processing Group - now
17  Computer Vision and Electro Optics Group - DERA Chertsey, UK)
18  Email: steve@fmrib.ox.ac.uk
19  WWW: http://www.fmrib.ox.ac.uk/~steve
20 
21  (C) Crown Copyright (1995-1999), Defence Evaluation and Research Agency,
22  Farnborough, Hampshire, GU14 6TD, UK
23  DERA WWW site:
24  http://www.dera.gov.uk/
25  DERA Computer Vision and Electro Optics Group WWW site:
26  http://www.dera.gov.uk/imageprocessing/dera/group_home.html
27  DERA Computer Vision and Electro Optics Group point of contact:
28  Dr. John Savage, jtsavage@dera.gov.uk, +44 1344 633203
29 
30  A UK patent has been granted: "Method for digitally processing
31  images to determine the position of edges and/or corners therein for
32  guidance of unmanned vehicle", UK Patent 2272285. Proprietor:
33  Secretary of State for Defence, UK. 15 January 1997
34 
35  This code is issued for research purposes only and remains the
36  property of the UK Secretary of State for Defence. This code must
37  not be passed on without this header information being kept
38  intact. This code must not be sold.
39 
40 \**********************************************************************/
41 
42 /* }}} */
43 /* {{{ Readme First */
44 
45 /**********************************************************************\
46 
47  SUSAN Version 2l
48  SUSAN = Smallest Univalue Segment Assimilating Nucleus
49 
50  Email: steve@fmrib.ox.ac.uk
51  WWW: http://www.fmrib.ox.ac.uk/~steve
52 
53  Related paper:
54  @article{Smith97,
55  author = "Smith, S.M. and Brady, J.M.",
56  title = "{SUSAN} - A New Approach to Low Level Image Processing",
57  journal = "Int. Journal of Computer Vision",
58  pages = "45--78",
59  volume = "23",
60  number = "1",
61  month = "May",
62  year = 1997}
63 
64  To be registered for automatic (bug) updates of SUSAN, send an email.
65 
66  Compile with:
67  gcc -O4 -o susan susan2l.c -lm
68 
69  See following section for different machine information. Please
70  report any bugs (and fixes). There are a few optional changes that
71  can be made in the "defines" section which follows shortly.
72 
73  Usage: type "susan" to get usage. Only PGM format files can be input
74  and output. Utilities such as the netpbm package and XV can be used
75  to convert to and from other formats. Any size of image can be
76  processed.
77 
78  This code is written using an emacs folding mode, making moving
79  around the different sections very easy. This is why there are
80  various marks within comments and why comments are indented.
81 
82 
83  SUSAN QUICK:
84 
85  This version of the SUSAN corner finder does not do all the
86  false-corner suppression and thus is faster and produced some false
87  positives, particularly on strong edges. However, because there are
88  less stages involving thresholds etc., the corners that are
89  correctly reported are usually more stable than those reported with
90  the full algorithm. Thus I recommend at least TRYING this algorithm
91  for applications where stability is important, e.g., tracking.
92 
93  THRESHOLDS:
94 
95  There are two thresholds which can be set at run-time. These are the
96  brightness threshold (t) and the distance threshold (d).
97 
98  SPATIAL CONTROL: d
99 
100  In SUSAN smoothing d controls the size of the Gaussian mask; its
101  default is 4.0. Increasing d gives more smoothing. In edge finding,
102  a fixed flat mask is used, either 37 pixels arranged in a "circle"
103  (default), or a 3 by 3 mask which gives finer detail. In corner
104  finding, only the larger 37 pixel mask is used; d is not
105  variable. In smoothing, the flat 3 by 3 mask can be used instead of
106  a larger Gaussian mask; this gives low smoothing and fast operation.
107 
108  BRIGHTNESS CONTROL: t
109 
110  In all three algorithms, t can be varied (default=20); this is the
111  main threshold to be varied. It determines the maximum difference in
112  greylevels between two pixels which allows them to be considered
113  part of the same "region" in the image. Thus it can be reduced to
114  give more edges or corners, i.e. to be more sensitive, and vice
115  versa. In smoothing, reducing t gives less smoothing, and vice
116  versa. Set t=10 for the test image available from the SUSAN web
117  page.
118 
119  ITERATIONS:
120 
121  With SUSAN smoothing, more smoothing can also be obtained by
122  iterating the algorithm several times. This has a different effect
123  from varying d or t.
124 
125  FIXED MASKS:
126 
127  37 pixel mask: ooo 3 by 3 mask: ooo
128  ooooo ooo
129  ooooooo ooo
130  ooooooo
131  ooooooo
132  ooooo
133  ooo
134 
135  CORNER ATTRIBUTES dx, dy and I
136  (Only read this if you are interested in the C implementation or in
137  using corner attributes, e.g., for corner matching)
138 
139  Corners reported in the corner list have attributes associated with
140  them as well as positions. This is useful, for example, when
141  attempting to match corners from one image to another, as these
142  attributes can often be fairly unchanged between images. The
143  attributes are dx, dy and I. I is the value of image brightness at
144  the position of the corner. In the case of susan_corners_quick, dx
145  and dy are the first order derivatives (differentials) of the image
146  brightness in the x and y directions respectively, at the position
147  of the corner. In the case of normal susan corner finding, dx and dy
148  are scaled versions of the position of the centre of gravity of the
149  USAN with respect to the centre pixel (nucleus).
150 
151  BRIGHTNESS FUNCTION LUT IMPLEMENTATION:
152  (Only read this if you are interested in the C implementation)
153 
154  The SUSAN brightness function is implemented as a LUT
155  (Look-Up-Table) for speed. The resulting pointer-based code is a
156  little hard to follow, so here is a brief explanation. In
157  setup_brightness_lut() the LUT is setup. This mallocs enough space
158  for *bp and then repositions the pointer to the centre of the
159  malloced space. The SUSAN function e^-(x^6) or e^-(x^2) is
160  calculated and converted to a uchar in the range 0-100, for all
161  possible image brightness differences (including negative
162  ones). Thus bp[23] is the output for a brightness difference of 23
163  greylevels. In the SUSAN algorithms this LUT is used as follows:
164 
165  p=in + (i-3)*x_size + j - 1;
166  p points to the first image pixel in the circular mask surrounding
167  point (x,y).
168 
169  cp=bp + in[i*x_size+j];
170  cp points to a position in the LUT corresponding to the brightness
171  of the centre pixel (x,y).
172 
173  now for every pixel within the mask surrounding (x,y),
174  n+=*(cp-*p++);
175  the brightness difference function is found by moving the cp pointer
176  down by an amount equal to the value of the pixel pointed to by p,
177  thus subtracting the two brightness values and performing the
178  exponential function. This value is added to n, the running USAN
179  area.
180 
181  in SUSAN smoothing, the variable height mask is implemented by
182  multiplying the above by the moving mask pointer, reset for each new
183  centre pixel.
184  tmp = *dpt++ * *(cp-brightness);
185 
186 \**********************************************************************/
187 
188 /* }}} */
189 
190 #include "CornerDetectorSusan.hh"
191 
192 #define FTOI(a) ( (a) < 0 ? ((int)(a-0.5)) : ((int)(a+0.5)) )
193 
194 
195 
196 using namespace BIAS;
197 using namespace std;
198 
199 //////////////////////////////////////////////////////////////////////////
200 // implementation
201 //////////////////////////////////////////////////////////////////////////
202 
203 
204 template <class StorageType>
207  : CornerDetectorBase<StorageType>()
208 {
209  _cgx=_cgy=_r=NULL;
210  _bp=NULL;
212  _Threshold = DEFAULT_THRESH;
213  _Quick= DEFAULT_QUICK;
214  this->_MaxNum = CORNERDETECTOR_SUSAN_MAXNUM_DEFAULT;
215 }
216 
217 template <class StorageType>
219 {
220  if (_cgx!=NULL) delete[] _cgx;
221  if (_cgy!=NULL) delete[] _cgy;
222  if (_r!=NULL) delete[] _r;
223  if (_bp!=NULL) delete[] (_bp-258);
224 }
225 
226 template <class StorageType>
228 Detect(const Image<StorageType>& image, CORNER_LIST corner_list, int& num)
229 {
230 #ifdef BIAS_DEBUG
231  if ( (image.GetChannelCount()!=1) || (image.IsEmpty()) ) {
232  BIASERR("Susan: Can only detect corners on grey value images");
233  return -1;
234  }
235 #endif
236  int x_size = image.GetWidth();
237  int y_size = image.GetHeight();
238  if (_susansize<x_size*y_size) {
239  _SusanReAllocMem(x_size, y_size);
240  }
241  const StorageType *in = image.GetImageData();
242 
243  if (_susanthresh!=_Threshold)
244  _setup_brightness_lut(_Threshold, 6);
245  if (_Quick){
246  num = _susan_corners_quick(in, _r, _bp, corner_list,
247  x_size, y_size);
248  } else {
249  num = _susan_corners(in, _r, _bp, corner_list, x_size,
250  y_size);
251  }
252  BIASDOUT(D_CD_SUSAN,"Susan found "<< num << " corners ");
253  return (num>0)?0:-1;
254 }
255 
256 template <class StorageType>
259  CORNER_LIST corner_list, int& num)
260 {
261 #ifdef BIAS_DEBUG
262  if ( (image.GetChannelCount()!=1) || (image.IsEmpty()) ) {
263  BIASERR("Susan: Can only detect corners on grey value images");
264  return -1;
265  }
266 #endif
267  int x_size = image.GetWidth();
268  int y_size = image.GetHeight();
269  if (_susansize<x_size*y_size) {
270  _SusanReAllocMem(x_size, y_size);
271  }
272  const StorageType *in = image.GetImageData();
273  const StorageType *roid = roi.GetImageData();
274 
275  if (_susanthresh!=_Threshold)
276  _setup_brightness_lut(_Threshold, 6);
277  if (_Quick){
278  num = _susan_corners_quick(in, _r, _bp, corner_list,
279  x_size, y_size);
280  } else {
281  num = _susan_corners(in, _r, _bp, corner_list, x_size,
282  y_size, roid);
283  }
284  BIASDOUT(D_CD_SUSAN,"Susan found "<< num << " corners ");
285  return (num>0)?0:-1;
286 }
287 
288 template <class StorageType>
290 Detect(const Image<StorageType>& image, vector<HomgPoint2D>& pvec,
291  vector<float>& quality)
292 {
293 #ifdef BIAS_DEBUG
294  if ( (image.GetChannelCount()!=1) || (image.IsEmpty()) ) {
295  BIASERR("Susan: Can only detect corners on grey value images");
296  return -1;
297  }
298 #endif
299  int x_size = image.GetWidth();
300  int y_size = image.GetHeight();
301  if (_susansize<x_size*y_size) {
302  _SusanReAllocMem(x_size, y_size);
303  }
304  const StorageType *in = image.GetImageData();
305 
306  HomgPoint2D p;
307  int num;
308 
309  pvec.clear();
310  quality.clear();
311 
312  CORNER_LIST corner_list;
313 
314  if (_susanthresh!=_Threshold)
315  _setup_brightness_lut(_Threshold, 6);
316  if (_Quick)
317  num = _susan_corners_quick(in, _r, _bp, corner_list,
318  x_size, y_size);
319  else
320  num = _susan_corners(in, _r, _bp, corner_list,
321  x_size, y_size);
322  int n=0;
323  quality.resize(num+1);
324  pvec.resize(num+1);
325  while(corner_list[n].info != 7){
326  pvec[n].Set((double)corner_list[n].x, (double)corner_list[n].y);
327  n++;
328  if (_Quick){
329  /* In the case of susan_corners_quick, dx
330  and dy are the first order derivatives (differentials) of the image
331  brightness in the x and y directions respectively, at the position
332  of the corner. */
333  quality[n]=((float)fabs((float)corner_list[n].dx*corner_list[n].dy)
334  /65025.0f);
335  // cerr << (float)fabs(corner_list[n].dx*corner_list[n].dy)/65025.0 << endl;
336  } else {
337  /* In the case of normal susan corner finding, dx and dy
338  are scaled versions of the position of the centre of gravity of the
339  USAN with respect to the centre pixel (nucleus). */
340  quality[n]=0.0;
341  //cerr << corner_list[n].dx << " " << corner_list[n].dy << endl;
342  }
343  }
344  BIASDOUT(D_CD_SUSAN,"Susan found "<< n << " corners ");
345  return 0;
346 }
347 
348 
349 
350 template <class StorageType>
352 _int_to_uchar(const int *r, StorageType *in, int size)
353 {
354  int i,
355  max_r=r[0],
356  min_r=r[0];
357 
358  for (i=0; i<size; i++)
359  {
360  if ( r[i] > max_r )
361  max_r=r[i];
362  if ( r[i] < min_r )
363  min_r=r[i];
364  }
365 
366  /*printf("min=%d max=%d\n",min_r,max_r);*/
367 
368  max_r-=min_r;
369 
370  for (i=0; i<size; i++)
371  in[i] = (StorageType)((int)((int)(r[i]-min_r)*255)/max_r);
372 }
373 
374 
375 template <class StorageType>
377 _setup_brightness_lut(int thresh, int form)
378 {
379  int k;
380  float temp;
381 
382  _susanthresh=thresh;
383  if (_bp==NULL){
384  _bp=new StorageType[516];
385  _bp+=258;
386  }
387 
388 
389  for(k=-256;k<257;k++)
390  {
391  temp=((float)k)/((float)thresh);
392  temp=temp*temp;
393  if (form==6)
394  temp=temp*temp*temp;
395  temp=100.0f*exp(-temp);
396  *(_bp+k)= (StorageType)temp;
397  }
398 }
399 
400 template <class StorageType>
402 _susan_corners(const StorageType *in, int *r, StorageType *bp,
403  CORNER_LIST corner_list, int x_size, int y_size)
404 {
405  const int max_no((this->_MaxNum>0)? (this->_MaxNum):INT_MAX);
406  int n,x,y,sq,xx,yy,
407  i,j,*cgx,*cgy;
408  float divide;
409  StorageType c;
410  const StorageType *p,*cp;
411 
412  memset (r,0,x_size * y_size * sizeof(int));
413 
414  cgx=new int[x_size*y_size];
415  cgy=new int[x_size*y_size];
416 
417  for (i=5;i<y_size-5;i++)
418  for (j=5;j<x_size-5;j++) {
419  n=100;
420  p=in + (i-3)*x_size + j - 1;
421  cp=bp + in[i*x_size+j];
422 
423  n+=*(cp-*p++);
424  n+=*(cp-*p++);
425  n+=*(cp-*p);
426  p+=x_size-3;
427 
428  n+=*(cp-*p++);
429  n+=*(cp-*p++);
430  n+=*(cp-*p++);
431  n+=*(cp-*p++);
432  n+=*(cp-*p);
433  p+=x_size-5;
434 
435  n+=*(cp-*p++);
436  n+=*(cp-*p++);
437  n+=*(cp-*p++);
438  n+=*(cp-*p++);
439  n+=*(cp-*p++);
440  n+=*(cp-*p++);
441  n+=*(cp-*p);
442  p+=x_size-6;
443 
444  n+=*(cp-*p++);
445  n+=*(cp-*p++);
446  n+=*(cp-*p);
447  if (n<max_no){ /* do this test early and often ONLY to save wasted computation */
448  p+=2;
449  n+=*(cp-*p++);
450  if (n<max_no){
451  n+=*(cp-*p++);
452  if (n<max_no){
453  n+=*(cp-*p);
454  if (n<max_no){
455  p+=x_size-6;
456 
457  n+=*(cp-*p++);
458  if (n<max_no){
459  n+=*(cp-*p++);
460  if (n<max_no){
461  n+=*(cp-*p++);
462  if (n<max_no){
463  n+=*(cp-*p++);
464  if (n<max_no){
465  n+=*(cp-*p++);
466  if (n<max_no){
467  n+=*(cp-*p++);
468  if (n<max_no){
469  n+=*(cp-*p);
470  if (n<max_no){
471  p+=x_size-5;
472 
473  n+=*(cp-*p++);
474  if (n<max_no){
475  n+=*(cp-*p++);
476  if (n<max_no){
477  n+=*(cp-*p++);
478  if (n<max_no){
479  n+=*(cp-*p++);
480  if (n<max_no){
481  n+=*(cp-*p);
482  if (n<max_no){
483  p+=x_size-3;
484 
485  n+=*(cp-*p++);
486  if (n<max_no){
487  n+=*(cp-*p++);
488  if (n<max_no){
489  n+=*(cp-*p);
490 
491  if (n<max_no)
492  {
493  x=0;y=0;
494  p=in + (i-3)*x_size + j - 1;
495 
496  c=*(cp-*p++);x-=c;y-=3*c;
497  c=*(cp-*p++);y-=3*c;
498  c=*(cp-*p);x+=c;y-=3*c;
499  p+=x_size-3;
500 
501  c=*(cp-*p++);x-=2*c;y-=2*c;
502  c=*(cp-*p++);x-=c;y-=2*c;
503  c=*(cp-*p++);y-=2*c;
504  c=*(cp-*p++);x+=c;y-=2*c;
505  c=*(cp-*p);x+=2*c;y-=2*c;
506  p+=x_size-5;
507 
508  c=*(cp-*p++);x-=3*c;y-=c;
509  c=*(cp-*p++);x-=2*c;y-=c;
510  c=*(cp-*p++);x-=c;y-=c;
511  c=*(cp-*p++);y-=c;
512  c=*(cp-*p++);x+=c;y-=c;
513  c=*(cp-*p++);x+=2*c;y-=c;
514  c=*(cp-*p);x+=3*c;y-=c;
515  p+=x_size-6;
516 
517  c=*(cp-*p++);x-=3*c;
518  c=*(cp-*p++);x-=2*c;
519  c=*(cp-*p);x-=c;
520  p+=2;
521  c=*(cp-*p++);x+=c;
522  c=*(cp-*p++);x+=2*c;
523  c=*(cp-*p);x+=3*c;
524  p+=x_size-6;
525 
526  c=*(cp-*p++);x-=3*c;y+=c;
527  c=*(cp-*p++);x-=2*c;y+=c;
528  c=*(cp-*p++);x-=c;y+=c;
529  c=*(cp-*p++);y+=c;
530  c=*(cp-*p++);x+=c;y+=c;
531  c=*(cp-*p++);x+=2*c;y+=c;
532  c=*(cp-*p);x+=3*c;y+=c;
533  p+=x_size-5;
534 
535  c=*(cp-*p++);x-=2*c;y+=2*c;
536  c=*(cp-*p++);x-=c;y+=2*c;
537  c=*(cp-*p++);y+=2*c;
538  c=*(cp-*p++);x+=c;y+=2*c;
539  c=*(cp-*p);x+=2*c;y+=2*c;
540  p+=x_size-3;
541 
542  c=*(cp-*p++);x-=c;y+=3*c;
543  c=*(cp-*p++);y+=3*c;
544  c=*(cp-*p);x+=c;y+=3*c;
545 
546  xx=x*x;
547  yy=y*y;
548  sq=xx+yy;
549  if ( sq > ((n*n)/2) )
550  {
551  if(yy<xx) {
552  divide=(float)y/(float)abs(x);
553  sq=abs(x)/x;
554  sq=*(cp-in[(i+FTOI(divide))*x_size+j+sq]) +
555  *(cp-in[(i+FTOI(2*divide))*x_size+j+2*sq]) +
556  *(cp-in[(i+FTOI(3*divide))*x_size+j+3*sq]);}
557  else {
558  divide=(float)x/(float)abs(y);
559  sq=abs(y)/y;
560  sq=*(cp-in[(i+sq)*x_size+j+FTOI(divide)]) +
561  *(cp-in[(i+2*sq)*x_size+j+FTOI(2*divide)]) +
562  *(cp-in[(i+3*sq)*x_size+j+FTOI(3*divide)]);}
563 
564  if(sq>290){
565  r[i*x_size+j] = max_no-n;
566  cgx[i*x_size+j] = (51*x)/n;
567  cgy[i*x_size+j] = (51*y)/n;}
568  }
569  }
570  }}}}}}}}}}}}}}}}}}}
571 
572  /* to locate the local maxima */
573  n=0;
574  for (i=5;i<y_size-5;i++)
575  for (j=5;j<x_size-5;j++) {
576  x = r[i*x_size+j];
577  if (x>0) {
578  /* 5x5 mask */
579 #ifdef FIVE_SUPP
580  if (
581  (x>r[(i-1)*x_size+j+2]) &&
582  (x>r[(i )*x_size+j+1]) &&
583  (x>r[(i )*x_size+j+2]) &&
584  (x>r[(i+1)*x_size+j-1]) &&
585  (x>r[(i+1)*x_size+j ]) &&
586  (x>r[(i+1)*x_size+j+1]) &&
587  (x>r[(i+1)*x_size+j+2]) &&
588  (x>r[(i+2)*x_size+j-2]) &&
589  (x>r[(i+2)*x_size+j-1]) &&
590  (x>r[(i+2)*x_size+j ]) &&
591  (x>r[(i+2)*x_size+j+1]) &&
592  (x>r[(i+2)*x_size+j+2]) &&
593  (x>=r[(i-2)*x_size+j-2]) &&
594  (x>=r[(i-2)*x_size+j-1]) &&
595  (x>=r[(i-2)*x_size+j ]) &&
596  (x>=r[(i-2)*x_size+j+1]) &&
597  (x>=r[(i-2)*x_size+j+2]) &&
598  (x>=r[(i-1)*x_size+j-2]) &&
599  (x>=r[(i-1)*x_size+j-1]) &&
600  (x>=r[(i-1)*x_size+j ]) &&
601  (x>=r[(i-1)*x_size+j+1]) &&
602  (x>=r[(i )*x_size+j-2]) &&
603  (x>=r[(i )*x_size+j-1]) &&
604  (x>=r[(i+1)*x_size+j-2]) )
605 #endif
606 #ifdef SEVEN_SUPP
607  if (
608  (x>r[(i-3)*x_size+j-3]) &&
609  (x>r[(i-3)*x_size+j-2]) &&
610  (x>r[(i-3)*x_size+j-1]) &&
611  (x>r[(i-3)*x_size+j ]) &&
612  (x>r[(i-3)*x_size+j+1]) &&
613  (x>r[(i-3)*x_size+j+2]) &&
614  (x>r[(i-3)*x_size+j+3]) &&
615 
616  (x>r[(i-2)*x_size+j-3]) &&
617  (x>r[(i-2)*x_size+j-2]) &&
618  (x>r[(i-2)*x_size+j-1]) &&
619  (x>r[(i-2)*x_size+j ]) &&
620  (x>r[(i-2)*x_size+j+1]) &&
621  (x>r[(i-2)*x_size+j+2]) &&
622  (x>r[(i-2)*x_size+j+3]) &&
623 
624  (x>r[(i-1)*x_size+j-3]) &&
625  (x>r[(i-1)*x_size+j-2]) &&
626  (x>r[(i-1)*x_size+j-1]) &&
627  (x>r[(i-1)*x_size+j ]) &&
628  (x>r[(i-1)*x_size+j+1]) &&
629  (x>r[(i-1)*x_size+j+2]) &&
630  (x>r[(i-1)*x_size+j+3]) &&
631 
632  (x>r[(i)*x_size+j-3]) &&
633  (x>r[(i)*x_size+j-2]) &&
634  (x>r[(i)*x_size+j-1]) &&
635  (x>=r[(i)*x_size+j+1]) &&
636  (x>=r[(i)*x_size+j+2]) &&
637  (x>=r[(i)*x_size+j+3]) &&
638 
639  (x>=r[(i+1)*x_size+j-3]) &&
640  (x>=r[(i+1)*x_size+j-2]) &&
641  (x>=r[(i+1)*x_size+j-1]) &&
642  (x>=r[(i+1)*x_size+j ]) &&
643  (x>=r[(i+1)*x_size+j+1]) &&
644  (x>=r[(i+1)*x_size+j+2]) &&
645  (x>=r[(i+1)*x_size+j+3]) &&
646 
647  (x>=r[(i+2)*x_size+j-3]) &&
648  (x>=r[(i+2)*x_size+j-2]) &&
649  (x>=r[(i+2)*x_size+j-1]) &&
650  (x>=r[(i+2)*x_size+j ]) &&
651  (x>=r[(i+2)*x_size+j+1]) &&
652  (x>=r[(i+2)*x_size+j+2]) &&
653  (x>=r[(i+2)*x_size+j+3]) &&
654 
655  (x>=r[(i+3)*x_size+j-3]) &&
656  (x>=r[(i+3)*x_size+j-2]) &&
657  (x>=r[(i+3)*x_size+j-1]) &&
658  (x>=r[(i+3)*x_size+j ]) &&
659  (x>=r[(i+3)*x_size+j+1]) &&
660  (x>=r[(i+3)*x_size+j+2]) &&
661  (x>=r[(i+3)*x_size+j+3]) )
662 #endif
663  {
664  corner_list[n].info=0;
665  corner_list[n].x=j;
666  corner_list[n].y=i;
667  corner_list[n].dx=cgx[i*x_size+j];
668  corner_list[n].dy=cgy[i*x_size+j];
669  corner_list[n].I=in[i*x_size+j];
670  n++;
671  if(n==MAX_CORNERS){
672  BIASERR("Too many corners.\n");
673  return n;
674  }}}}
675  corner_list[n].info=7;
676 
677  delete[] cgx;
678  delete[] cgy;
679  return n;
680 }
681 
682 /* some modifications by woelk
683  - added roi to avoid unnecessary computqations
684  - introduced xj* to avoid unnecessary computations
685  - introduced _cgx, _cgy and _susanwidth, _susanheight to avoid unnecessaity
686  malloc/free */
687 template <class StorageType>
689 _susan_corners(const StorageType *in, int *r, StorageType *bp,
690  CORNER_LIST corner_list, int x_size, int y_size,
691  const StorageType *roi) {
692  const int max_no((this->_MaxNum>0)? (this->_MaxNum):INT_MAX);
693  int n,x,y,sq,xx,yy,i,j;
694  float divide;
695  StorageType c;
696  const StorageType *p, *cp;
697  int maxx=x_size-5, maxy=y_size-5;
698 
699 #ifdef FIVE_SUPP
700  int j1p, j1m, j2p, j2m, xi, xi1m, xi1p, xi2m, xi2p;
701 #endif
702 #ifdef SEVEN_SUPP
703  int j1p, j1m, j2p, j2m, j3p, j3m, xi, xi1m, xi1p, xi2m, xi2p, xi3m, xi3p;
704 #endif
705 
706  memset (r,0,x_size * y_size * sizeof(int));
707 
708 
709  if (_susansize<x_size*y_size){
710  _SusanReAllocMem(x_size, y_size);
711  }
712 
713  for (i=5;i<maxy;i++)
714  for (j=5;j<maxx;j++) {
715  if (roi[i*x_size+j]!=0){
716  n=100;
717  p=in + (i-3)*x_size + j - 1;
718  cp=bp + in[i*x_size+j];
719 
720  n+=*(cp-*p++);
721  n+=*(cp-*p++);
722  n+=*(cp-*p);
723  p+=x_size-3;
724 
725  n+=*(cp-*p++);
726  n+=*(cp-*p++);
727  n+=*(cp-*p++);
728  n+=*(cp-*p++);
729  n+=*(cp-*p);
730  p+=x_size-5;
731 
732  n+=*(cp-*p++);
733  n+=*(cp-*p++);
734  n+=*(cp-*p++);
735  n+=*(cp-*p++);
736  n+=*(cp-*p++);
737  n+=*(cp-*p++);
738  n+=*(cp-*p);
739  p+=x_size-6;
740 
741  n+=*(cp-*p++);
742  n+=*(cp-*p++);
743  n+=*(cp-*p);
744  if (n<max_no){ /* do this test early and often ONLY to save wasted computation */
745  p+=2;
746  n+=*(cp-*p++);
747  if (n<max_no){
748  n+=*(cp-*p++);
749  if (n<max_no){
750  n+=*(cp-*p);
751  if (n<max_no){
752  p+=x_size-6;
753 
754  n+=*(cp-*p++);
755  if (n<max_no){
756  n+=*(cp-*p++);
757  if (n<max_no){
758  n+=*(cp-*p++);
759  if (n<max_no){
760  n+=*(cp-*p++);
761  if (n<max_no){
762  n+=*(cp-*p++);
763  if (n<max_no){
764  n+=*(cp-*p++);
765  if (n<max_no){
766  n+=*(cp-*p);
767  if (n<max_no){
768  p+=x_size-5;
769 
770  n+=*(cp-*p++);
771  if (n<max_no){
772  n+=*(cp-*p++);
773  if (n<max_no){
774  n+=*(cp-*p++);
775  if (n<max_no){
776  n+=*(cp-*p++);
777  if (n<max_no){
778  n+=*(cp-*p);
779  if (n<max_no){
780  p+=x_size-3;
781 
782  n+=*(cp-*p++);
783  if (n<max_no){
784  n+=*(cp-*p++);
785  if (n<max_no){
786  n+=*(cp-*p);
787 
788  if (n<max_no)
789  {
790  x=0;y=0;
791  p=in + (i-3)*x_size + j - 1;
792 
793  c=*(cp-*p++);x-=c;y-=3*c;
794  c=*(cp-*p++);y-=3*c;
795  c=*(cp-*p);x+=c;y-=3*c;
796  p+=x_size-3;
797 
798  c=*(cp-*p++);x-=2*c;y-=2*c;
799  c=*(cp-*p++);x-=c;y-=2*c;
800  c=*(cp-*p++);y-=2*c;
801  c=*(cp-*p++);x+=c;y-=2*c;
802  c=*(cp-*p);x+=2*c;y-=2*c;
803  p+=x_size-5;
804 
805  c=*(cp-*p++);x-=3*c;y-=c;
806  c=*(cp-*p++);x-=2*c;y-=c;
807  c=*(cp-*p++);x-=c;y-=c;
808  c=*(cp-*p++);y-=c;
809  c=*(cp-*p++);x+=c;y-=c;
810  c=*(cp-*p++);x+=2*c;y-=c;
811  c=*(cp-*p);x+=3*c;y-=c;
812  p+=x_size-6;
813 
814  c=*(cp-*p++);x-=3*c;
815  c=*(cp-*p++);x-=2*c;
816  c=*(cp-*p);x-=c;
817  p+=2;
818  c=*(cp-*p++);x+=c;
819  c=*(cp-*p++);x+=2*c;
820  c=*(cp-*p);x+=3*c;
821  p+=x_size-6;
822 
823  c=*(cp-*p++);x-=3*c;y+=c;
824  c=*(cp-*p++);x-=2*c;y+=c;
825  c=*(cp-*p++);x-=c;y+=c;
826  c=*(cp-*p++);y+=c;
827  c=*(cp-*p++);x+=c;y+=c;
828  c=*(cp-*p++);x+=2*c;y+=c;
829  c=*(cp-*p);x+=3*c;y+=c;
830  p+=x_size-5;
831 
832  c=*(cp-*p++);x-=2*c;y+=2*c;
833  c=*(cp-*p++);x-=c;y+=2*c;
834  c=*(cp-*p++);y+=2*c;
835  c=*(cp-*p++);x+=c;y+=2*c;
836  c=*(cp-*p);x+=2*c;y+=2*c;
837  p+=x_size-3;
838 
839  c=*(cp-*p++);x-=c;y+=3*c;
840  c=*(cp-*p++);y+=3*c;
841  c=*(cp-*p);x+=c;y+=3*c;
842 
843  xx=x*x;
844  yy=y*y;
845  sq=xx+yy;
846  if ( sq > ((n*n)/2) ){
847  if(yy<xx) {
848  divide=(float)y/(float)abs(x);
849  sq=abs(x)/x;
850  sq=*(cp-in[(i+FTOI(divide))*x_size+j+sq]) +
851  *(cp-in[(i+FTOI(2*divide))*x_size+j+2*sq]) +
852  *(cp-in[(i+FTOI(3*divide))*x_size+j+3*sq]);}
853  else {
854  divide=(float)x/(float)abs(y);
855  sq=abs(y)/y;
856  sq=*(cp-in[(i+sq)*x_size+j+FTOI(divide)]) +
857  *(cp-in[(i+2*sq)*x_size+j+FTOI(2*divide)]) +
858  *(cp-in[(i+3*sq)*x_size+j+FTOI(3*divide)]);}
859 
860  if(sq>290){
861  r[i*x_size+j] = max_no-n;
862  _cgx[i*x_size+j] = (51*x)/n;
863  _cgy[i*x_size+j] = (51*y)/n;}
864  }
865  }
866  }}}}}}}}}}}}}}}}}}}}
867 
868  /* to locate the local maxima */
869  n=0;
870  for (i=5;i<maxy;i++)
871  for (j=5;j<maxx;j++) {
872  x = r[i*x_size+j];
873  if (x>0) {
874  j1p=j+1;
875  j2p=j+2;
876  j1m=j-1;
877  j2m=j-2;
878  xi=i*x_size;
879  xi1m=(i-1)*x_size;
880  xi1p=(i+1)*x_size;
881  xi2m=(i-2)*x_size;
882  xi2p=(i+2)*x_size;
883  /* 5x5 mask */
884 #ifdef FIVE_SUPP
885  if (
886  (x>r[xi1m+j2p]) &&
887  (x>r[xi+j1p]) &&
888  (x>r[xi+j2p]) &&
889  (x>r[xi1p+j1m]) &&
890  (x>r[xi1p+j ]) &&
891  (x>r[xi1p+j1p]) &&
892  (x>r[xi1p+j2p]) &&
893  (x>r[xi2p+j2m]) &&
894  (x>r[xi2p+j1m]) &&
895  (x>r[xi2p+j ]) &&
896  (x>r[xi2p+j1p]) &&
897  (x>r[xi2p+j2p]) &&
898  (x>=r[xi2m+j2m]) &&
899  (x>=r[xi2m+j1m]) &&
900  (x>=r[xi2m+j ]) &&
901  (x>=r[xi2m+j1p]) &&
902  (x>=r[xi2m+j2p]) &&
903  (x>=r[xi1m+j2m]) &&
904  (x>=r[xi1m+j1m]) &&
905  (x>=r[xi1m+j ]) &&
906  (x>=r[xi1m+j1p]) &&
907  (x>=r[xi+j2m]) &&
908  (x>=r[xi+j1m]) &&
909  (x>=r[xi1p+j2m]) )
910 #endif
911 #ifdef SEVEN_SUPP
912  j3p=j+3;
913  j3m=j-3;
914  xi3m=(i-3)*x_size;
915  xi3p=(i+3)*x_size;
916  if (
917  (x>r[xi3m+j3m]) &&
918  (x>r[xi3m+j2m]) &&
919  (x>r[xi3m+j1m]) &&
920  (x>r[xi3m+j ]) &&
921  (x>r[xi3m+j1p]) &&
922  (x>r[xi3m+j2p]) &&
923  (x>r[xi3m+j3p]) &&
924 
925  (x>r[xi2m+j3m]) &&
926  (x>r[xi2m+j2m]) &&
927  (x>r[xi2m+j1m]) &&
928  (x>r[xi2m+j ]) &&
929  (x>r[xi2m+j1p]) &&
930  (x>r[xi2m+j2p]) &&
931  (x>r[xi2m+j3p]) &&
932 
933  (x>r[xi1m+j3m]) &&
934  (x>r[xi1m+j2m]) &&
935  (x>r[xi1m+j1m]) &&
936  (x>r[xi1m+j ]) &&
937  (x>r[xi1m+j1p]) &&
938  (x>r[xi1m+j2p]) &&
939  (x>r[xi1m+j3p]) &&
940 
941  (x>r[xi+j3m]) &&
942  (x>r[xi+j2m]) &&
943  (x>r[xi+j1m]) &&
944  (x>=r[xi+j1p]) &&
945  (x>=r[xi+j2p]) &&
946  (x>=r[xi+j3p]) &&
947 
948  (x>=r[xi1p+j3m]) &&
949  (x>=r[xi1p+j2m]) &&
950  (x>=r[xi1p+j1m]) &&
951  (x>=r[xi1p+j ]) &&
952  (x>=r[xi1p+j1p]) &&
953  (x>=r[xi1p+j2p]) &&
954  (x>=r[xi1p+j3p]) &&
955 
956  (x>=r[xi2p+j3m]) &&
957  (x>=r[xi2p+j2m]) &&
958  (x>=r[xi2p+j1m]) &&
959  (x>=r[xi2p+j ]) &&
960  (x>=r[xi2p+j1p]) &&
961  (x>=r[xi2p+j2p]) &&
962  (x>=r[xi2p+j3p]) &&
963 
964  (x>=r[xi3p+j3m]) &&
965  (x>=r[xi3p+j2m]) &&
966  (x>=r[xi3p+j1m]) &&
967  (x>=r[xi3p+j ]) &&
968  (x>=r[xi3p+j1p]) &&
969  (x>=r[xi3p+j2p]) &&
970  (x>=r[xi3p+j3p]) )
971 #endif
972  {
973  corner_list[n].info=0;
974  corner_list[n].x=j;
975  corner_list[n].y=i;
976  corner_list[n].dx=_cgx[i*x_size+j];
977  corner_list[n].dy=_cgy[i*x_size+j];
978  corner_list[n].I=in[i*x_size+j];
979  n++;
980  if(n==MAX_CORNERS){
981  BIASERR("Too many corners.\n");
982  return n;
983  }}}}
984  corner_list[n].info=7;
985 
986  return n;
987 }
988 
989 template <class StorageType>
991 _susan_corners_quick(const StorageType *in, int *r, StorageType *bp,
992  CORNER_LIST corner_list, int x_size, int y_size)
993 {
994  const int max_no((this->_MaxNum>0)? (this->_MaxNum):INT_MAX);
995  int n,x,y,i,j;
996  const StorageType *p, *cp;
997 
998  memset (r,0,x_size * y_size * sizeof(int));
999 
1000  for (i=7;i<y_size-7;i++)
1001  for (j=7;j<x_size-7;j++) {
1002  n=100;
1003  p=in + (i-3)*x_size + j - 1;
1004  cp=bp + in[i*x_size+j];
1005 
1006  n+=*(cp-*p++);
1007  n+=*(cp-*p++);
1008  n+=*(cp-*p);
1009  p+=x_size-3;
1010 
1011  n+=*(cp-*p++);
1012  n+=*(cp-*p++);
1013  n+=*(cp-*p++);
1014  n+=*(cp-*p++);
1015  n+=*(cp-*p);
1016  p+=x_size-5;
1017 
1018  n+=*(cp-*p++);
1019  n+=*(cp-*p++);
1020  n+=*(cp-*p++);
1021  n+=*(cp-*p++);
1022  n+=*(cp-*p++);
1023  n+=*(cp-*p++);
1024  n+=*(cp-*p);
1025  p+=x_size-6;
1026 
1027  n+=*(cp-*p++);
1028  n+=*(cp-*p++);
1029  n+=*(cp-*p);
1030  if (n<max_no){
1031  p+=2;
1032  n+=*(cp-*p++);
1033  if (n<max_no){
1034  n+=*(cp-*p++);
1035  if (n<max_no){
1036  n+=*(cp-*p);
1037  if (n<max_no){
1038  p+=x_size-6;
1039 
1040  n+=*(cp-*p++);
1041  if (n<max_no){
1042  n+=*(cp-*p++);
1043  if (n<max_no){
1044  n+=*(cp-*p++);
1045  if (n<max_no){
1046  n+=*(cp-*p++);
1047  if (n<max_no){
1048  n+=*(cp-*p++);
1049  if (n<max_no){
1050  n+=*(cp-*p++);
1051  if (n<max_no){
1052  n+=*(cp-*p);
1053  if (n<max_no){
1054  p+=x_size-5;
1055 
1056  n+=*(cp-*p++);
1057  if (n<max_no){
1058  n+=*(cp-*p++);
1059  if (n<max_no){
1060  n+=*(cp-*p++);
1061  if (n<max_no){
1062  n+=*(cp-*p++);
1063  if (n<max_no){
1064  n+=*(cp-*p);
1065  if (n<max_no){
1066  p+=x_size-3;
1067 
1068  n+=*(cp-*p++);
1069  if (n<max_no){
1070  n+=*(cp-*p++);
1071  if (n<max_no){
1072  n+=*(cp-*p);
1073 
1074  if (n<max_no)
1075  r[i*x_size+j] = max_no-n;
1076  }}}}}}}}}}}}}}}}}}}
1077 
1078  /* to locate the local maxima */
1079  n=0;
1080  for (i=7;i<y_size-7;i++)
1081  for (j=7;j<x_size-7;j++) {
1082  x = r[i*x_size+j];
1083  if (x>0) {
1084  /* 5x5 mask */
1085 #ifdef FIVE_SUPP
1086  if (
1087  (x>r[(i-1)*x_size+j+2]) &&
1088  (x>r[(i )*x_size+j+1]) &&
1089  (x>r[(i )*x_size+j+2]) &&
1090  (x>r[(i+1)*x_size+j-1]) &&
1091  (x>r[(i+1)*x_size+j ]) &&
1092  (x>r[(i+1)*x_size+j+1]) &&
1093  (x>r[(i+1)*x_size+j+2]) &&
1094  (x>r[(i+2)*x_size+j-2]) &&
1095  (x>r[(i+2)*x_size+j-1]) &&
1096  (x>r[(i+2)*x_size+j ]) &&
1097  (x>r[(i+2)*x_size+j+1]) &&
1098  (x>r[(i+2)*x_size+j+2]) &&
1099  (x>=r[(i-2)*x_size+j-2]) &&
1100  (x>=r[(i-2)*x_size+j-1]) &&
1101  (x>=r[(i-2)*x_size+j ]) &&
1102  (x>=r[(i-2)*x_size+j+1]) &&
1103  (x>=r[(i-2)*x_size+j+2]) &&
1104  (x>=r[(i-1)*x_size+j-2]) &&
1105  (x>=r[(i-1)*x_size+j-1]) &&
1106  (x>=r[(i-1)*x_size+j ]) &&
1107  (x>=r[(i-1)*x_size+j+1]) &&
1108  (x>=r[(i )*x_size+j-2]) &&
1109  (x>=r[(i )*x_size+j-1]) &&
1110  (x>=r[(i+1)*x_size+j-2]) )
1111 #endif
1112 #ifdef SEVEN_SUPP
1113  if (
1114  (x>r[(i-3)*x_size+j-3]) &&
1115  (x>r[(i-3)*x_size+j-2]) &&
1116  (x>r[(i-3)*x_size+j-1]) &&
1117  (x>r[(i-3)*x_size+j ]) &&
1118  (x>r[(i-3)*x_size+j+1]) &&
1119  (x>r[(i-3)*x_size+j+2]) &&
1120  (x>r[(i-3)*x_size+j+3]) &&
1121 
1122  (x>r[(i-2)*x_size+j-3]) &&
1123  (x>r[(i-2)*x_size+j-2]) &&
1124  (x>r[(i-2)*x_size+j-1]) &&
1125  (x>r[(i-2)*x_size+j ]) &&
1126  (x>r[(i-2)*x_size+j+1]) &&
1127  (x>r[(i-2)*x_size+j+2]) &&
1128  (x>r[(i-2)*x_size+j+3]) &&
1129 
1130  (x>r[(i-1)*x_size+j-3]) &&
1131  (x>r[(i-1)*x_size+j-2]) &&
1132  (x>r[(i-1)*x_size+j-1]) &&
1133  (x>r[(i-1)*x_size+j ]) &&
1134  (x>r[(i-1)*x_size+j+1]) &&
1135  (x>r[(i-1)*x_size+j+2]) &&
1136  (x>r[(i-1)*x_size+j+3]) &&
1137 
1138  (x>r[(i)*x_size+j-3]) &&
1139  (x>r[(i)*x_size+j-2]) &&
1140  (x>r[(i)*x_size+j-1]) &&
1141  (x>=r[(i)*x_size+j+1]) &&
1142  (x>=r[(i)*x_size+j+2]) &&
1143  (x>=r[(i)*x_size+j+3]) &&
1144 
1145  (x>=r[(i+1)*x_size+j-3]) &&
1146  (x>=r[(i+1)*x_size+j-2]) &&
1147  (x>=r[(i+1)*x_size+j-1]) &&
1148  (x>=r[(i+1)*x_size+j ]) &&
1149  (x>=r[(i+1)*x_size+j+1]) &&
1150  (x>=r[(i+1)*x_size+j+2]) &&
1151  (x>=r[(i+1)*x_size+j+3]) &&
1152 
1153  (x>=r[(i+2)*x_size+j-3]) &&
1154  (x>=r[(i+2)*x_size+j-2]) &&
1155  (x>=r[(i+2)*x_size+j-1]) &&
1156  (x>=r[(i+2)*x_size+j ]) &&
1157  (x>=r[(i+2)*x_size+j+1]) &&
1158  (x>=r[(i+2)*x_size+j+2]) &&
1159  (x>=r[(i+2)*x_size+j+3]) &&
1160 
1161  (x>=r[(i+3)*x_size+j-3]) &&
1162  (x>=r[(i+3)*x_size+j-2]) &&
1163  (x>=r[(i+3)*x_size+j-1]) &&
1164  (x>=r[(i+3)*x_size+j ]) &&
1165  (x>=r[(i+3)*x_size+j+1]) &&
1166  (x>=r[(i+3)*x_size+j+2]) &&
1167  (x>=r[(i+3)*x_size+j+3]) )
1168 #endif
1169  {
1170  corner_list[n].info=0;
1171  corner_list[n].x=j;
1172  corner_list[n].y=i;
1173  x = in[(i-2)*x_size+j-2] + in[(i-2)*x_size+j-1] + in[(i-2)*x_size+j] + in[(i-2)*x_size+j+1] + in[(i-2)*x_size+j+2] +
1174  in[(i-1)*x_size+j-2] + in[(i-1)*x_size+j-1] + in[(i-1)*x_size+j] + in[(i-1)*x_size+j+1] + in[(i-1)*x_size+j+2] +
1175  in[(i )*x_size+j-2] + in[(i )*x_size+j-1] + in[(i )*x_size+j] + in[(i )*x_size+j+1] + in[(i )*x_size+j+2] +
1176  in[(i+1)*x_size+j-2] + in[(i+1)*x_size+j-1] + in[(i+1)*x_size+j] + in[(i+1)*x_size+j+1] + in[(i+1)*x_size+j+2] +
1177  in[(i+2)*x_size+j-2] + in[(i+2)*x_size+j-1] + in[(i+2)*x_size+j] + in[(i+2)*x_size+j+1] + in[(i+2)*x_size+j+2];
1178 
1179  corner_list[n].I=x/25;
1180  /*corner_list[n].I=in[i*x_size+j];*/
1181  x = in[(i-2)*x_size+j+2] + in[(i-1)*x_size+j+2] + in[(i)*x_size+j+2] + in[(i+1)*x_size+j+2] + in[(i+2)*x_size+j+2] -
1182  (in[(i-2)*x_size+j-2] + in[(i-1)*x_size+j-2] + in[(i)*x_size+j-2] + in[(i+1)*x_size+j-2] + in[(i+2)*x_size+j-2]);
1183  x += x + in[(i-2)*x_size+j+1] + in[(i-1)*x_size+j+1] + in[(i)*x_size+j+1] + in[(i+1)*x_size+j+1] + in[(i+2)*x_size+j+1] -
1184  (in[(i-2)*x_size+j-1] + in[(i-1)*x_size+j-1] + in[(i)*x_size+j-1] + in[(i+1)*x_size+j-1] + in[(i+2)*x_size+j-1]);
1185 
1186  y = in[(i+2)*x_size+j-2] + in[(i+2)*x_size+j-1] + in[(i+2)*x_size+j] + in[(i+2)*x_size+j+1] + in[(i+2)*x_size+j+2] -
1187  (in[(i-2)*x_size+j-2] + in[(i-2)*x_size+j-1] + in[(i-2)*x_size+j] + in[(i-2)*x_size+j+1] + in[(i-2)*x_size+j+2]);
1188  y += y + in[(i+1)*x_size+j-2] + in[(i+1)*x_size+j-1] + in[(i+1)*x_size+j] + in[(i+1)*x_size+j+1] + in[(i+1)*x_size+j+2] -
1189  (in[(i-1)*x_size+j-2] + in[(i-1)*x_size+j-1] + in[(i-1)*x_size+j] + in[(i-1)*x_size+j+1] + in[(i-1)*x_size+j+2]);
1190  corner_list[n].dx=x/15;
1191  corner_list[n].dy=y/15;
1192 // point.Set((double)j, (double)i);
1193 // pvec.push_back(point);
1194 // quality.push_back((float)(x/15*y/15));
1195 
1196  n++;
1197  if(n==MAX_CORNERS){
1198  BIASERR("Too many corners.\n");
1199  return n;
1200  }}}}
1201  corner_list[n].info=7;
1202  return n;
1203 }
1204 
1205 //////////////////////////////////////////////////////////////////////////
1206 // instantiation
1207 //////////////////////////////////////////////////////////////////////////
1208 namespace BIAS{
1209 template class CornerDetectorSusan<unsigned char>;
1210 //template class CornerDetectorSusan<float>;
1211 
1212 // fill in instances as required
1213 #ifdef BUILD_IMAGE_INT
1214 #endif
1215 #ifdef BUILD_IMAGE_CHAR
1216 #endif
1217 #ifdef BUILD_IMAGE_SHORT
1218 #endif
1219 #ifdef BUILD_IMAGE_USHORT
1220 template class CornerDetectorSusan<unsigned short>;
1221 #endif
1222 #ifdef BUILD_IMAGE_UINT
1223 #endif
1224 #ifdef BUILD_IMAGE_DOUBLE
1225 #endif
1226 }
1227 /* {{{ Machine Information */
1228 
1229 /**********************************************************************\
1230 
1231  Success has been reported with the following:
1232 
1233  MACHINE OS COMPILER
1234 
1235  Sun 4.1.4 bundled C, gcc
1236 
1237  Next
1238 
1239  SGI IRIX SGI cc
1240 
1241  DEC Unix V3.2+
1242 
1243  IBM RISC AIX gcc
1244 
1245  PC Borland 5.0
1246 
1247  PC Linux gcc-2.6.3
1248 
1249  PC Win32 Visual C++ 4.0 (Console Application)
1250 
1251  PC Win95 Visual C++ 5.0 (Console Application)
1252  Thanks to Niu Yongsheng <niuysbit@163.net>:
1253  Use the FOPENB option below
1254 
1255  PC DOS djgpp gnu C
1256  Thanks to Mark Pettovello <mpettove@umdsun2.umd.umich.edu>:
1257  Use the FOPENB option below
1258 
1259  HP HP-UX bundled cc
1260  Thanks to Brian Dixon <briand@hpcvsgen.cv.hp.com>:
1261  in ksh:
1262  export CCOPTS="-Aa -D_HPUX_SOURCE | -lM"
1263  cc -O3 -o susan susan2l.c
1264 
1265 \**********************************************************************/
1266 
1267 /* }}} */
1268 
class HomgPoint2D describes a point with 2 degrees of freedom in projective coordinates.
Definition: HomgPoint2D.hh:67
bool IsEmpty() const
check if ImageData_ points to allocated image buffer or not
Definition: ImageBase.hh:245
int _susan_corners(const StorageType *in, int *r, StorageType *bp, CORNER_LIST corner_list, int x_size, int y_size)
returns the number of corners found
int * _cgx
local vars for susan
virtual int Detect(const Image< StorageType > &image, std::vector< HomgPoint2D > &pvec, std::vector< QUAL > &quality)
Susan Corner Detector returning homogenous points,.
unsigned int GetWidth() const
Definition: ImageBase.hh:312
The Susan corner detector (oxford implementation, see license)
int _MaxNum
maximum number of corners to return
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
Definition: ImageBase.hh:382
void _setup_brightness_lut(int thresh, int form)
protected function for susan
unsigned int GetHeight() const
Definition: ImageBase.hh:319
The image template class for specific storage types.
Definition: Image.hh:78
const StorageType * GetImageData() const
overloaded GetImageData() from ImageBase
Definition: Image.hh:137
struct cornerstruct CORNER_LIST[MAX_CORNERS]
purly virtual interface defining class for corner detectors
int _susan_corners_quick(const StorageType *in, int *r, StorageType *bp, CORNER_LIST corner_list, int x_size, int y_size)
returns the number of corners found
void _int_to_uchar(const int *r, StorageType *in, int size)
protected function for susan