From 14b6330b677d142f78e92af3c8399435b6436e74 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Fri, 23 Sep 2016 18:46:11 +0200 Subject: [PATCH] Add simple lens correction function. --- src/omv/img/imlib.c | 31 +++++++++++++++++++++++++++++++ src/omv/py/py_image.c | 12 ++++++++++++ src/omv/py/qstrdefsomv.h | 1 + 3 files changed, 44 insertions(+) diff --git a/src/omv/img/imlib.c b/src/omv/img/imlib.c index 2d316004d..5d8f2233c 100644 --- a/src/omv/img/imlib.c +++ b/src/omv/img/imlib.c @@ -942,3 +942,34 @@ int imlib_image_std(image_t *src) /* std */ return fast_sqrtf(v); } + +// Simple lens correction function. +// See http://www.tannerhelland.com/4743/simple-algorithm-correcting-lens-distortion/ +void imlib_lens_corr(image_t *src, float strength) +{ + float zoom = 1.0f; + int halfWidth = src->w / 2; + int halfHeight = src->h / 2; + float corr_radius = strength / fast_sqrtf(src->w*src->w + src->h*src->h); + image_t dst = {.w = src->w, .h = src->h, .data = fb_alloc(src->w*src->h)}; + + for (int y=0; yh; y++) { + for (int x=0; xw; x++) { + int newX = x - halfWidth; + int newY = y - halfHeight; + + float r = corr_radius * fast_sqrtf(newX*newX + newY*newY); + float theta = (abs(r) < 1e-6f) ? (atanf(r)/r) : 1.0f; + + int sourceX = (int) (newX * theta * zoom + halfWidth ); + int sourceY = (int) (newY * theta * zoom + halfHeight); + if (sourceX >= 0 && sourceX < src->w && sourceY >= 0 && sourceY < src->h) { + dst.data[y * dst.w + x] = src->data[sourceY * src->w + sourceX]; + } else { + dst.data[y * dst.w + x] = src->data[y * dst.w + x]; + } + } + } + memcpy(src->data, dst.data, src->w * src->h); + fb_free(); +} diff --git a/src/omv/py/py_image.c b/src/omv/py/py_image.c index 003974a1a..87e8b603c 100644 --- a/src/omv/py/py_image.c +++ b/src/omv/py/py_image.c @@ -883,6 +883,16 @@ static mp_obj_t py_image_histeq(mp_obj_t img_obj) return img_obj; } +static mp_obj_t py_image_lens_corr(mp_obj_t img_obj, mp_obj_t s_obj) +{ + image_t *arg_img = py_image_cobj(img_obj); + PY_ASSERT_FALSE_MSG(IM_IS_JPEG(arg_img), "Operation not supported on JPEG"); + + imlib_lens_corr(arg_img, mp_obj_get_float(s_obj)); + return img_obj; +} + + static mp_obj_t py_image_mask_ellipse(mp_obj_t img_obj) { image_t *arg_img = py_image_cobj(img_obj); @@ -1461,6 +1471,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_mode_obj, py_image_mode); STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_median_obj, 2, py_image_median); STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_gaussian_obj, 1, py_image_gaussian); STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_histeq_obj, py_image_histeq); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_lens_corr_obj, py_image_lens_corr); STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_mask_ellipse_obj, py_image_mask_ellipse); /* Color Tracking */ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_find_blobs_obj, 2, py_image_find_blobs); @@ -1527,6 +1538,7 @@ static const mp_map_elem_t locals_dict_table[] = { {MP_OBJ_NEW_QSTR(MP_QSTR_median), (mp_obj_t)&py_image_median_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_gaussian), (mp_obj_t)&py_image_gaussian_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_histeq), (mp_obj_t)&py_image_histeq_obj}, + {MP_OBJ_NEW_QSTR(MP_QSTR_lens_corr), (mp_obj_t)&py_image_lens_corr_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_mask_ellipse), (mp_obj_t)&py_image_mask_ellipse_obj}, /* Color Tracking */ {MP_OBJ_NEW_QSTR(MP_QSTR_find_blobs), (mp_obj_t)&py_image_find_blobs_obj}, diff --git a/src/omv/py/qstrdefsomv.h b/src/omv/py/qstrdefsomv.h index 77bc98364..bb92d8fe6 100644 --- a/src/omv/py/qstrdefsomv.h +++ b/src/omv/py/qstrdefsomv.h @@ -97,6 +97,7 @@ Q(percentile) Q(feature_filter) Q(margin) Q(normalized) +Q(lens_corr) // Lcd Module Q(lcd)