mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Use ROI in Keypoint detector
This commit is contained in:
parent
017b62d20d
commit
918026a22c
@ -4,24 +4,48 @@
|
||||
#define INIT_ALLOC (50)
|
||||
#define Compare(X, Y) ((X)>=(Y))
|
||||
|
||||
static kp_t* fast9_detect(const uint8_t* im, int xsize, int ysize, int stride, int b, int* ret_num_corners, rectangle_t *roi);
|
||||
static int pixel[16];
|
||||
static kp_t* fast9_detect(const uint8_t* im, int stride, int b, int* ret_num_corners, rectangle_t *roi);
|
||||
static uint8_t* fast9_score(const uint8_t* i, int stride, kp_t* corners, int num_corners, int b);
|
||||
static kp_t* nonmax_suppression(const kp_t* corners, const uint8_t* scores, int num_corners, int* ret_num_nonmax);
|
||||
|
||||
static void make_offsets(int pixel[], int row_stride)
|
||||
{
|
||||
pixel[0] = 0 + row_stride * 3;
|
||||
pixel[1] = 1 + row_stride * 3;
|
||||
pixel[2] = 2 + row_stride * 2;
|
||||
pixel[3] = 3 + row_stride * 1;
|
||||
pixel[4] = 3 + row_stride * 0;
|
||||
pixel[5] = 3 + row_stride * -1;
|
||||
pixel[6] = 2 + row_stride * -2;
|
||||
pixel[7] = 1 + row_stride * -3;
|
||||
pixel[8] = 0 + row_stride * -3;
|
||||
pixel[9] = -1 + row_stride * -3;
|
||||
pixel[10] = -2 + row_stride * -2;
|
||||
pixel[11] = -3 + row_stride * -1;
|
||||
pixel[12] = -3 + row_stride * 0;
|
||||
pixel[13] = -3 + row_stride * 1;
|
||||
pixel[14] = -2 + row_stride * 2;
|
||||
pixel[15] = -1 + row_stride * 3;
|
||||
}
|
||||
|
||||
kp_t *fast_detect(image_t *image, int threshold, int *ret_num_corners, rectangle_t *roi)
|
||||
{
|
||||
uint8_t* scores;
|
||||
kp_t* nonmax;
|
||||
kp_t* corners=0;
|
||||
int num_corners=0;
|
||||
|
||||
int num_corners;
|
||||
kp_t* corners;
|
||||
uint8_t* scores=0;
|
||||
kp_t* nonmax=0;
|
||||
|
||||
corners = fast9_detect(image->data, image->w, image->h, image->w, threshold, &num_corners, roi);
|
||||
scores = fast9_score(image->data, image->w, corners, num_corners, threshold);
|
||||
nonmax = nonmax_suppression(corners, scores, num_corners, ret_num_corners);
|
||||
make_offsets(pixel, image->w);
|
||||
|
||||
corners = fast9_detect(image->data, image->w, threshold, &num_corners, roi);
|
||||
if (num_corners) {
|
||||
scores = fast9_score(image->data, image->w, corners, num_corners, threshold);
|
||||
nonmax = nonmax_suppression(corners, scores, num_corners, ret_num_corners);
|
||||
xfree(scores);
|
||||
}
|
||||
xfree(corners);
|
||||
xfree(scores);
|
||||
|
||||
return nonmax;
|
||||
}
|
||||
@ -33,7 +57,7 @@ static kp_t* nonmax_suppression(const kp_t* corners, const uint8_t* scores, int
|
||||
int* row_start;
|
||||
int i, j;
|
||||
kp_t* ret_nonmax;
|
||||
const int sz = (int)num_corners;
|
||||
const int sz = (int)num_corners;
|
||||
|
||||
/*Point above points (roughly) to the pixel above the one of interest, if there
|
||||
is a feature there.*/
|
||||
@ -3069,58 +3093,30 @@ static uint8_t fast9_corner_score(const uint8_t* p, const int pixel[], int bstar
|
||||
}
|
||||
}
|
||||
|
||||
static void make_offsets(int pixel[], int row_stride)
|
||||
{
|
||||
pixel[0] = 0 + row_stride * 3;
|
||||
pixel[1] = 1 + row_stride * 3;
|
||||
pixel[2] = 2 + row_stride * 2;
|
||||
pixel[3] = 3 + row_stride * 1;
|
||||
pixel[4] = 3 + row_stride * 0;
|
||||
pixel[5] = 3 + row_stride * -1;
|
||||
pixel[6] = 2 + row_stride * -2;
|
||||
pixel[7] = 1 + row_stride * -3;
|
||||
pixel[8] = 0 + row_stride * -3;
|
||||
pixel[9] = -1 + row_stride * -3;
|
||||
pixel[10] = -2 + row_stride * -2;
|
||||
pixel[11] = -3 + row_stride * -1;
|
||||
pixel[12] = -3 + row_stride * 0;
|
||||
pixel[13] = -3 + row_stride * 1;
|
||||
pixel[14] = -2 + row_stride * 2;
|
||||
pixel[15] = -1 + row_stride * 3;
|
||||
}
|
||||
|
||||
static uint8_t* fast9_score(const uint8_t* i, int stride, kp_t* corners, int num_corners, int b)
|
||||
{
|
||||
int n;
|
||||
uint8_t* scores = (uint8_t*)xalloc(sizeof(uint8_t)* num_corners);
|
||||
|
||||
int pixel[16];
|
||||
make_offsets(pixel, stride);
|
||||
|
||||
for(n=0; n < num_corners; n++)
|
||||
scores[n] = fast9_corner_score(i + corners[n].y*stride + corners[n].x, pixel, b);
|
||||
|
||||
return scores;
|
||||
}
|
||||
|
||||
static kp_t* fast9_detect(const uint8_t* im, int xsize, int ysize, int stride, int b, int* ret_num_corners, rectangle_t *roi)
|
||||
static kp_t* fast9_detect(const uint8_t* im, int stride, int b, int* ret_num_corners, rectangle_t *roi)
|
||||
{
|
||||
int num_corners=0;
|
||||
kp_t* ret_corners;
|
||||
int rsize= INIT_ALLOC;
|
||||
int pixel[16];
|
||||
int x, y;
|
||||
|
||||
ret_corners = (kp_t*)xalloc(sizeof(kp_t)*rsize);
|
||||
make_offsets(pixel, stride);
|
||||
|
||||
for(y=3; y < ysize - 3; y++)
|
||||
for(x=3; x < xsize - 3; x++)
|
||||
{
|
||||
const uint8_t* p = im + y*stride + x;
|
||||
|
||||
int cb = *p + b;
|
||||
int c_b= *p - b;
|
||||
for(int y=roi->y+3; y < roi->h+roi->y-3; y++) {
|
||||
const uint8_t* p = im + y*stride;
|
||||
for(int x=roi->x+3; x < roi->w+roi->x-3; x++, p++) {
|
||||
int cb = *p + b;
|
||||
int c_b= *p - b;
|
||||
if(p[pixel[0]] > cb)
|
||||
if(p[pixel[1]] > cb)
|
||||
if(p[pixel[2]] > cb)
|
||||
@ -6024,28 +6020,22 @@ static kp_t* fast9_detect(const uint8_t* im, int xsize, int ysize, int stride, i
|
||||
continue;
|
||||
if(num_corners == rsize)
|
||||
{
|
||||
rsize*=2;
|
||||
rsize+=INIT_ALLOC;
|
||||
ret_corners = (kp_t*)xrealloc(ret_corners, sizeof(kp_t)*rsize);
|
||||
}
|
||||
|
||||
//check if the description at this position/scale fits inside the image
|
||||
if (x <= KP_SIZE || x >= (xsize-KP_SIZE) ||
|
||||
y <= KP_SIZE || y >= (ysize-KP_SIZE)) {
|
||||
if (x <= (roi->x+KP_SIZE) || x >= ((roi->x+roi->w)-KP_SIZE) ||
|
||||
y <= (roi->y+KP_SIZE) || y >= ((roi->y+roi->h)-KP_SIZE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if kp inside ROI
|
||||
if (roi) {
|
||||
if (x <= (roi->x+KP_SIZE) || x >= ((roi->x+roi->w)-KP_SIZE) ||
|
||||
y <= (roi->y+KP_SIZE) || y >= ((roi->y+roi->h)-KP_SIZE)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ret_corners[num_corners].x = x;
|
||||
ret_corners[num_corners].y = y;
|
||||
num_corners++;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
*ret_num_corners = num_corners;
|
||||
return ret_corners;
|
||||
|
||||
@ -491,8 +491,11 @@ static mp_obj_t py_image_draw_keypoints(mp_obj_t image_obj, mp_obj_t kpts_obj)
|
||||
/* get pointer */
|
||||
image = py_image_cobj(image_obj);
|
||||
kpts = (py_kp_obj_t*)kpts_obj;
|
||||
color_t cl = {.r=0xFF, .g=0xFF, .b=0xFF};
|
||||
|
||||
PY_ASSERT_TRUE(image->bpp == 1);
|
||||
PY_ASSERT_TYPE(kpts_obj, &py_kp_type);
|
||||
|
||||
color_t cl = {.r=0xFF, .g=0xFF, .b=0xFF};
|
||||
for (int i=0; i<kpts->size; i++) {
|
||||
kp_t *kp = &kpts->kpts[i];
|
||||
float co = arm_cos_f32(kp->angle);
|
||||
@ -551,7 +554,7 @@ static mp_obj_t py_image_find_features(mp_obj_t image_obj, mp_obj_t cascade_obj)
|
||||
mp_obj_t objects_list = mp_const_none;
|
||||
|
||||
/* sanity checks */
|
||||
PY_ASSERT_TRUE(sensor.framesize <= FRAMESIZE_QQVGA);
|
||||
PY_ASSERT_TRUE(sensor.framesize <= FRAMESIZE_QCIF);
|
||||
PY_ASSERT_TRUE(sensor.pixformat == PIXFORMAT_GRAYSCALE);
|
||||
|
||||
/* get C image pointer */
|
||||
@ -568,11 +571,12 @@ static mp_obj_t py_image_find_features(mp_obj_t image_obj, mp_obj_t cascade_obj)
|
||||
/* Add detected objects to the list */
|
||||
for (int i=0; i<array_length(objects_array); i++) {
|
||||
struct rectangle *r = array_at(objects_array, 0);
|
||||
mp_obj_t rec_obj[4];
|
||||
rec_obj[0] = mp_obj_new_int(r->x);
|
||||
rec_obj[1] = mp_obj_new_int(r->y);
|
||||
rec_obj[2] = mp_obj_new_int(r->w);
|
||||
rec_obj[3] = mp_obj_new_int(r->h);
|
||||
mp_obj_t rec_obj[4] = {
|
||||
mp_obj_new_int(r->x),
|
||||
mp_obj_new_int(r->y),
|
||||
mp_obj_new_int(r->w),
|
||||
mp_obj_new_int(r->h),
|
||||
};
|
||||
mp_obj_list_append(objects_list, mp_obj_new_tuple(4, rec_obj));
|
||||
}
|
||||
|
||||
@ -617,35 +621,54 @@ static mp_obj_t py_image_find_keypoints(uint n_args, const mp_obj_t *args, mp_ma
|
||||
{
|
||||
int threshold = 20;
|
||||
bool normalized = false;
|
||||
|
||||
int kpts_size = 0;
|
||||
kp_t *kpts = NULL;
|
||||
py_kp_obj_t *kp_obj =NULL;
|
||||
|
||||
/* make sure image is grayscale */
|
||||
image_t *image = py_image_cobj(args[0]);
|
||||
rectangle_t roi={0, 0, image->w, image->h};
|
||||
PY_ASSERT_TRUE(image->bpp == 1);
|
||||
|
||||
/* read var args */ //TODO
|
||||
/* read var args */
|
||||
mp_map_elem_t *kw_thresh = mp_map_lookup(kw_args, MP_OBJ_NEW_QSTR(qstr_from_str("threshold")), MP_MAP_LOOKUP);
|
||||
if (kw_thresh != NULL) {
|
||||
threshold = mp_obj_get_int(kw_thresh->value);
|
||||
}
|
||||
|
||||
mp_map_elem_t *kw_norm = mp_map_lookup(kw_args, MP_OBJ_NEW_QSTR(qstr_from_str("normalized")), MP_MAP_LOOKUP);
|
||||
if (kw_norm != NULL) {
|
||||
normalized = mp_obj_get_int(kw_norm->value);
|
||||
}
|
||||
|
||||
/* run keypoint extractor */
|
||||
int kpts_size = 0;
|
||||
kp_t *kpts = fast_detect(image, threshold, &kpts_size, NULL);
|
||||
freak_find_keypoints(image, kpts, kpts_size, normalized, normalized);
|
||||
mp_map_elem_t *kw_roi = mp_map_lookup(kw_args, MP_OBJ_NEW_QSTR(qstr_from_str("roi")), MP_MAP_LOOKUP);
|
||||
if (kw_roi != NULL) {
|
||||
mp_obj_t *array;
|
||||
mp_obj_get_array_fixed_n(kw_roi->value, 4, &array);
|
||||
roi.x=mp_obj_get_int(array[0]);
|
||||
roi.y=mp_obj_get_int(array[1]);
|
||||
roi.w=mp_obj_get_int(array[2]);
|
||||
roi.h=mp_obj_get_int(array[3]);
|
||||
}
|
||||
|
||||
/* return keypoints MP object */
|
||||
kp_obj = m_new_obj(py_kp_obj_t);
|
||||
kp_obj->base.type = &py_kp_type;
|
||||
kp_obj->kpts = kpts;
|
||||
kp_obj->size = kpts_size;
|
||||
kp_obj->threshold = threshold;
|
||||
kp_obj->normalized = normalized;
|
||||
return kp_obj;
|
||||
/* run keypoint extractor on ROI */
|
||||
kpts = fast_detect(image, threshold, &kpts_size, &roi);
|
||||
|
||||
if (kpts_size) {
|
||||
/* run keypoint descriptor */
|
||||
freak_find_keypoints(image, kpts, kpts_size, normalized, normalized);
|
||||
|
||||
/* return keypoints MP object */
|
||||
kp_obj = m_new_obj(py_kp_obj_t);
|
||||
kp_obj->base.type = &py_kp_type;
|
||||
kp_obj->kpts = kpts;
|
||||
kp_obj->size = kpts_size;
|
||||
kp_obj->threshold = threshold;
|
||||
kp_obj->normalized = normalized;
|
||||
return kp_obj;
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
static mp_obj_t py_image_match_keypoints(uint n_args, const mp_obj_t *args)
|
||||
@ -712,7 +735,7 @@ mp_obj_t py_image_load_cascade(mp_obj_t path_obj)
|
||||
/* detection parameters */
|
||||
struct cascade cascade = {
|
||||
.step = 2,
|
||||
.scale_factor = 0.35f,
|
||||
.scale_factor = 0.5f,
|
||||
};
|
||||
|
||||
const char *path = mp_obj_str_get_str(path_obj);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user