190 #include "CornerDetectorSusan.hh"
192 #define FTOI(a) ( (a) < 0 ? ((int)(a-0.5)) : ((int)(a+0.5)) )
196 using namespace BIAS;
204 template <
class StorageType>
214 this->
_MaxNum = CORNERDETECTOR_SUSAN_MAXNUM_DEFAULT;
217 template <
class StorageType>
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);
226 template <
class StorageType>
232 BIASERR(
"Susan: Can only detect corners on grey value images");
238 if (_susansize<x_size*y_size) {
239 _SusanReAllocMem(x_size, y_size);
243 if (_susanthresh!=_Threshold)
244 _setup_brightness_lut(_Threshold, 6);
246 num = _susan_corners_quick(in, _r, _bp, corner_list,
249 num = _susan_corners(in, _r, _bp, corner_list, x_size,
252 BIASDOUT(D_CD_SUSAN,
"Susan found "<< num <<
" corners ");
256 template <
class StorageType>
263 BIASERR(
"Susan: Can only detect corners on grey value images");
269 if (_susansize<x_size*y_size) {
270 _SusanReAllocMem(x_size, y_size);
275 if (_susanthresh!=_Threshold)
276 _setup_brightness_lut(_Threshold, 6);
278 num = _susan_corners_quick(in, _r, _bp, corner_list,
281 num = _susan_corners(in, _r, _bp, corner_list, x_size,
284 BIASDOUT(D_CD_SUSAN,
"Susan found "<< num <<
" corners ");
288 template <
class StorageType>
291 vector<float>& quality)
295 BIASERR(
"Susan: Can only detect corners on grey value images");
301 if (_susansize<x_size*y_size) {
302 _SusanReAllocMem(x_size, y_size);
314 if (_susanthresh!=_Threshold)
315 _setup_brightness_lut(_Threshold, 6);
317 num = _susan_corners_quick(in, _r, _bp, corner_list,
320 num = _susan_corners(in, _r, _bp, corner_list,
323 quality.resize(num+1);
325 while(corner_list[n].info != 7){
326 pvec[n].Set((
double)corner_list[n].x, (
double)corner_list[n].y);
333 quality[n]=((float)fabs((
float)corner_list[n].dx*corner_list[n].dy)
344 BIASDOUT(D_CD_SUSAN,
"Susan found "<< n <<
" corners ");
350 template <
class StorageType>
358 for (i=0; i<size; i++)
370 for (i=0; i<size; i++)
371 in[i] = (StorageType)((int)((
int)(r[i]-min_r)*255)/max_r);
375 template <
class StorageType>
384 _bp=
new StorageType[516];
389 for(k=-256;k<257;k++)
391 temp=((float)k)/((float)thresh);
395 temp=100.0f*exp(-temp);
396 *(_bp+k)= (StorageType)temp;
400 template <
class StorageType>
405 const int max_no((this->_MaxNum>0)? (this->_MaxNum):INT_MAX);
410 const StorageType *p,*cp;
412 memset (r,0,x_size * y_size *
sizeof(
int));
414 cgx=
new int[x_size*y_size];
415 cgy=
new int[x_size*y_size];
417 for (i=5;i<y_size-5;i++)
418 for (j=5;j<x_size-5;j++) {
420 p=in + (i-3)*x_size + j - 1;
421 cp=bp + in[i*x_size+j];
494 p=in + (i-3)*x_size + j - 1;
496 c=*(cp-*p++);x-=c;y-=3*c;
498 c=*(cp-*p);x+=c;y-=3*c;
501 c=*(cp-*p++);x-=2*c;y-=2*c;
502 c=*(cp-*p++);x-=c;y-=2*c;
504 c=*(cp-*p++);x+=c;y-=2*c;
505 c=*(cp-*p);x+=2*c;y-=2*c;
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;
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;
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;
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;
535 c=*(cp-*p++);x-=2*c;y+=2*c;
536 c=*(cp-*p++);x-=c;y+=2*c;
538 c=*(cp-*p++);x+=c;y+=2*c;
539 c=*(cp-*p);x+=2*c;y+=2*c;
542 c=*(cp-*p++);x-=c;y+=3*c;
544 c=*(cp-*p);x+=c;y+=3*c;
549 if ( sq > ((n*n)/2) )
552 divide=(float)y/(
float)abs(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]);}
558 divide=(float)x/(
float)abs(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)]);}
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;}
574 for (i=5;i<y_size-5;i++)
575 for (j=5;j<x_size-5;j++) {
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]) )
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]) &&
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]) &&
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]) &&
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]) &&
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]) &&
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]) &&
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]) )
664 corner_list[n].info=0;
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];
672 BIASERR(
"Too many corners.\n");
675 corner_list[n].info=7;
687 template <
class StorageType>
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;
696 const StorageType *p, *cp;
697 int maxx=x_size-5, maxy=y_size-5;
700 int j1p, j1m, j2p, j2m, xi, xi1m, xi1p, xi2m, xi2p;
703 int j1p, j1m, j2p, j2m, j3p, j3m, xi, xi1m, xi1p, xi2m, xi2p, xi3m, xi3p;
706 memset (r,0,x_size * y_size *
sizeof(
int));
709 if (_susansize<x_size*y_size){
710 _SusanReAllocMem(x_size, y_size);
714 for (j=5;j<maxx;j++) {
715 if (roi[i*x_size+j]!=0){
717 p=in + (i-3)*x_size + j - 1;
718 cp=bp + in[i*x_size+j];
791 p=in + (i-3)*x_size + j - 1;
793 c=*(cp-*p++);x-=c;y-=3*c;
795 c=*(cp-*p);x+=c;y-=3*c;
798 c=*(cp-*p++);x-=2*c;y-=2*c;
799 c=*(cp-*p++);x-=c;y-=2*c;
801 c=*(cp-*p++);x+=c;y-=2*c;
802 c=*(cp-*p);x+=2*c;y-=2*c;
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;
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;
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;
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;
832 c=*(cp-*p++);x-=2*c;y+=2*c;
833 c=*(cp-*p++);x-=c;y+=2*c;
835 c=*(cp-*p++);x+=c;y+=2*c;
836 c=*(cp-*p);x+=2*c;y+=2*c;
839 c=*(cp-*p++);x-=c;y+=3*c;
841 c=*(cp-*p);x+=c;y+=3*c;
846 if ( sq > ((n*n)/2) ){
848 divide=(float)y/(
float)abs(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]);}
854 divide=(float)x/(
float)abs(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)]);}
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;}
871 for (j=5;j<maxx;j++) {
973 corner_list[n].info=0;
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];
981 BIASERR(
"Too many corners.\n");
984 corner_list[n].info=7;
989 template <
class StorageType>
994 const int max_no((this->_MaxNum>0)? (this->_MaxNum):INT_MAX);
996 const StorageType *p, *cp;
998 memset (r,0,x_size * y_size *
sizeof(
int));
1000 for (i=7;i<y_size-7;i++)
1001 for (j=7;j<x_size-7;j++) {
1003 p=in + (i-3)*x_size + j - 1;
1004 cp=bp + in[i*x_size+j];
1075 r[i*x_size+j] = max_no-n;
1080 for (i=7;i<y_size-7;i++)
1081 for (j=7;j<x_size-7;j++) {
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]) )
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]) &&
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]) &&
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]) &&
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]) &&
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]) &&
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]) &&
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]) )
1170 corner_list[n].info=0;
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];
1179 corner_list[n].I=x/25;
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]);
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;
1198 BIASERR(
"Too many corners.\n");
1201 corner_list[n].info=7;
1213 #ifdef BUILD_IMAGE_INT
1215 #ifdef BUILD_IMAGE_CHAR
1217 #ifdef BUILD_IMAGE_SHORT
1219 #ifdef BUILD_IMAGE_USHORT
1222 #ifdef BUILD_IMAGE_UINT
1224 #ifdef BUILD_IMAGE_DOUBLE
class HomgPoint2D describes a point with 2 degrees of freedom in projective coordinates.
bool IsEmpty() const
check if ImageData_ points to allocated image buffer or not
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
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.
void _setup_brightness_lut(int thresh, int form)
protected function for susan
unsigned int GetHeight() const
The image template class for specific storage types.
const StorageType * GetImageData() const
overloaded GetImageData() from ImageBase
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