mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Add morphological operations, fix threshold
This commit is contained in:
parent
5a66fd714b
commit
29202f1f99
@ -1 +1 @@
|
||||
Subproject commit 71ecc7ae7ce8faa6a0a7224961c7b3c49bc7f114
|
||||
Subproject commit 84078f85a5135bf83d6bdd655740ac89a97145fd
|
||||
@ -203,46 +203,89 @@ void imlib_grayscale_to_rgb565(struct image *image)
|
||||
#endif
|
||||
}
|
||||
|
||||
void imlib_erosion_filter(struct image *src, uint8_t *kernel, int k_size)
|
||||
void imlib_erode(image_t *src, int ksize)
|
||||
{
|
||||
int x, y, j, k;
|
||||
int w = src->w;
|
||||
int h = src->h;
|
||||
/* TODO */
|
||||
uint8_t *dst = xalloc0(w*h);
|
||||
int c = ksize/2;// center pixel
|
||||
int k_rows = (ksize+1)*2;
|
||||
uint8_t *dst = xalloc0(src->w * k_rows);
|
||||
|
||||
for (y=0; y<h-k_size; y++) {
|
||||
for (x=0; x<w-k_size; x++) {
|
||||
dst[w*(y+1)+x+1] = 255;
|
||||
for (j=0; j<k_size; j++) {
|
||||
for (k=0; k<k_size; k++) {
|
||||
/* (y*w+x)+(j*w+k) */
|
||||
if (src->pixels[w*(y+j)+x+k] != (kernel[j*k_size+k]*255)) {
|
||||
dst[w*(y+1)+x+1] = 0;
|
||||
j=k_size;
|
||||
break;
|
||||
}
|
||||
for (int y=1; y<src->h-ksize; y++) {
|
||||
for (int x=1; x<src->w-ksize; x++) {
|
||||
int i = y*src->w+x;
|
||||
int di = (y%k_rows)*src->w+x;
|
||||
if ((dst[di] = src->pixels[i])==0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j=-c; j<c; j++) {
|
||||
for (int k=-c; k<c; k++) {
|
||||
if (src->pixels[(y+j)*src->w+x+k]==0) {
|
||||
dst[di]=0;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
done:;
|
||||
}
|
||||
|
||||
if ((y+1)%k_rows==0) {
|
||||
memcpy(src->pixels+((y/k_rows)*k_rows*src->w), dst, src->w*k_rows);
|
||||
}
|
||||
}
|
||||
memcpy(src->pixels, dst, w*h);
|
||||
xfree(dst);
|
||||
}
|
||||
|
||||
void imlib_threshold(image_t *src, image_t *dst, struct color *color, int threshold)
|
||||
void imlib_dilate(image_t *src, int ksize)
|
||||
{
|
||||
/* Extract reference RGB */
|
||||
uint16_t r = color->r*31/255;
|
||||
uint16_t g = color->g*63/255;
|
||||
uint16_t b = color->b*31/255;
|
||||
uint32_t rgb = SWAP((r << 11) | (g << 5) | b) * 3;
|
||||
int c = ksize/2;// center pixel
|
||||
int k_rows = (ksize+1)*2;
|
||||
uint8_t *dst = xalloc0(src->w * k_rows);
|
||||
|
||||
/* Convert reference RGB to LAB */
|
||||
uint32_t L = lab_table[rgb];
|
||||
uint32_t A = lab_table[rgb+1];
|
||||
uint32_t B = lab_table[rgb+2];
|
||||
for (int y=1; y<src->h-ksize; y++) {
|
||||
for (int x=1; x<src->w-ksize; x++) {
|
||||
int i = y*src->w+x;
|
||||
int di = (y%k_rows)*src->w+x;
|
||||
if ((dst[di] = src->pixels[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j=-c; j<c; j++) {
|
||||
for (int k=-c; k<c; k++) {
|
||||
if (src->pixels[(y+j)*src->w+x+k]) {
|
||||
dst[di]=src->pixels[(y+j)*src->w+x+k];
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
done:;
|
||||
}
|
||||
|
||||
if ((y+1)%k_rows==0) {
|
||||
memcpy(src->pixels+((y/k_rows)*k_rows*src->w), dst, src->w*k_rows);
|
||||
}
|
||||
}
|
||||
xfree(dst);
|
||||
}
|
||||
|
||||
void imlib_morph(struct image *src, uint8_t *kernel, int ksize)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void imlib_threshold(image_t *src, image_t *dst, color_t *color, int color_size, int threshold)
|
||||
{
|
||||
// /* Extract reference RGB */
|
||||
// uint16_t r = color->r*31/255;
|
||||
// uint16_t g = color->g*63/255;
|
||||
// uint16_t b = color->b*31/255;
|
||||
// uint32_t rgb = SWAP((r << 11) | (g << 5) | b) * 3;
|
||||
//
|
||||
// /* Convert reference RGB to LAB */
|
||||
// uint32_t L = lab_table[rgb];
|
||||
// uint32_t A = lab_table[rgb+1];
|
||||
// uint32_t B = lab_table[rgb+2];
|
||||
//
|
||||
/* Square threshold */
|
||||
threshold *= threshold;
|
||||
|
||||
@ -251,12 +294,19 @@ void imlib_threshold(image_t *src, image_t *dst, struct color *color, int thresh
|
||||
for (int y=0; y<src->h; y++) {
|
||||
int i=y*src->w;
|
||||
for (int x=0; x<src->w; x++) {
|
||||
rgb = pixels[i+x]*3;
|
||||
uint32_t sum =(L-lab_table[rgb]) * (L-lab_table[rgb]) +
|
||||
(A-lab_table[rgb+1]) * (A-lab_table[rgb+1]) +
|
||||
(B-lab_table[rgb+2]) * (B-lab_table[rgb+2]);
|
||||
/* add pixel if within threshold */
|
||||
dst->pixels[i+x] = (sum<threshold);
|
||||
uint32_t rgb = pixels[i+x]*3;
|
||||
dst->pixels[i+x] = 0;
|
||||
for (int c=0; c<color_size; c++) {
|
||||
// TODO
|
||||
uint32_t sum =(color[c].L-lab_table[rgb]) * (color[c].L-lab_table[rgb]) +
|
||||
(color[c].A-lab_table[rgb+1]) * (color[c].A-lab_table[rgb+1]) +
|
||||
(color[c].B-lab_table[rgb+2]) * (color[c].B-lab_table[rgb+2]);
|
||||
if (sum<threshold) {
|
||||
/* set pixel if within threshold */
|
||||
dst->pixels[i+x] = c+1; //sets color label c+1
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -300,10 +350,24 @@ void imlib_subimage(struct image *src_img, struct image *dst_img, int x_off, int
|
||||
}
|
||||
}
|
||||
|
||||
void imlib_blit(struct image *src, struct image *dst, int x_off, int y_off)
|
||||
void imlib_blit_gs(struct image *src, struct image *dst, int x_off, int y_off)
|
||||
{
|
||||
int x, y;
|
||||
typeof(*src->data) *srcp = src->data;
|
||||
uint8_t *srcp = src->data;
|
||||
uint16_t *dstp = (uint16_t*) dst->data;
|
||||
|
||||
for (y=y_off; y<src->h+y_off; y++) {
|
||||
for (x=x_off; x<src->w+x_off; x++) {
|
||||
uint8_t p =*srcp++;
|
||||
dstp[y*dst->w+x]= ((uint16_t)p<<8)|p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void imlib_blit_rgb(struct image *src, struct image *dst, int x_off, int y_off)
|
||||
{
|
||||
int x, y;
|
||||
typeof(*src->data) *srcp = src->data; //TODO
|
||||
typeof(*dst->data) *dstp = dst->data;
|
||||
|
||||
for (y=y_off; y<src->h+y_off; y++) {
|
||||
@ -313,6 +377,15 @@ void imlib_blit(struct image *src, struct image *dst, int x_off, int y_off)
|
||||
}
|
||||
}
|
||||
|
||||
void imlib_blit(struct image *src, struct image *dst, int x_off, int y_off)
|
||||
{
|
||||
if (src->bpp == 1) {
|
||||
imlib_blit_gs(src, dst, x_off, y_off);
|
||||
} else {
|
||||
imlib_blit_rgb(src, dst, x_off, y_off);
|
||||
}
|
||||
}
|
||||
|
||||
void imlib_blend(struct image *src, struct image *dst, int x_off, int y_off, uint8_t alpha)
|
||||
{
|
||||
uint16_t i,r, g, b;
|
||||
|
||||
@ -21,6 +21,15 @@ typedef struct rectangle {
|
||||
int h;
|
||||
} rectangle_t;
|
||||
|
||||
typedef struct blob {
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
int h;
|
||||
int c;
|
||||
int id;
|
||||
} blob_t;
|
||||
|
||||
typedef struct color {
|
||||
union {
|
||||
uint8_t vec[3];
|
||||
@ -159,9 +168,11 @@ void imlib_rgb_to_hsv(struct color *rgb, struct color *hsv);
|
||||
int imlib_image_mean(struct image *src);
|
||||
void imlib_histeq(struct image *src);
|
||||
void imlib_median_filter(image_t *src, int r);
|
||||
void imlib_erosion_filter(struct image *src, uint8_t *kernel, int k_size);
|
||||
void imlib_threshold(struct image *src, struct image *dst, struct color *color, int threshold);
|
||||
void imlib_rainbow(struct image *src, struct image *dst);
|
||||
void imlib_erode(image_t *src, int ksize);
|
||||
void imlib_dilate(image_t *src, int ksize);
|
||||
void imlib_morph(image_t *src, uint8_t *kernel, int k_size);
|
||||
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);
|
||||
|
||||
/* Integral image functions */
|
||||
@ -198,5 +209,4 @@ int ppm_write(image_t *img, const char *path);
|
||||
int ppm_write_subimg(image_t *img, const char *path, rectangle_t *r);
|
||||
int imlib_load_image(image_t *image, const char *path);
|
||||
int imlib_save_image(image_t *image, const char *path, rectangle_t *r);
|
||||
void imlib_blit(struct image *src, struct image *dst, int x_off, int y_off);
|
||||
#endif //__IMLIB_H__
|
||||
|
||||
@ -270,33 +270,46 @@ static mp_obj_t py_image_median(uint n_args, const mp_obj_t *args, mp_map_t *kw_
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
static mp_obj_t py_image_threshold(mp_obj_t image_obj, mp_obj_t color_obj, mp_obj_t threshold)
|
||||
static mp_obj_t py_image_threshold(mp_obj_t image_obj, mp_obj_t color_list_obj, mp_obj_t threshold)
|
||||
{
|
||||
/* C stuff */
|
||||
struct color color;
|
||||
struct image *image;
|
||||
mp_obj_t bimage_obj;
|
||||
color_t *color;
|
||||
image_t *image;
|
||||
|
||||
/* sanity checks */
|
||||
PY_ASSERT_TRUE(sensor.pixformat == PIXFORMAT_RGB565);
|
||||
PY_ASSERT_TRUE(sensor.framesize <= FRAMESIZE_QQVGA);
|
||||
|
||||
mp_obj_t *col_obj;
|
||||
mp_obj_get_array_fixed_n(color_obj, 3, &col_obj);
|
||||
color.r = mp_obj_get_int(col_obj[0]);
|
||||
color.g = mp_obj_get_int(col_obj[1]);
|
||||
color.b = mp_obj_get_int(col_obj[2]);
|
||||
|
||||
/* get image pointer */
|
||||
/* read arguments */
|
||||
image = py_image_cobj(image_obj);
|
||||
int thresh = mp_obj_get_int(threshold);
|
||||
|
||||
/* returned image */
|
||||
bimage_obj = py_image(image->w, image->h, 1, image->data+(image->w*image->h*image->bpp));
|
||||
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; i<len; i++) {
|
||||
mp_obj_t *color_obj;
|
||||
mp_obj_get_array_fixed_n(color_arr[i], 3, &color_obj);
|
||||
color[i].L = mp_obj_get_int(color_obj[0]);
|
||||
color[i].A = mp_obj_get_int(color_obj[1]);
|
||||
color[i].B = mp_obj_get_int(color_obj[2]);
|
||||
}
|
||||
|
||||
/* Threshold image using reference color */
|
||||
imlib_threshold(image, py_image_cobj(bimage_obj), &color, mp_obj_get_int(threshold));
|
||||
imlib_threshold(image, &bimage, color, len, thresh);
|
||||
|
||||
return bimage_obj;
|
||||
return py_image_from_struct(&bimage);
|
||||
}
|
||||
|
||||
static mp_obj_t py_image_rainbow(mp_obj_t src_image_obj)
|
||||
@ -340,6 +353,43 @@ static mp_obj_t py_image_draw_circle(mp_obj_t image_obj, mp_obj_t c_obj, mp_obj_
|
||||
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;
|
||||
@ -389,7 +439,7 @@ static mp_obj_t py_image_find_blobs(mp_obj_t image_obj)
|
||||
/* C stuff */
|
||||
array_t *blobs;
|
||||
struct image *image;
|
||||
mp_obj_t rec_obj[4];
|
||||
mp_obj_t blob_obj[6];
|
||||
|
||||
/* MP List */
|
||||
mp_obj_t objects_list = mp_const_none;
|
||||
@ -408,12 +458,14 @@ static mp_obj_t py_image_find_blobs(mp_obj_t image_obj)
|
||||
|
||||
if (array_length(blobs)) {
|
||||
for (int j=0; j<array_length(blobs); j++) {
|
||||
rectangle_t *r = array_at(blobs, j);
|
||||
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_list_append(objects_list, mp_obj_new_tuple(4, rec_obj));
|
||||
blob_t *r = array_at(blobs, j);
|
||||
blob_obj[0] = mp_obj_new_int(r->x);
|
||||
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);
|
||||
@ -490,6 +542,10 @@ static mp_obj_t py_image_find_template(mp_obj_t image_obj, mp_obj_t template_obj
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
//#define get_kw_arg(kw_map, kw_val, kw_def)
|
||||
// ({ mp_map_elem_t *kw_arg = mp_map_lookup(kw_map,
|
||||
// MP_OBJ_NEW_QSTR(qstr_from_str(kw_val)), MP_MAP_LOOKUP);
|
||||
// _a < _b ? _a : _b; })
|
||||
|
||||
static mp_obj_t py_image_find_keypoints(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
||||
{
|
||||
@ -564,19 +620,39 @@ static mp_obj_t py_image_match_keypoints(mp_obj_t image_obj, mp_obj_t kpts_obj,
|
||||
// match the keypoint sets
|
||||
int16_t *kpts_match = freak_match_keypoints(kpts1, kpts1_size, kpts2, kpts2_size, m_thresh);
|
||||
|
||||
// // do something with the match
|
||||
// for (int i=0; i<kpts1_size; i++) {
|
||||
// if (kpts_match[i] != -1) {
|
||||
// kp_t *kp1 = &kpts1[i];
|
||||
// kp_t *kp2 = &kpts2[kpts_match[i]];
|
||||
// imlib_draw_line(image, kp1->x, kp1->y, kp2->x, kp2->y);
|
||||
// //int r = 4;
|
||||
// // if (((kp->x+r) < image->w) && ((kp->y+r) < image->h)) {
|
||||
// // imlib_draw_circle(image, kp->x, kp->y, r);
|
||||
// // }
|
||||
// }
|
||||
// }
|
||||
|
||||
// do something with the match
|
||||
int cx=0, cy=0, match=0;
|
||||
for (int i=0; i<kpts1_size; i++) {
|
||||
if (kpts_match[i] != -1) {
|
||||
kp_t *kp1 = &kpts1[i];
|
||||
kp_t *kp2 = &kpts2[kpts_match[i]];
|
||||
imlib_draw_line(image, kp1->x, kp1->y, kp2->x, kp2->y);
|
||||
//int r = 4;
|
||||
// if (((kp->x+r) < image->w) && ((kp->y+r) < image->h)) {
|
||||
// imlib_draw_circle(image, kp->x, kp->y, r);
|
||||
// }
|
||||
cx += kp2->x;
|
||||
cy += kp2->y;
|
||||
match ++;
|
||||
}
|
||||
}
|
||||
|
||||
if (match ==0) {
|
||||
match++;
|
||||
}
|
||||
cx /= match;
|
||||
cy /= match;
|
||||
int r = 5;
|
||||
if (((cx+r) < image->w) && ((cy+r) < image->h)) {
|
||||
imlib_draw_line(image, image->w/2, image->h/2, cx, cy);
|
||||
imlib_draw_circle(image, cx, cy, r);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
@ -630,6 +706,9 @@ 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_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_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);
|
||||
@ -647,13 +726,16 @@ static const mp_map_elem_t locals_dict_table[] = {
|
||||
/* 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_scaled), (mp_obj_t)&py_image_scaled_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_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},
|
||||
|
||||
/* drawing functions */
|
||||
{MP_OBJ_NEW_QSTR(MP_QSTR_draw_circle), (mp_obj_t)&py_image_draw_circle_obj},
|
||||
@ -686,7 +768,7 @@ mp_obj_t py_image(int w, int h, int bpp, void *pixels)
|
||||
o->base.type = &py_image_type;
|
||||
|
||||
o->_cobj.w =w;
|
||||
o->_cobj.h =w;
|
||||
o->_cobj.h =h;
|
||||
o->_cobj.bpp =bpp;
|
||||
o->_cobj.pixels =pixels;
|
||||
return o;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user