32 #define ATAN2_TABLE_INDEX(dx, dy) (((dy + MAX_GRADIENT) * (2 * MAX_GRADIENT + 1)) + (dx + MAX_GRADIENT))
36 #define DERIVATIVES_KERNEL_SIZE 1
44 neighborhood_size = _neighborhood_size;
47 actual_neighborhood_size = neighborhood_size;
49 angle_buckets =
new int[ANGLE_BUCKET_NUMBER];
54 void keypoint_orientation_corrector::initialize_tables(
void)
62 float norm2 = float(dx * dx + dy * dy);
65 float angle = atan2((
float)dy, (
float)dx);
66 angle = (float) ((angle + 3.14159) * 180 / 3.14159);
67 if (angle < 0) angle = 0;
68 if (angle > 359) angle = 359;
69 int result = int(angle / ANGLE_QUANTUM + 0.5);
70 if (result < 0) result = 0;
71 if (result >= ANGLE_BUCKET_NUMBER) result = ANGLE_BUCKET_NUMBER - 1;
72 atan2_table[index] = (short)result;
75 atan2_table[index] = -1;
78 orientation_lookup_tables =
new int* [ANGLE_BUCKET_NUMBER*nbLev];
81 PyrImage im(cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1), nbLev);
83 for(
int i = 0; i < ANGLE_BUCKET_NUMBER*nbLev; i++)
85 int level = i / ANGLE_BUCKET_NUMBER;
86 int angle = i % ANGLE_BUCKET_NUMBER;
87 int size = neighborhood_size ;
88 int * table = orientation_lookup_tables[i] =
new int[size * size];
89 float cs = float(cos(angle * 2 * 3.14159 / ANGLE_BUCKET_NUMBER));
90 float sn = float(sin(angle * 2 * 3.14159 / ANGLE_BUCKET_NUMBER));
92 for(
int y = 0; y < size; y++)
93 for(
int x = 0; x < size; x++)
98 int nx = int(cs * dx - sn * dy + 0.5);
99 int ny = int(sn * dx + cs * dy + 0.5);
100 table[y * size + x] = int(ny * im[level]->widthStep + nx);
104 exp_weights = cvCreateImage(cvSize(neighborhood_size, neighborhood_size), IPL_DEPTH_32S, 1);
107 bool actual_neighborhood_size_found =
false;
108 for(
int y = 0; y < neighborhood_size; y++)
110 int *
W = (
int *)(exp_weights->imageData + y * exp_weights->widthStep);
112 for(
int x = 0; x < neighborhood_size; x++)
114 float d2 = float(
gf_sqr(x - neighborhood_size / 2) +
gf_sqr(y - neighborhood_size / 2));
117 W[x] = int(100 * exp(-d2 / (2 * sigma_d2 * sigma_d2)));
119 if (y == neighborhood_size / 2)
120 if (x > neighborhood_size / 2 && !actual_neighborhood_size_found)
123 actual_neighborhood_size = 2 * (x - (neighborhood_size / 2));
124 actual_neighborhood_size_found =
true;
132 delete[] angle_buckets;
134 for(
int i = 0; i < ANGLE_BUCKET_NUMBER*nbLev; i++)
135 delete[] orientation_lookup_tables[i];
136 delete[] orientation_lookup_tables;
137 if (atan2_table)
delete[] atan2_table;
142 *_Ix = cvCreateImage(cvSize(image->width, image->height), IPL_DEPTH_16S, 1);
143 *_Iy = cvCreateImage(cvSize(image->width, image->height), IPL_DEPTH_16S, 1);
150 const int u,
const int v)
152 const int D = actual_neighborhood_size / 2;
154 for(
int i = 0; i < ANGLE_BUCKET_NUMBER; i++)
155 angle_buckets[i] = 0;
157 for(
int y = -D; y < D; y++)
159 int dIx = (v + y) * _Ix->widthStep + (u << 1);
160 short * Ix_row = (
short*)(_Ix->imageData + dIx);
161 short * Iy_row = (
short*)(_Iy->imageData + dIx);
162 int * W = (
int*) (exp_weights->imageData + (D + y) * exp_weights->widthStep) + D;
164 for(
int x = -D; x < D; x++)
166 if (W[x] == 0)
continue;
170 int norm2 = dx * dx + dy * dy;
178 assert(index <ANGLE_BUCKET_NUMBER);
179 angle_buckets[index] += W[x] * norm2;
186 int orientation_bucket_index = 0, value = angle_buckets[0];
187 for(
int i = 1; i < ANGLE_BUCKET_NUMBER; i++)
188 if (angle_buckets[i] > value)
190 value = angle_buckets[i];
191 orientation_bucket_index = i;
194 return orientation_bucket_index;
198 const int u,
const int v)
200 const int D = actual_neighborhood_size / 2;
202 for(
int i = 0; i < ANGLE_BUCKET_NUMBER; i++)
203 angle_buckets[i] = 0;
205 for(
int y = -D; y < D; y++)
207 int dIx = (v + y) * _Ix->widthStep + (u << 1);
208 short * Ix_row = (
short*)(_Ix->imageData + dIx);
209 short * Iy_row = (
short*)(_Iy->imageData + dIx);
210 int * W = (
int*) (exp_weights->imageData + (D + y) * exp_weights->widthStep) + D;
212 int dx = (y + D) & 1;
214 for(
int x = dx; x < D; x+=2)
216 if (W[x] == 0)
break;
220 int norm2 = dx * dx + dy * dy;
228 angle_buckets[index] += W[x] * norm2;
231 for(
int x = -2 + dx; x >= -D; x-=2)
233 if (W[x] == 0)
break;
237 int norm2 = dx * dx + dy * dy;
245 angle_buckets[index] += W[x] * norm2;
252 int orientation_bucket_index = 0, value = angle_buckets[0];
253 for(
int i = 1; i < ANGLE_BUCKET_NUMBER; i++)
254 if (angle_buckets[i] > value)
256 value = angle_buckets[i];
257 orientation_bucket_index = i;
260 return orientation_bucket_index;
263 void keypoint_orientation_corrector::rotate_patchf(IplImage * original_image,
float u,
float v,
264 IplImage * rotated_patch,
268 static CvMat M = cvMat( 2, 3, CV_32F, m );
270 m[0] = (float)(cos(-angle));
271 m[1] = (float)(sin(-angle));
277 cvGetQuadrangleSubPix(original_image, rotated_patch, &M);
280 void keypoint_orientation_corrector::rotate_patch(IplImage * original_image,
int u,
int v,
281 IplImage * rotated_patch,
282 int orientation_bucket_index,
int level)
284 if (original_image->depth == IPL_DEPTH_8U && rotated_patch->depth == IPL_DEPTH_8U)
286 int * table = orientation_lookup_tables[level * ANGLE_BUCKET_NUMBER + orientation_bucket_index];
287 char * src = original_image->imageData;
288 int offset = (int)v * original_image->widthStep + (
int)u;
289 unsigned max = (unsigned)original_image->widthStep*(original_image->height+1);
290 char * dst = rotated_patch->imageData;
292 const int length = neighborhood_size * neighborhood_size;
293 for(
int i = 0; i < length; i++) {
294 unsigned idx = offset + table[i];
299 else if (original_image->depth == (
int)IPL_DEPTH_16S && rotated_patch->depth == (int)IPL_DEPTH_16S)
301 int * table = orientation_lookup_tables[level* ANGLE_BUCKET_NUMBER + orientation_bucket_index];
302 short * src = (
short*)(original_image->imageData + (
int)v * original_image->widthStep) + (
int)u;
303 short * dst = (
short*)(rotated_patch->imageData);
305 const int length = neighborhood_size * neighborhood_size;
306 for(
int i = 0; i < length; i++)
307 dst[i] = src[table[i]];
311 cerr <<
"keypoint_orientation_corrector::rotate_patch invalid depths" << endl;
312 cerr <<
"depth 1 = " << original_image->depth << endl;
313 cerr <<
"depth 2 = " << rotated_patch->depth << endl;
318 IplImage * _Ix, IplImage * _Iy)
323 int _orientation_bucket_index = orientation_bucket_index(_Ix, _Iy, u, v);
325 return _orientation_bucket_index * 2 * 3.14159f / ANGLE_BUCKET_NUMBER;
329 IplImage * rotated_neighborhood,
330 IplImage * _Ix, IplImage * _Iy,
int level)
332 int _orientation_bucket_index = orientation_bucket_index(_Ix, _Iy, u, v);
334 rotate_patch(image, u, v, rotated_neighborhood, _orientation_bucket_index, level);
336 return _orientation_bucket_index;
340 IplImage * rotated_neighborhood,
341 float orientation_in_radians,
int level)
344 rotate_patchf(image, u, v, rotated_neighborhood, orientation_in_radians);
346 int _orientation_bucket_index = int(orientation_in_radians * ANGLE_BUCKET_NUMBER / (2 * 3.14159));
347 if (_orientation_bucket_index < 0) _orientation_bucket_index = 0;
348 if (_orientation_bucket_index >= ANGLE_BUCKET_NUMBER) _orientation_bucket_index = ANGLE_BUCKET_NUMBER - 1;
349 rotate_patch(image, (
int)(u+.5f), (
int)(v+.5f), rotated_neighborhood, _orientation_bucket_index, level);