54 minimal_neighbor_number = 4;
57 set_bins_number(4, 4);
59 disactivate_subpixel();
61 set_minimal_neighbor_number(3);
68 if (Dirs)
delete Dirs;
69 if (Dirs_nb)
delete[] Dirs_nb;
70 if (scores) cvReleaseImage(&scores);
71 if (filtered_image) cvReleaseImage(&filtered_image);
76 yape * pe =
new yape(image->width, image->height);
80 int point_number = pe->
detect(image, points, max_point_number);
99 scores = cvCreateImage(cvSize(width, height), IPL_DEPTH_16S, 1);
100 filtered_image = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
107 precompute_directions(filtered_image, Dirs->t[R], &(Dirs_nb[R]), R);
113 for(
int i = 0; i < bin_nb_u; i++)
114 for(
int j = 0; j < bin_nb_v; j++)
128 int widthStep = image->widthStep;
134 for(y = 0; y < x; y++, i++)
136 x = int(sqrt(
double(R * R - y * y)) + 0.5);
137 _Dirs[i] = short(x + widthStep * y);
139 for(x-- ; x < y && x >= 0; x--, i++)
141 y = int(sqrt(
double(R * R - x * x)) + 0.5);
142 _Dirs[i] = short(x + widthStep * y);
144 for( ; -x < y; x--, i++)
146 y = int(sqrt(
double(R * R - x * x)) + 0.5);
147 _Dirs[i] = short(x + widthStep * y);
149 for(y-- ; y >= 0; y--, i++)
151 x = int(-sqrt(
double(R * R - y * y)) - 0.5);
152 _Dirs[i] = short(x + widthStep * y);
154 for(; y > x; y--, i++)
156 x = int(-sqrt(
double(R * R - y * y)) - 0.5);
157 _Dirs[i] = short(x + widthStep * y);
159 for(x++ ; x <= 0; x++, i++)
161 y = int(-sqrt(
double(R * R - x * x)) - 0.5);
162 _Dirs[i] = short(x + widthStep * y);
164 for( ; x < -y; x++, i++)
166 y = int(-sqrt(
double(R * R - x * x)) - 0.5);
167 _Dirs[i] = short(x + widthStep * y);
169 for(y++ ; y < 0; y++, i++)
171 x = int(sqrt(
double(R * R - y * y)) + 0.5);
172 _Dirs[i] = short(x + widthStep * y);
177 _Dirs[i + 1] = _Dirs[1];
184 for(
int i = 0; i < points_nb; i++) {
185 int s = (int)points[i].scale;
198 unsigned char * I = (
unsigned char *)(image->imageData + y * image->widthStep);
203 for(A = dirs_nb / 2 - 2; A <= dirs_nb / 2 + 2; A++)
204 for(
int i = 0; i < dirs_nb - A; i++)
206 if (I[x+dirs[i]] > Im && I[x+dirs[i]] < Ip && I[x+dirs[i+A]] > Im && I[x+dirs[i+A]] < Ip)
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)
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)
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)
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)
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]]
238 #define GOTO_STATE(s) { score -= A + B1; state = (s); break; }
239 #define GOTO_END_NOT_AN_INTEREST_POINT { Scores[x] = 0; return; }
240 #define PUT_B2_IN_B1_AND_GET_B2() B1 = B2; GET_B2()
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
254 const int Im,
const int Ip,
255 const short * dirs,
const unsigned char opposite,
const unsigned char dirs_nb)
258 unsigned char a = 0, b = opposite - 1;
324 for(a = 1; a <= opposite; a++)
471 cout <<
"PB default" << endl;
475 Scores[x] = short(score + dirs_nb * I[x]);
480 IplImage * used_filtered_image;
482 if (_filtered_image == 0)
484 int gaussian_filter_size = 3;
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);
490 used_filtered_image = filtered_image;
493 used_filtered_image = _filtered_image;
495 reserve_tmp_arrays();
497 raw_detect(used_filtered_image);
499 get_local_maxima(image, radius, 0);
501 int points_nb = pick_best_points(points, max_point_number);
504 for(
int i = 0; i < points_nb; i++)
505 subpix_refine(used_filtered_image, points + i);
510 static unsigned mymin(
unsigned a,
unsigned b)
523 for(
int i = 0; i < bin_nb_u; i++)
525 for(
int j = 0; j < bin_nb_v; j++)
527 if (bins[i][j].size() > 0){
528 sort(bins[i][j].begin(), bins[i][j].end());
529 N += bins[i][j].size();
534 N = max_point_number;
535 unsigned int N_per_bin = N / (bin_nb_u * bin_nb_v);
537 for(
int i = 0; i < bin_nb_u; i++)
539 for(
int j = 0; j < bin_nb_v; j++)
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];
549 if (tmp_points.size() > 0)
551 sort(tmp_points.begin(), tmp_points.end());
553 int score_threshold = 0;
555 int tot_pts = tmp_points.size()<max_point_number ? tmp_points.size() : max_point_number;
559 points_nb<tot_pts && tmp_points[points_nb].score>score_threshold;
561 points[points_nb] = tmp_points[points_nb];
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;
579 CvRect roi = cvGetImageROI(im);
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;
586 unsigned int xend = roi.x + roi.width;
587 unsigned int yend = roi.y + roi.height;
589 for(
unsigned int y = roi.y; y < yend; y++)
591 unsigned char * I = (
unsigned char *)(im->imageData + y*im->widthStep);
592 short * Scores = (
short *)(scores->imageData + y*scores->widthStep);
594 for(
unsigned int x = roi.x; x < xend; x++)
599 if (Im<I[x+R] && I[x+R]<Ip && Im<I[x-R] && I[x-R]<Ip)
602 perform_one_point(I, x, Scores, Im, Ip, dirs, opposite, dirs_nb);
615 #define MINIMAL_SCORE (0 / radius)
624 if (Sb[
S+
E] != 0) n++;
625 if (Sb[
S+
W] != 0) n++;
627 if (Sb[
N+
E] != 0) n++;
628 if (Sb[
N+
W] != 0) n++;
630 return n >= minimal_neighbor_number;
634 static inline bool is_local_maxima(
const short *p,
int neighborhood,
const IplImage *scores)
636 #ifdef CONSIDER_ABS_VALUE_ONLY
637 unsigned v = abs(p[0]);
638 if (v < 5)
return false;
640 int step = scores->widthStep / 2;
642 p -= step*neighborhood;
643 for (
int y= -neighborhood; y<=neighborhood; ++y) {
644 for (
int x= -neighborhood; x<=neighborhood; ++x) {
654 int step = scores->widthStep / 2;
657 p -= step*neighborhood;
658 for (
int y= -neighborhood; y<=neighborhood; ++y) {
659 for (
int x= -neighborhood; x<=neighborhood; ++x) {
666 p -= step*neighborhood;
667 for (
int y= -neighborhood; y<=neighborhood; ++y) {
668 for (
int x= -neighborhood; x<=neighborhood; ++x) {
688 const int next_line = scores->widthStep /
sizeof(short);
689 int h = scores->height;
690 int w = scores->width;
692 CvRect roi = cvGetImageROI(image);
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;
699 unsigned int xend = roi.x + roi.width;
700 unsigned int yend = roi.y + roi.height;
702 for(
unsigned int y = roi.y; y < yend; y++)
704 short * Scores = (
short *)(scores->imageData + y * scores->widthStep);
706 for(
unsigned int x = roi.x; x < xend; x++)
708 short * Sb = Scores + x;
721 p.
score = float(abs(Sb[0]));
725 int bin_u_index = (bin_nb_u * x) / w;
726 int bin_v_index = (bin_nb_v * y) / h;
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;
734 bins[bin_u_index][bin_v_index].push_back(p);
737 tmp_points.push_back(p);
757 b[0] = -(L[1][2] - L[1][0]) / 2.0f;
758 b[1] = -(L[2][1] - L[0][1]) / 2.0f;
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;
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];
768 return 0.5f * (b[0] * x[0] + b[1] * x[1]);
777 int dirs_nb = Dirs_nb[radius];
778 short * dirs = Dirs->t[radius];
780 if ((px<= radius) || (px >= (scores->width-radius)) || (py <= radius) || (py >= (scores->height-radius)))
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);
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) {
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]);
797 L[y][x] = (float)s[ offset + x];
805 if ((delta[0] >= -1) && (delta[0] <= 1))
809 if ((delta[1] >= -1) && (delta[1] <= 1))
832 PyrImage pim(cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1),nbLev);
834 for (
int i=1; i<nbLev; i++) {
871 for (
int i=image->
nbLev-1; i>=0; --i)
879 for (
int i = 0; i < n; i++) {
880 int l =(int)points[i].scale;
905 assert(im->nChannels == 1);
926 assert (im->width == caller_pim->
images[0]->width);
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);
936 return detect(pim, points, max_point_number);
942 for(
int i = 0; i < points_nb; i++)
948 cvReleaseImage(&point_image);
957 for (
int i=0; i<nb_pts; ++i)
958 histogram[(
int)(points[i].
scale)]++;
961 cout <<
"Level " << l <<
": " << histogram[l] <<
" keypoints ("
962 << 100.0f * (
float)histogram[l]/(float)nb_pts <<
"%)\n";