mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Add Midpoint filter.
Has a bias value that allows you to control if its really a midpoint, min, max filter, or something inbetween. Run at 160x120 or lower. 320x240 is slow (seems to be the case for all convoltions at that res).
This commit is contained in:
parent
b2e77e9dce
commit
978b4c12df
@ -139,6 +139,7 @@ OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/img/,\
|
||||
rainbow_tab.o \
|
||||
rgb2rgb_tab.o \
|
||||
median.o \
|
||||
midpoint.o \
|
||||
point.o \
|
||||
rectangle.o \
|
||||
bmp.o \
|
||||
|
||||
@ -42,6 +42,7 @@ SRCS += $(addprefix img/, \
|
||||
rainbow_tab.c \
|
||||
rgb2rgb_tab.c \
|
||||
median.c \
|
||||
midpoint.c \
|
||||
point.c \
|
||||
rectangle.c \
|
||||
bmp.c \
|
||||
|
||||
@ -460,13 +460,16 @@ void imlib_morph(image_t *img, const int ksize, const int8_t *krn, const float m
|
||||
int32_t *imlib_histogram(image_t *img, rectangle_t *r);
|
||||
void imlib_statistics(image_t *img, rectangle_t *r, statistics_t *out);
|
||||
|
||||
/* Image Filtering */
|
||||
void imlib_midpoint_filter(image_t *img, const int ksize, const int bias);
|
||||
void imlib_median_filter(image_t *src, int r);
|
||||
|
||||
/* Clustering functions */
|
||||
array_t *cluster_kmeans(array_t *points, int k);
|
||||
|
||||
/* Image filtering functions */
|
||||
int imlib_image_mean(struct image *src);
|
||||
void imlib_histeq(struct image *src);
|
||||
void imlib_median_filter(image_t *src, int r);
|
||||
void imlib_threshold(image_t *src, image_t *dst, color_t *color, int color_size, int threshold);
|
||||
void imlib_rainbow(image_t *src, struct image *dst);
|
||||
array_t *imlib_count_blobs(struct image *image);
|
||||
|
||||
95
src/omv/img/midpoint.c
Normal file
95
src/omv/img/midpoint.c
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* This file is part of the OpenMV project.
|
||||
* Copyright (c) 2013-2016 Kwabena W. Agyeman <kwagyeman@openmv.io>
|
||||
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||
*
|
||||
* Min/Max/Midpoint Filtering.
|
||||
*
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "imlib.h"
|
||||
#include "fb_alloc.h"
|
||||
|
||||
// krn_s == 0 -> 1x1 kernel
|
||||
// krn_s == 1 -> 3x3 kernel
|
||||
// ...
|
||||
// krn_s == n -> ((n*2)+1)x((n*2)+1) kernel
|
||||
|
||||
// bias == 0 to 256 -> 0.0 to 1.0 (0.0==min filter, 1.0==max filter)
|
||||
|
||||
void imlib_midpoint_filter(image_t *img, const int ksize, const int bias)
|
||||
{
|
||||
int min_bias = (256-bias);
|
||||
int max_bias = bias;
|
||||
int brows = ksize + 1;
|
||||
uint8_t *buffer = fb_alloc(img->w * brows * img->bpp);
|
||||
if (IM_IS_GS(img)) {
|
||||
for (int y=0; y<img->h; y++) {
|
||||
for (int x=0; x<img->w; x++) {
|
||||
int min = 255, max = 0;
|
||||
for (int j=-ksize; j<=ksize; j++) {
|
||||
for (int k=-ksize; k<=ksize; k++) {
|
||||
if (IM_X_INSIDE(img, x+k) && IM_Y_INSIDE(img, y+j)) {
|
||||
const uint8_t pixel = IM_GET_GS_PIXEL(img, x+k, y+j);
|
||||
min = IM_MIN(min, pixel);
|
||||
max = IM_MAX(max, pixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
// We're writing into the buffer like if it were a window.
|
||||
buffer[((y%brows)*img->w)+x] =
|
||||
((min*min_bias)+(max*max_bias))>>8;
|
||||
}
|
||||
if (y>=ksize) {
|
||||
memcpy(img->pixels+((y-ksize)*img->w),
|
||||
buffer+(((y-ksize)%brows)*img->w),
|
||||
img->w * sizeof(uint8_t));
|
||||
}
|
||||
}
|
||||
for (int y=img->h-ksize; y<img->h; y++) {
|
||||
memcpy(img->pixels+(y*img->w),
|
||||
buffer+((y%brows)*img->w),
|
||||
img->w * sizeof(uint8_t));
|
||||
}
|
||||
} else {
|
||||
for (int y=0; y<img->h; y++) {
|
||||
for (int x=0; x<img->w; x++) {
|
||||
int r_min = 255, r_max = 0;
|
||||
int g_min = 255, g_max = 0;
|
||||
int b_min = 255, b_max = 0;
|
||||
for (int j=-ksize; j<=ksize; j++) {
|
||||
for (int k=-ksize; k<=ksize; k++) {
|
||||
if (IM_X_INSIDE(img, x+k) && IM_Y_INSIDE(img, y+j)) {
|
||||
const uint16_t pixel = IM_GET_RGB565_PIXEL(img, x+k, y+j);
|
||||
int red = IM_R565(pixel);
|
||||
int green = IM_G565(pixel);
|
||||
int blue = IM_B565(pixel);
|
||||
r_min = IM_MIN(r_min, red);
|
||||
r_max = IM_MAX(r_max, red);
|
||||
g_min = IM_MIN(g_min, green);
|
||||
g_max = IM_MAX(g_max, green);
|
||||
b_min = IM_MIN(b_min, blue);
|
||||
b_max = IM_MAX(b_max, blue);
|
||||
}
|
||||
}
|
||||
}
|
||||
// We're writing into the buffer like if it were a window.
|
||||
((uint16_t *) buffer)[((y%brows)*img->w)+x] =
|
||||
IM_RGB565(((r_min*min_bias)+(r_max*max_bias))>>8,
|
||||
((g_min*min_bias)+(g_max*max_bias))>>8,
|
||||
((b_min*min_bias)+(b_max*max_bias))>>8);
|
||||
}
|
||||
if (y>=ksize) {
|
||||
memcpy(((uint16_t *) img->pixels)+((y-ksize)*img->w),
|
||||
((uint16_t *) buffer)+(((y-ksize)%brows)*img->w),
|
||||
img->w * sizeof(uint16_t));
|
||||
}
|
||||
}
|
||||
for (int y=img->h-ksize; y<img->h; y++) {
|
||||
memcpy(((uint16_t *) img->pixels)+(y*img->w),
|
||||
((uint16_t *) buffer)+((y%brows)*img->w),
|
||||
img->w * sizeof(uint16_t));
|
||||
}
|
||||
}
|
||||
fb_free();
|
||||
}
|
||||
@ -696,6 +696,20 @@ static mp_obj_t py_image_statistics(uint n_args, const mp_obj_t *args, mp_map_t
|
||||
}
|
||||
}
|
||||
|
||||
static mp_obj_t py_image_midpoint(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
||||
{
|
||||
image_t *arg_img = py_image_cobj(args[0]);
|
||||
PY_ASSERT_FALSE_MSG(IM_IS_JPEG(arg_img),
|
||||
"Operation not supported on JPEG");
|
||||
|
||||
int arg_ksize = mp_obj_get_int(args[1]);
|
||||
PY_ASSERT_TRUE_MSG(arg_ksize >= 0, "Kernel Size must be >= 0");
|
||||
|
||||
int bias = py_helper_lookup_float(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_bias), 0.5) * 256;
|
||||
imlib_midpoint_filter(arg_img, arg_ksize, IM_MIN(IM_MAX(bias, 0), 256));
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
static mp_obj_t py_image_scale(mp_obj_t image_obj, mp_obj_t size_obj)
|
||||
{
|
||||
int w,h;
|
||||
@ -1182,6 +1196,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_difference_obj, py_image_difference);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_morph_obj, 3, py_image_morph);
|
||||
/* Image Statistics */
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_statistics_obj, 1, py_image_statistics);
|
||||
/* Image Filtering */
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_midpoint_obj, 2, py_image_midpoint);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_median_obj, 1, py_image_median);
|
||||
|
||||
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);
|
||||
@ -1189,7 +1206,6 @@ 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_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_compress_obj, py_image_compress);
|
||||
@ -1240,6 +1256,9 @@ static const mp_map_elem_t locals_dict_table[] = {
|
||||
{MP_OBJ_NEW_QSTR(MP_QSTR_morph), (mp_obj_t)&py_image_morph_obj},
|
||||
/* Image Statistics */
|
||||
{MP_OBJ_NEW_QSTR(MP_QSTR_statistics), (mp_obj_t)&py_image_statistics_obj},
|
||||
/* Image Filtering */
|
||||
{MP_OBJ_NEW_QSTR(MP_QSTR_midpoint), (mp_obj_t)&py_image_midpoint_obj},
|
||||
{MP_OBJ_NEW_QSTR(MP_QSTR_median), (mp_obj_t)&py_image_median_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},
|
||||
@ -1247,7 +1266,6 @@ static const mp_map_elem_t locals_dict_table[] = {
|
||||
{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_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_compress), (mp_obj_t)&py_image_compress_obj},
|
||||
|
||||
Loading…
Reference in New Issue
Block a user