/* * This file is part of the OpenMV project. * Copyright (c) 2013/2014 Ibrahim Abdelkader * This work is licensed under the MIT license, see the file LICENSE for details. * * Image Python module. * */ #include "mp.h" #include "imlib.h" #include "array.h" #include "sensor.h" #include "xalloc.h" #include "py_assert.h" #include "py_image.h" #include "py_file.h" #include "arm_math.h" extern struct sensor_dev sensor; static const mp_obj_type_t py_cascade_type; static const mp_obj_type_t py_image_type; /* Haar Cascade */ typedef struct _py_cascade_obj_t { mp_obj_base_t base; struct cascade _cobj; } py_cascade_obj_t; void *py_cascade_cobj(mp_obj_t cascade) { PY_ASSERT_TYPE(cascade, &py_cascade_type); return &((py_cascade_obj_t *)cascade)->_cobj; } static void py_cascade_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { py_cascade_obj_t *self = self_in; /* print some info */ print(env, "width:%d height:%d n_stages:%d n_features:%d n_rectangles:%d\n", self->_cobj.window.w, self->_cobj.window.h, self->_cobj.n_stages, self->_cobj.n_features, self->_cobj.n_rectangles); } static const mp_obj_type_t py_cascade_type = { { &mp_type_type }, .name = MP_QSTR_Cascade, .print = py_cascade_print, }; /* Keypoints object */ typedef struct _py_kp_obj_t { mp_obj_base_t base; int size; kp_t *kpts; int threshold; bool normalized; } py_kp_obj_t; static void py_kp_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { py_kp_obj_t *self = self_in; print(env, "size:%d threshold:%d normalized:%d\n", self->size, self->threshold, self->normalized); } static const mp_obj_type_t py_kp_type = { { &mp_type_type }, .name = MP_QSTR_kp_desc, .print = py_kp_print, }; /* LBP descriptor */ typedef struct _py_lbp_obj_t { mp_obj_base_t base; uint8_t *hist; } py_lbp_obj_t; static void py_lbp_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { print(env, ""); } static const mp_obj_type_t py_lbp_type = { { &mp_type_type }, .name = MP_QSTR_lbp_desc, .print = py_lbp_print, }; /* Image */ typedef struct _py_image_obj_t { mp_obj_base_t base; struct image _cobj; } py_image_obj_t; void *py_image_cobj(mp_obj_t image) { PY_ASSERT_TYPE(image, &py_image_type); return &((py_image_obj_t *)image)->_cobj; } static void py_image_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { py_image_obj_t *self = self_in; print(env, "", self->_cobj.w, self->_cobj.h, self->_cobj.bpp); } static mp_int_t py_image_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { image_t *image = py_image_cobj(self_in); if (flags == MP_BUFFER_READ) { bufinfo->buf = (void*)image->pixels; if (image->bpp > 2) { //JPEG bufinfo->len = image->bpp; } else { bufinfo->len = image->w*image->h*image->bpp; } bufinfo->typecode = 'b'; return 0; } else { // disable write for now bufinfo->buf = NULL; bufinfo->len = 0; bufinfo->typecode = -1; return 1; } } static mp_obj_t py_image_size(mp_obj_t self_in) { uint32_t len; image_t *image = py_image_cobj(self_in); if (image->bpp > 2) { //JPEG len = image->bpp; } else { len = image->w*image->h*image->bpp; } return mp_obj_new_int(len); } static mp_obj_t py_image_save(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { int res; image_t *image = py_image_cobj(args[0]); const char *path = mp_obj_str_get_str(args[1]); mp_map_elem_t *kw_subimage = mp_map_lookup(kw_args, MP_OBJ_NEW_QSTR(qstr_from_str("subimage")), MP_MAP_LOOKUP); if (kw_subimage != NULL) { mp_obj_t *array; mp_obj_get_array_fixed_n(kw_subimage->value, 4, &array); rectangle_t r = { mp_obj_get_int(array[0]), mp_obj_get_int(array[1]), mp_obj_get_int(array[2]), mp_obj_get_int(array[3]), }; res = imlib_save_image(image, path, &r); } else { res = imlib_save_image(image, path, NULL); } if (res != FR_OK) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, ffs_strerror(res))); } return mp_const_true; } static mp_obj_t py_image_scale(mp_obj_t image_obj, mp_obj_t size_obj) { int w,h; mp_obj_t *array; image_t *src_image = NULL; /* get C image pointer */ src_image = py_image_cobj(image_obj); /* get x,y */ mp_obj_get_array_fixed_n(size_obj, 2, &array); w = mp_obj_get_int(array[0]); h = mp_obj_get_int(array[1]); image_t dst_image = { .w=w, .h=h, .bpp=src_image->bpp, .pixels=xalloc(w*h*src_image->bpp) }; imlib_scale(src_image, &dst_image, INTERP_BILINEAR); *src_image = dst_image; return image_obj; } static mp_obj_t py_image_scaled(mp_obj_t image_obj, mp_obj_t size_obj) { int w,h; mp_obj_t *array; image_t *src_image = NULL; /* get C image pointer */ src_image = py_image_cobj(image_obj); /* get x,y */ mp_obj_get_array_fixed_n(size_obj, 2, &array); w = mp_obj_get_int(array[0]); h = mp_obj_get_int(array[1]); image_t dst_image = { .w=w, .h=h, .bpp=src_image->bpp, .pixels=xalloc(w*h*src_image->bpp) }; imlib_scale(src_image, &dst_image, INTERP_NEAREST); return py_image_from_struct(&dst_image); } static mp_obj_t py_image_subimg(mp_obj_t image_obj, mp_obj_t subimg_obj) { rectangle_t r; image_t *image; mp_obj_t *array; /* image pointer */ image = py_image_cobj(image_obj); /* sub image */ mp_obj_get_array_fixed_n(subimg_obj, 4, &array); r.x = mp_obj_get_int(array[0]); r.y = mp_obj_get_int(array[1]); r.w = mp_obj_get_int(array[2]); r.h = mp_obj_get_int(array[3]); image_t subimg = { .w=r.w, .h=r.h, .bpp=image->bpp, .pixels=xalloc(r.w*r.h*image->bpp) }; imlib_subimage(image, &subimg, r.x, r.y); return py_image_from_struct(&subimg); } static mp_obj_t py_image_blit(mp_obj_t dst_image_obj, mp_obj_t src_image_obj, mp_obj_t offset_obj) { int x,y; image_t *src_image = NULL; image_t *dst_image = NULL; /* get C image pointer */ src_image = py_image_cobj(src_image_obj); dst_image = py_image_cobj(dst_image_obj); /* get x,y */ mp_obj_t *array; mp_obj_get_array_fixed_n(offset_obj, 2, &array); x = mp_obj_get_int(array[0]); y = mp_obj_get_int(array[1]); if ((src_image->w+x)>dst_image->w || (src_image->h+y)>dst_image->h) { printf("src image > dst image\n"); return mp_const_none; } imlib_blit(src_image, dst_image, x, y); return mp_const_none; } static mp_obj_t py_image_blend(mp_obj_t dst_image_obj, mp_obj_t src_image_obj, mp_obj_t param_obj) { int x,y; float alpha; image_t *src_image = NULL; image_t *dst_image = NULL; /* get C image pointer */ src_image = py_image_cobj(src_image_obj); dst_image = py_image_cobj(dst_image_obj); /* get x,y,alpha */ mp_obj_t *array; mp_obj_get_array_fixed_n(param_obj, 3, &array); x = mp_obj_get_int(array[0]); y = mp_obj_get_int(array[1]); alpha = mp_obj_get_float(array[2]); if ((src_image->w+x)>dst_image->w || (src_image->h+y)>dst_image->h) { printf("src image > dst image\n"); return mp_const_none; } imlib_blend(src_image, dst_image, x, y, (uint8_t)(alpha*256)); return mp_const_none; } static mp_obj_t py_image_histeq(mp_obj_t image_obj) { struct image *image; /* get image pointer */ image = (struct image*) py_image_cobj(image_obj); /* sanity checks */ PY_ASSERT_TRUE(image->bpp == 1); imlib_histeq(image); return mp_const_none; } static mp_obj_t py_image_median(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { int ksize = 1; /* get image pointer */ image_t *image = py_image_cobj(args[0]); mp_map_elem_t *kw_ksize = mp_map_lookup(kw_args, MP_OBJ_NEW_QSTR(qstr_from_str("size")), MP_MAP_LOOKUP); if (kw_ksize != NULL) { ksize = mp_obj_get_int(kw_ksize->value); } imlib_median_filter(image, ksize); return mp_const_none; } static mp_obj_t py_image_invert(mp_obj_t image_obj) { image_t *image; image = py_image_cobj(image_obj); /* Sanity checks */ PY_ASSERT_TRUE(image->bpp == 1); /* Threshold image */ imlib_invert(image); return mp_const_none; } static mp_obj_t py_image_binary(mp_obj_t image_obj, mp_obj_t threshold) { image_t *image; /* sanity checks */ PY_ASSERT_TRUE(sensor.framesize <= FRAMESIZE_QCIF); PY_ASSERT_TRUE(sensor.pixformat == PIXFORMAT_GRAYSCALE); /* read arguments */ image = py_image_cobj(image_obj); int thresh = mp_obj_get_int(threshold); /* Threshold image */ imlib_binary(image, thresh); return mp_const_none; } static mp_obj_t py_image_threshold(mp_obj_t image_obj, mp_obj_t color_list_obj, mp_obj_t threshold) { color_t *color; image_t *image; /* sanity checks */ PY_ASSERT_TRUE(sensor.pixformat == PIXFORMAT_RGB565); PY_ASSERT_TRUE(sensor.framesize <= FRAMESIZE_QCIF); /* read arguments */ image = py_image_cobj(image_obj); int thresh = mp_obj_get_int(threshold); /* returned image */ image_t bimage = { .w=image->w, .h=image->h, .bpp=1, .pixels=image->data+(image->w*image->h*image->bpp) }; /* copy color list */ uint len; mp_obj_t *color_arr; mp_obj_get_array(color_list_obj, &len, &color_arr); color = xalloc(len*sizeof*color); for (int i=0; ibpp==1); image_t dst_image = { .w=src_image->w, .h=src_image->h, .bpp=2, .pixels=xalloc(src_image->w*src_image->h*2) }; imlib_rainbow(src_image, &dst_image); *src_image = dst_image; return src_image_obj; } static mp_obj_t py_image_compress(mp_obj_t image_obj, mp_obj_t quality) { image_t *image = py_image_cobj(image_obj); image_t cimage = { .w=image->w, .h=image->h, .bpp=0, .pixels= NULL }; jpeg_compress(image, &cimage, mp_obj_get_int(quality)); return py_image_from_struct(&cimage); } static mp_obj_t py_image_draw_line(mp_obj_t image_obj, mp_obj_t line_obj) { /* get image pointer */ struct image *image; image = py_image_cobj(image_obj); mp_obj_t *array; mp_obj_get_array_fixed_n(line_obj, 4, &array); int x0 = mp_obj_get_int(array[0]); int y0 = mp_obj_get_int(array[1]); int x1 = mp_obj_get_int(array[2]); int y1 = mp_obj_get_int(array[3]); imlib_draw_line(image, x0, y0, x1, y1); return mp_const_none; } static mp_obj_t py_image_draw_circle(mp_obj_t image_obj, mp_obj_t c_obj, mp_obj_t r_obj) { int cx, cy, r; mp_obj_t *array; struct image *image; color_t c = {.r=0xFF, .g=0xFF, .b=0xFF}; /* get image pointer */ image = py_image_cobj(image_obj); /* center */ mp_obj_get_array_fixed_n(c_obj, 2, &array); cx = mp_obj_get_int(array[0]); cy = mp_obj_get_int(array[1]); /* radius */ r = mp_obj_get_int(r_obj); imlib_draw_circle(image, cx, cy, r, &c); return mp_const_none; } static mp_obj_t py_image_draw_string(uint n_args, const mp_obj_t *args) { int x = mp_obj_get_int(args[1]); int y = mp_obj_get_int(args[2]); image_t *image =py_image_cobj(args[0]); const char *str = mp_obj_str_get_str(args[3]); color_t c = {.r=0xFF, .g=0xFF, .b=0xFF}; if (n_args == 5) { // get color mp_obj_t *array; mp_obj_get_array_fixed_n(args[4], 3, &array); c.r = mp_obj_get_int(array[0]); c.g = mp_obj_get_int(array[1]); c.b = mp_obj_get_int(array[2]); } imlib_draw_string(image, x, y, str, &c); return mp_const_none; } static mp_obj_t py_image_erode(mp_obj_t image_obj, mp_obj_t ksize_obj) { image_t *image = NULL; image = py_image_cobj(image_obj); /* sanity checks */ PY_ASSERT_TRUE(image->bpp==1); imlib_erode(image, mp_obj_get_int(ksize_obj)); return mp_const_none; } static mp_obj_t py_image_dilate(mp_obj_t image_obj, mp_obj_t ksize_obj) { image_t *image = NULL; image = py_image_cobj(image_obj); /* sanity checks */ PY_ASSERT_TRUE(image->bpp==1); imlib_dilate(image, mp_obj_get_int(ksize_obj)); return mp_const_none; } static mp_obj_t py_image_morph(mp_obj_t image_obj, mp_obj_t ksize_obj) { image_t *image = NULL; image = py_image_cobj(image_obj); /* sanity checks */ PY_ASSERT_TRUE(image->bpp==1); imlib_morph(image, NULL, mp_obj_get_int(ksize_obj)); return mp_const_none; } static mp_obj_t py_image_draw_rectangle(mp_obj_t image_obj, mp_obj_t rectangle_obj) { struct rectangle r; struct image *image; mp_obj_t *array; mp_obj_get_array_fixed_n(rectangle_obj, 4, &array); r.x = mp_obj_get_int(array[0]); r.y = mp_obj_get_int(array[1]); r.w = mp_obj_get_int(array[2]); r.h = mp_obj_get_int(array[3]); /* get image pointer */ image = py_image_cobj(image_obj); imlib_draw_rectangle(image, &r); return mp_const_none; } static mp_obj_t py_image_draw_keypoints(mp_obj_t image_obj, mp_obj_t kpts_obj) { image_t *image = NULL; py_kp_obj_t *kpts=NULL; /* get pointer */ image = py_image_cobj(image_obj); kpts = (py_kp_obj_t*)kpts_obj; 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; isize; i++) { kp_t *kp = &kpts->kpts[i]; float co = arm_cos_f32(kp->angle); float si = arm_sin_f32(kp->angle); imlib_draw_line(image, kp->x, kp->y, kp->x+(co*10), kp->y+(si*10)); imlib_draw_circle(image, kp->x, kp->y, 4, &cl); } return mp_const_none; } static mp_obj_t py_image_find_blobs(mp_obj_t image_obj) { /* C stuff */ array_t *blobs; struct image *image; mp_obj_t blob_obj[6]; /* MP List */ mp_obj_t objects_list = mp_const_none; /* get image pointer */ image = py_image_cobj(image_obj); /* run color dector */ blobs = imlib_count_blobs(image); /* Create empty Python list */ objects_list = mp_obj_new_list(0, NULL); if (array_length(blobs)) { for (int j=0; jx); blob_obj[1] = mp_obj_new_int(r->y); blob_obj[2] = mp_obj_new_int(r->w); blob_obj[3] = mp_obj_new_int(r->h); blob_obj[4] = mp_obj_new_int(r->c); blob_obj[5] = mp_obj_new_int(r->id); mp_obj_list_append(objects_list, mp_obj_new_tuple(6, blob_obj)); } } array_free(blobs); return objects_list; } static mp_obj_t py_image_find_features(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { struct image *image = NULL; struct cascade *cascade = NULL; struct array *objects_array=NULL; mp_obj_t objects_list = mp_const_none; /* sanity checks */ PY_ASSERT_TRUE(sensor.framesize <= FRAMESIZE_QCIF); PY_ASSERT_TRUE(sensor.pixformat == PIXFORMAT_GRAYSCALE); /* read arguments */ image = py_image_cobj(args[0]); cascade = py_cascade_cobj(args[1]); /* set some defaults */ cascade->threshold = 0.65f; cascade->scale_factor = 1.65f; /* read kw 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) { cascade->threshold = mp_obj_get_float(kw_thresh->value); } mp_map_elem_t *kw_scalef = mp_map_lookup(kw_args, MP_OBJ_NEW_QSTR(qstr_from_str("scale")), MP_MAP_LOOKUP); if (kw_scalef != NULL) { cascade->scale_factor = mp_obj_get_float(kw_scalef->value); } /* Detect objects */ objects_array = imlib_detect_objects(image, cascade); /* Create empty Python list */ objects_list = mp_obj_new_list(0, NULL); /* Add detected objects to the list */ for (int i=0; ix), 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)); } /* Free the objects array */ array_free(objects_array); return objects_list; } static mp_obj_t py_image_find_template(mp_obj_t image_obj, mp_obj_t template_obj, mp_obj_t threshold) { struct rectangle r; struct image *image = NULL; struct image *template = NULL; mp_obj_t rec_obj[4]; mp_obj_t obj=mp_const_none; /* sanity checks */ PY_ASSERT_TRUE(sensor.framesize <= FRAMESIZE_QQVGA); PY_ASSERT_TRUE(sensor.pixformat == PIXFORMAT_GRAYSCALE); /* get C image pointer */ image = py_image_cobj(image_obj); template= py_image_cobj(template_obj); float t = mp_obj_get_float(threshold); /* look for object */ float corr = imlib_template_match(image, template, &r); //printf("t:%f coor:%f\n", (double)t, (double)corr); if (corr > t) { 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); obj = mp_obj_new_tuple(4, rec_obj); } return obj; } static mp_obj_t py_image_find_keypoints(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { 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 */ 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); } 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]); } /* 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_find_lbp(mp_obj_t image_obj, mp_obj_t roi_obj) { image_t *image; py_lbp_obj_t *lbp_obj; image = py_image_cobj(image_obj); PY_ASSERT_TRUE(image->bpp == 1); mp_obj_t *array; mp_obj_get_array_fixed_n(roi_obj, 4, &array); rectangle_t roi = { mp_obj_get_int(array[0]), mp_obj_get_int(array[1]), mp_obj_get_int(array[2]), mp_obj_get_int(array[3]), }; lbp_obj = m_new_obj(py_lbp_obj_t); lbp_obj->base.type = &py_lbp_type; lbp_obj->hist = imlib_lbp_cascade(image, &roi); return lbp_obj; } static mp_obj_t py_image_match_keypoints(uint n_args, const mp_obj_t *args) { image_t *image = py_image_cobj(args[0]); py_kp_obj_t *kpts1 = ((py_kp_obj_t*)args[1]); py_kp_obj_t *kpts2 = ((py_kp_obj_t*)args[2]); int threshold = mp_obj_get_int(args[3]); // sanity checks PY_ASSERT_TRUE(image->bpp == 1); PY_ASSERT_TYPE(kpts1, &py_kp_type); PY_ASSERT_TYPE(kpts2, &py_kp_type); if (kpts1->size == 0 || kpts2->size == 0) { return mp_const_none; } // match the keypoint sets int16_t *kpts_match = freak_match_keypoints(kpts1->kpts, kpts1->size, kpts2->kpts, kpts2->size, threshold); int match=0, cx=0, cy=0; //color_t cl = {.r=0xFF, .g=0xFF, .b=0xFF}; for (int i=0; isize; i++) { if (kpts_match[i] != -1) { kp_t *kp = &kpts2->kpts[kpts_match[i]]; cx += kp->x; cy += kp->y; match++; } } if (match>=(kpts1->size/16)) { mp_obj_t rec_obj[2] = { mp_obj_new_int(cx/match), mp_obj_new_int(cy/match), }; return mp_obj_new_tuple(2, rec_obj); } return mp_const_none; } static mp_obj_t py_image_match_lbp(mp_obj_t image_obj, mp_obj_t d0_obj, mp_obj_t d1_obj) { // image_t *image; // image = py_image_cobj(image_obj); py_lbp_obj_t *d0 = ((py_lbp_obj_t*)d0_obj); py_lbp_obj_t *d1 = ((py_lbp_obj_t*)d1_obj); return mp_obj_new_int(imlib_lbp_desc_distance(d0->hist, d1->hist)); } mp_obj_t py_image_load_image(mp_obj_t path_obj) { mp_obj_t image_obj =NULL; struct image *image; const char *path = mp_obj_str_get_str(path_obj); image_obj = py_image(0, 0, 0, 0); /* get image pointer */ image = py_image_cobj(image_obj); int res = imlib_load_image(image, path); if (res != FR_OK) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, ffs_strerror(res))); } return image_obj; } mp_obj_t py_image_load_cascade(mp_obj_t path_obj) { py_cascade_obj_t *o =NULL; /* detection parameters */ struct cascade cascade = { .step = 2, }; const char *path = mp_obj_str_get_str(path_obj); int res = imlib_load_cascade(&cascade, path); if (res != FR_OK) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, ffs_strerror(res))); } o = m_new_obj(py_cascade_obj_t); o->base.type = &py_cascade_type; o->_cobj = cascade; return o; } mp_obj_t py_image_load_descriptor(mp_obj_t path_obj) { kp_t *kpts=NULL; int kpts_size =0; py_kp_obj_t *kp_obj =NULL; const char *path = mp_obj_str_get_str(path_obj); int res = freak_load_descriptor(&kpts, &kpts_size, path); if (res != FR_OK) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, ffs_strerror(res))); } /* 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 = 10; kp_obj->normalized = false; return kp_obj; } mp_obj_t py_image_load_lbp(mp_obj_t path_obj) { py_lbp_obj_t *lbp = m_new_obj(py_lbp_obj_t); lbp->base.type = &py_lbp_type; int res = imlib_lbp_desc_load(mp_obj_str_get_str(path_obj), &lbp->hist); if (res != FR_OK) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, ffs_strerror(res))); } return lbp; } mp_obj_t py_image_save_descriptor(mp_obj_t path_obj, mp_obj_t kpts_obj) { py_kp_obj_t *kpts = ((py_kp_obj_t*)kpts_obj); const char *path = mp_obj_str_get_str(path_obj); int res = freak_save_descriptor(kpts->kpts, kpts->size, path); if (res != FR_OK) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, ffs_strerror(res))); } return mp_const_true; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_size_obj, py_image_size); STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_save_obj, 2, py_image_save); STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_scale_obj, py_image_scale); STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_scaled_obj, py_image_scaled); STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_subimg_obj, py_image_subimg); STATIC MP_DEFINE_CONST_FUN_OBJ_3(py_image_blit_obj, py_image_blit); STATIC MP_DEFINE_CONST_FUN_OBJ_3(py_image_blend_obj, py_image_blend); STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_histeq_obj, py_image_histeq); STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_median_obj, 1, py_image_median); STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_invert_obj, py_image_invert); STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_binary_obj, py_image_binary); STATIC MP_DEFINE_CONST_FUN_OBJ_3(py_image_threshold_obj, py_image_threshold); STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_rainbow_obj, py_image_rainbow); STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_erode_obj, py_image_erode); STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_dilate_obj, py_image_dilate); STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_morph_obj, py_image_morph); STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_compress_obj, py_image_compress); STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_draw_line_obj, py_image_draw_line); STATIC MP_DEFINE_CONST_FUN_OBJ_3(py_image_draw_circle_obj, py_image_draw_circle); STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_draw_rectangle_obj, py_image_draw_rectangle); STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_draw_keypoints_obj, py_image_draw_keypoints); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(py_image_draw_string_obj, 4, 5, py_image_draw_string); STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_find_blobs_obj, py_image_find_blobs); STATIC MP_DEFINE_CONST_FUN_OBJ_3(py_image_find_template_obj, py_image_find_template); STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_find_features_obj, 2, py_image_find_features); STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_find_keypoints_obj, 1, py_image_find_keypoints); STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_find_lbp_obj, py_image_find_lbp); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(py_image_match_keypoints_obj, 4, 4, py_image_match_keypoints); STATIC MP_DEFINE_CONST_FUN_OBJ_3(py_image_match_lbp_obj, py_image_match_lbp); static const mp_map_elem_t locals_dict_table[] = { {MP_OBJ_NEW_QSTR(MP_QSTR_size), (mp_obj_t)&py_image_size_obj}, /* basic image functions */ {MP_OBJ_NEW_QSTR(MP_QSTR_save), (mp_obj_t)&py_image_save_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_scale), (mp_obj_t)&py_image_scale_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_scaled), (mp_obj_t)&py_image_scaled_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_subimg), (mp_obj_t)&py_image_subimg_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_blit), (mp_obj_t)&py_image_blit_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_blend), (mp_obj_t)&py_image_blend_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_histeq), (mp_obj_t)&py_image_histeq_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_median), (mp_obj_t)&py_image_median_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_invert), (mp_obj_t)&py_image_invert_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_binary), (mp_obj_t)&py_image_binary_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_threshold), (mp_obj_t)&py_image_threshold_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_rainbow), (mp_obj_t)&py_image_rainbow_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_erode), (mp_obj_t)&py_image_erode_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_dilate), (mp_obj_t)&py_image_dilate_obj}, // {MP_OBJ_NEW_QSTR(MP_QSTR_morph), (mp_obj_t)&py_image_morph_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_compress), (mp_obj_t)&py_image_compress_obj}, /* drawing functions */ {MP_OBJ_NEW_QSTR(MP_QSTR_draw_line), (mp_obj_t)&py_image_draw_line_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_draw_circle), (mp_obj_t)&py_image_draw_circle_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_draw_rectangle), (mp_obj_t)&py_image_draw_rectangle_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_draw_keypoints), (mp_obj_t)&py_image_draw_keypoints_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_draw_string), (mp_obj_t)&py_image_draw_string_obj}, /* objects/feature detection */ {MP_OBJ_NEW_QSTR(MP_QSTR_find_blobs), (mp_obj_t)&py_image_find_blobs_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_find_template), (mp_obj_t)&py_image_find_template_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_find_features), (mp_obj_t)&py_image_find_features_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_find_keypoints), (mp_obj_t)&py_image_find_keypoints_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_find_lbp), (mp_obj_t)&py_image_find_lbp_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_match_keypoints), (mp_obj_t)&py_image_match_keypoints_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_match_lbp), (mp_obj_t)&py_image_match_lbp_obj}, { NULL, NULL }, }; STATIC MP_DEFINE_CONST_DICT(locals_dict, locals_dict_table); static const mp_obj_type_t py_image_type = { { &mp_type_type }, .name = MP_QSTR_image, .print = py_image_print, .buffer_p = { .get_buffer = py_image_get_buffer }, .locals_dict = (mp_obj_t)&locals_dict, }; mp_obj_t py_image(int w, int h, int bpp, void *pixels) { py_image_obj_t *o = m_new_obj(py_image_obj_t); o->base.type = &py_image_type; o->_cobj.w =w; o->_cobj.h =h; o->_cobj.bpp =bpp; o->_cobj.pixels =pixels; return o; } mp_obj_t py_image_from_struct(image_t *image) { py_image_obj_t *o = m_new_obj(py_image_obj_t); o->base.type = &py_image_type; o->_cobj =*image; return o; } int py_image_descriptor_from_roi(image_t *image, const char *path, rectangle_t *roi) { int kpts_size = 0; kp_t *kpts = NULL; int threshold = 10; bool normalized = false; kpts = fast_detect(image, threshold, &kpts_size, roi); freak_find_keypoints(image, kpts, kpts_size, normalized, normalized); printf("Save Descriptor: KPTS(%d)\n", kpts_size); printf("Save Descriptor: ROI(%d %d %d %d)\n", roi->x, roi->y, roi->w, roi->h); if (kpts_size ==0) { return 0; } int res = freak_save_descriptor(kpts, kpts_size, path); if (res != FR_OK) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, ffs_strerror(res))); } return 0; }