Add morphological operations, fix threshold

This commit is contained in:
iabdalkader 2014-09-01 16:49:02 +02:00
parent 5a66fd714b
commit 29202f1f99
4 changed files with 237 additions and 72 deletions

@ -1 +1 @@
Subproject commit 71ecc7ae7ce8faa6a0a7224961c7b3c49bc7f114
Subproject commit 84078f85a5135bf83d6bdd655740ac89a97145fd

View File

@ -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;

View File

@ -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__

View File

@ -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;