mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Add a list of matching keypoints to keypoints match object.
This commit is contained in:
parent
eabdcbbbca
commit
f2431de175
@ -1176,7 +1176,7 @@ void agast_detect(image_t *image, array_t *keypoints, int threshold, rectangle_t
|
||||
/* ORB descriptor */
|
||||
array_t *orb_find_keypoints(image_t *image, bool normalized, int threshold,
|
||||
float scale_factor, int max_keypoints, corner_detector_t corner_detector, rectangle_t *roi);
|
||||
int orb_match_keypoints(array_t *kpts1, array_t *kpts2, int threshold, rectangle_t *r, point_t *c, int *angle);
|
||||
int orb_match_keypoints(array_t *kpts1, array_t *kpts2, int *match, int threshold, rectangle_t *r, point_t *c, int *angle);
|
||||
int orb_filter_keypoints(array_t *kpts, rectangle_t *r, point_t *c);
|
||||
int orb_save_descriptor(FIL *fp, array_t *kpts);
|
||||
int orb_load_descriptor(FIL *fp, array_t *kpts);
|
||||
|
||||
@ -479,7 +479,7 @@ static inline uint32_t popcount(uint32_t i)
|
||||
return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
|
||||
}
|
||||
|
||||
static kp_t *find_best_match(kp_t *kp1, array_t *kpts, int *dist_out1, int *dist_out2)
|
||||
static kp_t *find_best_match(kp_t *kp1, array_t *kpts, int *dist_out1, int *dist_out2, int *index)
|
||||
{
|
||||
kp_t *min_kp=NULL;
|
||||
int min_dist1 = MAX_KP_DIST;
|
||||
@ -496,6 +496,7 @@ static kp_t *find_best_match(kp_t *kp1, array_t *kpts, int *dist_out1, int *dist
|
||||
}
|
||||
|
||||
if (dist < min_dist1) {
|
||||
*index = i;
|
||||
min_kp = kp2;
|
||||
min_dist2 = min_dist1;
|
||||
min_dist1 = dist;
|
||||
@ -508,7 +509,7 @@ static kp_t *find_best_match(kp_t *kp1, array_t *kpts, int *dist_out1, int *dist
|
||||
return min_kp;
|
||||
}
|
||||
|
||||
int orb_match_keypoints(array_t *kpts1, array_t *kpts2, int threshold, rectangle_t *r, point_t *c, int *angle)
|
||||
int orb_match_keypoints(array_t *kpts1, array_t *kpts2, int *match, int threshold, rectangle_t *r, point_t *c, int *angle)
|
||||
{
|
||||
int matches=0;
|
||||
int cx = 0, cy = 0;
|
||||
@ -522,20 +523,22 @@ int orb_match_keypoints(array_t *kpts1, array_t *kpts2, int threshold, rectangle
|
||||
// The first test is based on the distance ratio between the two best matches for a feature, to remove ambiguous matches.
|
||||
// Second test is the symmetry test (corss-matching) both points in a match must be the best matching feature of each other.
|
||||
for (int i=0; i<kpts1_size; i++) {
|
||||
int kp_index1 = 0;
|
||||
int kp_index2 = 0;
|
||||
int min_dist1 = 0;
|
||||
int min_dist2 = 0;
|
||||
kp_t *min_kp = NULL;
|
||||
kp_t *kp1 = array_at(kpts1, i);
|
||||
|
||||
// Find the best match in second set
|
||||
min_kp = find_best_match(kp1, kpts2, &min_dist1, &min_dist2);
|
||||
min_kp = find_best_match(kp1, kpts2, &min_dist1, &min_dist2, &kp_index2);
|
||||
// Test the distance ratio between the best two matches
|
||||
if ((min_dist1*100/min_dist2) > threshold) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Cross-match the keypoint in the first set
|
||||
kp_t *kp2 = find_best_match(min_kp, kpts1, &min_dist1, &min_dist2);
|
||||
kp_t *kp2 = find_best_match(min_kp, kpts1, &min_dist1, &min_dist2, &kp_index1);
|
||||
// Test the distance ratio between the best two matches
|
||||
if ((min_dist1*100/min_dist2) > threshold) {
|
||||
continue;
|
||||
@ -553,6 +556,8 @@ int orb_match_keypoints(array_t *kpts1, array_t *kpts2, int threshold, rectangle
|
||||
if (angle >= 0 && angle < 360) {
|
||||
angles[angle]++;
|
||||
}
|
||||
*match++ = kp_index1;
|
||||
*match++ = kp_index2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -124,12 +124,14 @@ static const mp_obj_type_t py_lbp_type = {
|
||||
};
|
||||
|
||||
// Keypoints match object /////////////////////////////////////////////////////
|
||||
#define kptmatch_obj_size 8
|
||||
#define kptmatch_obj_size 9
|
||||
typedef struct _py_kptmatch_obj_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_t cx, cy;
|
||||
mp_obj_t x, y, w, h;
|
||||
mp_obj_t count, theta;
|
||||
mp_obj_t count;
|
||||
mp_obj_t theta;
|
||||
mp_obj_t match;
|
||||
} py_kptmatch_obj_t;
|
||||
|
||||
static void py_kptmatch_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind)
|
||||
@ -162,19 +164,21 @@ static mp_obj_t py_kptmatch_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t va
|
||||
case 5: return self->h;
|
||||
case 6: return self->count;
|
||||
case 7: return self->theta;
|
||||
case 8: return self->match;
|
||||
}
|
||||
}
|
||||
return MP_OBJ_NULL; // op not supported
|
||||
}
|
||||
|
||||
mp_obj_t py_kptmatch_cx(mp_obj_t self_in) { return ((py_kptmatch_obj_t *) self_in)->cx; }
|
||||
mp_obj_t py_kptmatch_cy(mp_obj_t self_in) { return ((py_kptmatch_obj_t *) self_in)->cy; }
|
||||
mp_obj_t py_kptmatch_x (mp_obj_t self_in) { return ((py_kptmatch_obj_t *) self_in)->x; }
|
||||
mp_obj_t py_kptmatch_y (mp_obj_t self_in) { return ((py_kptmatch_obj_t *) self_in)->y; }
|
||||
mp_obj_t py_kptmatch_w (mp_obj_t self_in) { return ((py_kptmatch_obj_t *) self_in)->w; }
|
||||
mp_obj_t py_kptmatch_h (mp_obj_t self_in) { return ((py_kptmatch_obj_t *) self_in)->h; }
|
||||
mp_obj_t py_kptmatch_count(mp_obj_t self_in) { return ((py_kptmatch_obj_t *) self_in)->count; }
|
||||
mp_obj_t py_kptmatch_theta(mp_obj_t self_in) { return ((py_kptmatch_obj_t *) self_in)->theta; }
|
||||
mp_obj_t py_kptmatch_cx(mp_obj_t self_in) { return ((py_kptmatch_obj_t *) self_in)->cx; }
|
||||
mp_obj_t py_kptmatch_cy(mp_obj_t self_in) { return ((py_kptmatch_obj_t *) self_in)->cy; }
|
||||
mp_obj_t py_kptmatch_x (mp_obj_t self_in) { return ((py_kptmatch_obj_t *) self_in)->x; }
|
||||
mp_obj_t py_kptmatch_y (mp_obj_t self_in) { return ((py_kptmatch_obj_t *) self_in)->y; }
|
||||
mp_obj_t py_kptmatch_w (mp_obj_t self_in) { return ((py_kptmatch_obj_t *) self_in)->w; }
|
||||
mp_obj_t py_kptmatch_h (mp_obj_t self_in) { return ((py_kptmatch_obj_t *) self_in)->h; }
|
||||
mp_obj_t py_kptmatch_count(mp_obj_t self_in) { return ((py_kptmatch_obj_t *) self_in)->count; }
|
||||
mp_obj_t py_kptmatch_theta(mp_obj_t self_in) { return ((py_kptmatch_obj_t *) self_in)->theta; }
|
||||
mp_obj_t py_kptmatch_match(mp_obj_t self_in) { return ((py_kptmatch_obj_t *) self_in)->match; }
|
||||
mp_obj_t py_kptmatch_rect(mp_obj_t self_in) {
|
||||
return mp_obj_new_tuple(4, (mp_obj_t []) {((py_kptmatch_obj_t *) self_in)->x,
|
||||
((py_kptmatch_obj_t *) self_in)->y,
|
||||
@ -182,15 +186,16 @@ mp_obj_t py_kptmatch_rect(mp_obj_t self_in) {
|
||||
((py_kptmatch_obj_t *) self_in)->h});
|
||||
}
|
||||
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_kptmatch_cx_obj, py_kptmatch_cx);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_kptmatch_cy_obj, py_kptmatch_cy);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_kptmatch_x_obj, py_kptmatch_x);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_kptmatch_y_obj, py_kptmatch_y);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_kptmatch_w_obj, py_kptmatch_w);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_kptmatch_h_obj, py_kptmatch_h);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_kptmatch_count_obj, py_kptmatch_count);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_kptmatch_theta_obj, py_kptmatch_theta);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_kptmatch_rect_obj, py_kptmatch_rect);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_kptmatch_cx_obj, py_kptmatch_cx);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_kptmatch_cy_obj, py_kptmatch_cy);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_kptmatch_x_obj, py_kptmatch_x);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_kptmatch_y_obj, py_kptmatch_y);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_kptmatch_w_obj, py_kptmatch_w);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_kptmatch_h_obj, py_kptmatch_h);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_kptmatch_count_obj, py_kptmatch_count);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_kptmatch_theta_obj, py_kptmatch_theta);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_kptmatch_match_obj, py_kptmatch_match);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_kptmatch_rect_obj, py_kptmatch_rect);
|
||||
|
||||
STATIC const mp_rom_map_elem_t py_kptmatch_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_cx), MP_ROM_PTR(&py_kptmatch_cx_obj) },
|
||||
@ -201,6 +206,7 @@ STATIC const mp_rom_map_elem_t py_kptmatch_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_h), MP_ROM_PTR(&py_kptmatch_h_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&py_kptmatch_count_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_theta), MP_ROM_PTR(&py_kptmatch_theta_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_match), MP_ROM_PTR(&py_kptmatch_match_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_rect), MP_ROM_PTR(&py_kptmatch_rect_obj) },
|
||||
};
|
||||
|
||||
@ -4559,29 +4565,46 @@ static mp_obj_t py_image_match_descriptor(uint n_args, const mp_obj_t *args, mp_
|
||||
PY_ASSERT_TRUE_MSG((threshold >=0 && threshold <= 100), "Expected threshold between 0 and 100");
|
||||
|
||||
int theta = 0; // Estimated angle of rotation
|
||||
int match = 0; // Number of matches
|
||||
point_t c = {0}; // Centroid
|
||||
rectangle_t r = {0};// Bounding rectangle
|
||||
int count = 0; // Number of matches
|
||||
point_t c = {0}; // Centroid
|
||||
rectangle_t r = {0}; // Bounding rectangle
|
||||
// List of matching keypoints indices
|
||||
mp_obj_t match_list = mp_obj_new_list(0, NULL);
|
||||
|
||||
if (array_length(kpts1->kpts) && array_length(kpts1->kpts)) {
|
||||
int *match = fb_alloc(array_length(kpts1->kpts) * sizeof(int) * 2);
|
||||
|
||||
// Match the two keypoint sets
|
||||
match = orb_match_keypoints(kpts1->kpts, kpts2->kpts, threshold, &r, &c, &theta);
|
||||
count = orb_match_keypoints(kpts1->kpts, kpts2->kpts, match, threshold, &r, &c, &theta);
|
||||
|
||||
// Add matching keypoints to Python list.
|
||||
for (int i=0; i<count; i+=2) {
|
||||
mp_obj_t index_obj[2] = {
|
||||
mp_obj_new_int(match[i+0]),
|
||||
mp_obj_new_int(match[i+1]),
|
||||
};
|
||||
mp_obj_list_append(match_list, mp_obj_new_tuple(2, index_obj));
|
||||
}
|
||||
|
||||
// Free match list
|
||||
fb_free();
|
||||
|
||||
if (filter_outliers == true) {
|
||||
match = orb_filter_keypoints(kpts2->kpts, &r, &c);
|
||||
count = orb_filter_keypoints(kpts2->kpts, &r, &c);
|
||||
}
|
||||
}
|
||||
|
||||
py_kptmatch_obj_t *o = m_new_obj(py_kptmatch_obj_t);
|
||||
o->base.type = &py_kptmatch_type;
|
||||
o->cx = mp_obj_new_int(c.x);
|
||||
o->cy = mp_obj_new_int(c.y);
|
||||
o->x = mp_obj_new_int(r.x);
|
||||
o->y = mp_obj_new_int(r.y);
|
||||
o->w = mp_obj_new_int(r.w);
|
||||
o->h = mp_obj_new_int(r.h);
|
||||
o->count = mp_obj_new_int(match);
|
||||
o->cx = mp_obj_new_int(c.x);
|
||||
o->cy = mp_obj_new_int(c.y);
|
||||
o->x = mp_obj_new_int(r.x);
|
||||
o->y = mp_obj_new_int(r.y);
|
||||
o->w = mp_obj_new_int(r.w);
|
||||
o->h = mp_obj_new_int(r.h);
|
||||
o->count = mp_obj_new_int(count);
|
||||
o->theta = mp_obj_new_int(theta);
|
||||
o->match = match_list;
|
||||
match_obj = o;
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Descriptor type is not supported"));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user