Fixed blob code.

Removed micropython code from the image libary. Also, blobs are now 10
tuple values by default now. The multilist thing has been removed from
blobs and it will return just a list of blobs instead of a tree of
lists.

Filter functions still work too.
This commit is contained in:
Kwabena W. Agyeman 2016-04-13 23:16:29 -04:00
parent 32acc9cb4e
commit 16daeb83a2
8 changed files with 276 additions and 167 deletions

View File

@ -6,9 +6,10 @@
* Blob and color code/marker detection code...
*
*/
#include <mp.h>
#include <string.h>
#include "mdefs.h"
#include "fb_alloc.h"
#include "xalloc.h"
#include "imlib.h"
ALWAYS_INLINE static uint8_t *init_mask(rectangle_t *roi)
@ -106,7 +107,10 @@ ALWAYS_INLINE static bool threshold(image_t *img, int x, int y, simple_color_t l
}
}
mp_obj_t imlib_find_blobs(mp_obj_t img_obj, image_t *img, int num_thresholds, simple_color_t *l_thresholds, simple_color_t *h_thresholds, bool invert, rectangle_t *r, mp_obj_t filtering_fn)
array_t *imlib_find_blobs(image_t *img,
int num_thresholds, simple_color_t *l_thresholds, simple_color_t *h_thresholds,
bool invert, rectangle_t *r,
bool (*f_fun)(void*,void*,color_blob_t*), void *f_fun_arg_0, void *f_fun_arg_1)
{
// We're using a modified wildfire algorithm below where instead of using a
// the stack we use a queue along with a burn mask to filter out already
@ -114,22 +118,20 @@ mp_obj_t imlib_find_blobs(mp_obj_t img_obj, image_t *img, int num_thresholds, si
// an area of connected pixels that all are within a threshold, the algorithm
// computes the bounding box around all those pixels, number of pixels in the
// blob, centroid, and blob orientation. The algorithm then returns a list
// of blobs for each set of thresholds passed in. That is, this function
// returns a tuple of lists of blobs.
// of all the blobs in the image. Note that blobs can be mapped back to colors
// by their blob code number.
rectangle_t rect;
if (!rectangle_subimg(img, r, &rect)) {
return mp_const_none;
return NULL;
}
mp_obj_t blob_lists[num_thresholds];
uint8_t *mask = init_mask(&rect);
stack_queue_t *sq = init_stack_queue(&rect);
array_t *blobs_list;
array_alloc(&blobs_list, xfree);
for (int n = 0; n < num_thresholds; n++) {
blob_lists[n] = mp_obj_new_list(4, NULL); // 4 is just the intial list size guess
mp_obj_list_set_len(blob_lists[n], 0);
for (int i = 0; i < rect.h; i++) {
for (int j = 0; j < rect.w; j++) {
int x = (rect.x + j); // in img
@ -188,29 +190,29 @@ mp_obj_t imlib_find_blobs(mp_obj_t img_obj, image_t *img, int num_thresholds, si
blob_c += blob_pixels*my*my;
// Compute the final blob orientation from a, b, and c sums.
float o = ((blob_a!=blob_c)?fast_atan2f(blob_b,blob_a-blob_c):0.0)/2.0;
mp_obj_t blob_tuple[10];
blob_tuple[0] = mp_obj_new_int(blob_x1);
blob_tuple[1] = mp_obj_new_int(blob_y1);
blob_tuple[2] = mp_obj_new_int(blob_x2-blob_x1+1);
blob_tuple[3] = mp_obj_new_int(blob_y2-blob_y1+1);
blob_tuple[4] = mp_obj_new_int(blob_pixels);
blob_tuple[5] = mp_obj_new_int(mx);
blob_tuple[6] = mp_obj_new_int(my);
blob_tuple[7] = mp_obj_new_float(o);
blob_tuple[8] = mp_obj_new_int(1<<n);
blob_tuple[9] = mp_obj_new_int(1);
mp_obj_t blob_tuple_obj = mp_obj_new_tuple(10, blob_tuple);
if (filtering_fn != MP_OBJ_NULL) {
if (mp_obj_is_true(mp_call_function_2(filtering_fn, img_obj, blob_tuple_obj))) {
mp_obj_list_append(blob_lists[n], blob_tuple_obj);
} else {
mp_obj_tuple_del(blob_tuple_obj);
color_blob_t cb;
cb.x = blob_x1;
cb.y = blob_y1;
cb.w = blob_x2-blob_x1+1;
cb.h = blob_y2-blob_y1+1;
cb.pixels = blob_pixels;
cb.cx = mx;
cb.cy = my;
cb.rotation = o;
cb.code = 1<<n;
cb.count = 1;
// We allocate in the below code to sped things up.
if ((f_fun != NULL) && (f_fun_arg_0 != NULL) && (f_fun_arg_1 != NULL)) {
if (f_fun(f_fun_arg_0, f_fun_arg_1, &cb)) {
color_blob_t *cb2 = xalloc(sizeof(color_blob_t));
memcpy(cb2, &cb, sizeof(color_blob_t));
array_push_back(blobs_list, cb2);
}
} else {
if (blob_pixels >= ((img->w*img->h)/1000)) {
mp_obj_list_append(blob_lists[n], blob_tuple_obj);
} else {
mp_obj_tuple_del(blob_tuple_obj);
color_blob_t *cb2 = xalloc(sizeof(color_blob_t));
memcpy(cb2, &cb, sizeof(color_blob_t));
array_push_back(blobs_list, cb2);
}
}
}
@ -221,137 +223,119 @@ mp_obj_t imlib_find_blobs(mp_obj_t img_obj, image_t *img, int num_thresholds, si
deinit_stack_queue();
deinit_mask();
return mp_obj_new_tuple(num_thresholds, blob_lists);
return blobs_list;
}
mp_obj_t imlib_find_markers(mp_obj_t img_obj, mp_obj_t blob_lists_obj, int margin, mp_obj_t filtering_fn)
array_t *imlib_find_markers(array_t *blobs_list, int margin,
bool (*f_fun)(void*,void*,color_blob_t*), void *f_fun_arg_0, void *f_fun_arg_1)
{
// After you have a list of blobs this function will merge blobs from the
// different colors lists that intersect into one blob. The new merged big
// blob will have a bounding box that surronds all the merged blobs, pixels will
// include all the blobs, and centroids/orientations are averaged. Additionally,
// the new blob will have an extra code value with a bit set for each color
// that was merged into the blob along with the number of blobs merged. The
// color code provides a nice and easy user controllable way to get an idea
// of what colors are in a merged blob.
// After you have a list of blobs this function will merge blobs that
// intersect into one blob. The new merged big blob will have a bounding box
// that surronds all the merged blobs, pixels will include all the blobs,
// and centroids/orientations are averaged. Additionally, the new blob will
// have an extra code value with a bit set for each color that was merged
// into the blob along with the number of blobs merged. The color code
// provides a nice and easy user controllable way to get an idea of what
// colors are in a merged blob.
mp_uint_t blob_l_len;
mp_obj_t *blob_l;
mp_obj_get_array(blob_lists_obj, &blob_l_len, &blob_l);
if (!blob_l_len) return mp_const_none;
mp_uint_t blob_lists_len[blob_l_len];
mp_obj_t *blob_lists[blob_l_len];
if (!array_length(blobs_list)) return NULL;
rectangle_t rect; // reusing mask from above - so we need a fake rect obj.
rect.x = 0;
rect.y = 0;
rect.w = 0;
rect.h = blob_l_len;
for (mp_uint_t i = 0; i < blob_l_len; i++) {
mp_obj_get_array(blob_l[i], &blob_lists_len[i], &blob_lists[i]);
rect.w = IM_MAX(rect.w, blob_lists_len[i]); // find longest list
}
if (!rect.w) return mp_const_none;
rect.w = array_length(blobs_list);
rect.h = 1;
uint8_t *mask = init_mask(&rect);
mp_obj_t out = mp_obj_new_list(4, NULL); // 4 is just the intial list size guess
mp_obj_list_set_len(out, 0);
for (mp_uint_t i = 0; i < blob_l_len; i++) {
for (mp_uint_t j = 0; j < blob_lists_len[i]; j++) {
if (get_not_mask_pixel(&rect, mask, j, i)) {
set_mask_pixel(&rect, mask, j, i);
array_t *blobs_list_ret;
array_alloc(&blobs_list_ret, xfree);
for (int i = 0, ii = array_length(blobs_list); i < ii; i++) {
if (get_not_mask_pixel(&rect, mask, i, 0)) {
set_mask_pixel(&rect, mask, i, 0);
mp_obj_t *temp0;
mp_obj_get_array_fixed_n(blob_lists[i][j], 10, &temp0);
color_blob_t *cb0 = array_at(blobs_list, i);
int blob_x = mp_obj_get_int(temp0[0]); // rect x
int blob_y = mp_obj_get_int(temp0[1]); // rect y
int blob_w = mp_obj_get_int(temp0[2]); // rect w
int blob_h = mp_obj_get_int(temp0[3]); // rect h
int blob_pixels = mp_obj_get_int(temp0[4]); // pixels
int blob_cx = mp_obj_get_int(temp0[5]); // centroid x
int blob_cy = mp_obj_get_int(temp0[6]); // centroid y
float blob_rotation = mp_obj_get_float(temp0[7]); // rotation
int blob_code = mp_obj_get_int(temp0[8]); // code bit
int blob_count = mp_obj_get_int(temp0[9]); // blob count
int blob_x = cb0->x; // rect x
int blob_y = cb0->y; // rect y
int blob_w = cb0->w; // rect w
int blob_h = cb0->h; // rect h
int blob_pixels = cb0->pixels; // pixels
int blob_cx = cb0->cx; // centroid x
int blob_cy = cb0->cy; // centroid y
float blob_rotation = cb0->rotation; // rotation
int blob_code = cb0->code; // code bit
int blob_count = cb0->count; // blob count
for (mp_uint_t a = 0; a < blob_l_len; a++) {
for (mp_uint_t b = 0; b < blob_lists_len[a]; b++) {
if (get_not_mask_pixel(&rect, mask, b, a)) {
for (int j = 0, jj = array_length(blobs_list); j < jj; j++) {
if (get_not_mask_pixel(&rect, mask, j, 0)) {
mp_obj_t *temp1;
mp_obj_get_array_fixed_n(blob_lists[a][b], 10, &temp1);
color_blob_t *cb1 = array_at(blobs_list, j);
rectangle_t t0;
t0.x = blob_x - margin;
t0.y = blob_y - margin;
t0.w = blob_w + (2*margin);
t0.h = blob_h + (2*margin);
rectangle_t t0, t1;
t0.x = blob_x - margin;
t0.y = blob_y - margin;
t0.w = blob_w + (2*margin);
t0.h = blob_h + (2*margin);
t1.x = cb1->x - margin;
t1.y = cb1->y - margin;
t1.w = cb1->w + (2*margin);
t1.h = cb1->h + (2*margin);
rectangle_t t1;
t1.x = mp_obj_get_int(temp1[0]) - margin;
t1.y = mp_obj_get_int(temp1[1]) - margin;
t1.w = mp_obj_get_int(temp1[2]) + (2*margin);
t1.h = mp_obj_get_int(temp1[3]) + (2*margin);
if (rectangle_intersects(&t0, &t1)) {
set_mask_pixel(&rect, mask, b, a);
// Compute bounding rect...
blob_x = IM_MIN(blob_x, t1.x);
blob_y = IM_MIN(blob_y, t1.y);
int x2_0 = t0.x+t0.w-1;
int x2_1 = t1.x+t1.w-1;
int x2 = IM_MAX(x2_0, x2_1);
blob_w = x2-blob_x+1;
int y2_0 = t0.y+t0.h-1;
int y2_1 = t1.y+t1.h-1;
int y2 = IM_MAX(y2_0, y2_1);
blob_h = y2-blob_y+1;
// Update tracking info...
blob_pixels += mp_obj_get_int(temp1[4]);
blob_cx += mp_obj_get_int(temp1[5]);
blob_cy += mp_obj_get_int(temp1[6]);
blob_rotation += mp_obj_get_float(temp1[7]);
blob_code |= mp_obj_get_int(temp1[8]);
blob_count += mp_obj_get_int(temp1[9]);
}
}
if (rectangle_intersects(&t0, &t1)) {
set_mask_pixel(&rect, mask, j, 0);
// Compute bounding rect...
int x2_0 = blob_x+blob_w-1;
int x2_1 = cb1->x+cb1->w-1;
int x2 = IM_MAX(x2_0, x2_1);
blob_x = IM_MIN(blob_x, cb1->x);
blob_w = x2-blob_x+1;
int y2_0 = blob_y+blob_h-1;
int y2_1 = cb1->y+cb1->h-1;
int y2 = IM_MAX(y2_0, y2_1);
blob_y = IM_MIN(blob_y, cb1->y);
blob_h = y2-blob_y+1;
// Update tracking info...
blob_pixels += cb1->pixels;
blob_cx += cb1->cx;
blob_cy += cb1->cy;
blob_rotation +=cb1->rotation;
blob_code |= cb1->code;
blob_count += cb1->count;
}
}
blob_cx /= blob_count;
blob_cy /= blob_count;
blob_rotation /= blob_count;
// Build output object.
mp_obj_t blob_tuple[10];
blob_tuple[0] = mp_obj_new_int(blob_x);
blob_tuple[1] = mp_obj_new_int(blob_y);
blob_tuple[2] = mp_obj_new_int(blob_w);
blob_tuple[3] = mp_obj_new_int(blob_h);
blob_tuple[4] = mp_obj_new_int(blob_pixels);
blob_tuple[5] = mp_obj_new_int(blob_cx);
blob_tuple[6] = mp_obj_new_int(blob_cy);
blob_tuple[7] = mp_obj_new_float(blob_rotation);
blob_tuple[8] = mp_obj_new_int(blob_code);
blob_tuple[9] = mp_obj_new_int(blob_count);
mp_obj_t blob_tuple_obj = mp_obj_new_tuple(10, blob_tuple);
if (filtering_fn != MP_OBJ_NULL) {
if (mp_obj_is_true(mp_call_function_2(filtering_fn, img_obj, blob_tuple_obj))) {
mp_obj_list_append(out, blob_tuple_obj);
} else {
mp_obj_tuple_del(blob_tuple_obj);
}
} else {
mp_obj_list_append(out, blob_tuple_obj);
}
blob_cx /= blob_count;
blob_cy /= blob_count;
blob_rotation /= blob_count;
// Build output object.
color_blob_t cb;
cb.x = blob_x;
cb.y = blob_y;
cb.w = blob_w;
cb.h = blob_h;
cb.pixels = blob_pixels;
cb.cx = blob_cx;
cb.cy = blob_cy;
cb.rotation = blob_rotation;
cb.code = blob_code;
cb.count = blob_count;
// We allocate in the below code to sped things up.
if ((f_fun != NULL) && (f_fun_arg_0 != NULL) && (f_fun_arg_1 != NULL)) {
if (f_fun(f_fun_arg_0, f_fun_arg_1, &cb)) {
color_blob_t *cb2 = xalloc(sizeof(color_blob_t));
memcpy(cb2, &cb, sizeof(color_blob_t));
array_push_back(blobs_list_ret, cb2);
}
} else {
color_blob_t *cb2 = xalloc(sizeof(color_blob_t));
memcpy(cb2, &cb, sizeof(color_blob_t));
array_push_back(blobs_list_ret, cb2);
}
}
}
deinit_mask();
return out;
return blobs_list_ret;
}

View File

@ -398,7 +398,9 @@ void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int
////////////////////////////////////////////////////////////////////////////////
void imlib_binary(image_t *img, int num_thresholds, simple_color_t *l_thresholds, simple_color_t *h_thresholds, bool invert)
void imlib_binary(image_t *img,
int num_thresholds, simple_color_t *l_thresholds, simple_color_t *h_thresholds,
bool invert)
{
if (IM_IS_GS(img)) {
uint8_t *pixels = img->pixels;

View File

@ -13,7 +13,6 @@
#include <ff.h>
#include "array.h"
#include "fmath.h"
#include "obj.h"
#define IM_SWAP16(x) __REV16(x) // Swap bottom two chars in short.
#define IM_SWAP32(x) __REV32(x) // Swap bottom two shorts in long.
@ -232,6 +231,20 @@ typedef struct statistics {
int8_t l_upper_q, a_upper_q, b_upper_q;
} statistics_t;
typedef struct color_blob { // organized this way to pack it...
int16_t x; // rect - 0
int16_t y; // rect - 1
int16_t w; // rect - 2
int16_t h; // rect - 3
int16_t cx; // centroid - 5
int16_t cy; // centroid - 6
float rotation; // rotation - 7
uint16_t pixels; // number of pixels in merged blobs - 4
uint16_t count; // number of blobs merged into this blob - 9
uint32_t code; // color code index bits of merged blobs - 8
}
color_blob_t;
typedef struct color {
union {
uint8_t vec[3];
@ -426,7 +439,9 @@ void imlib_draw_circle(image_t *img, int cx, int cy, int r, int c);
void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int c);
/* Binary functions */
void imlib_binary(image_t *img, int num_thresholds, simple_color_t *l_thresholds, simple_color_t *h_thresholds, bool invert);
void imlib_binary(image_t *img,
int num_thresholds, simple_color_t *l_thresholds, simple_color_t *h_thresholds,
bool invert);
void imlib_invert(image_t *img);
void imlib_and(image_t *img, const char *path, image_t *other);
void imlib_nand(image_t *img, const char *path, image_t *other);
@ -455,8 +470,12 @@ void imlib_mode_filter(image_t *img, const int ksize);
void imlib_median_filter(image_t *img, const int ksize, const int percentile);
/* Color Tracking */
mp_obj_t imlib_find_blobs(mp_obj_t img_obj, image_t *img, int num_thresholds, simple_color_t *l_thresholds, simple_color_t *h_thresholds, bool invert, rectangle_t *r, mp_obj_t filtering_fn);
mp_obj_t imlib_find_markers(mp_obj_t img_obj, mp_obj_t blob_lists_obj, int margin, mp_obj_t filtering_fn);
array_t *imlib_find_blobs(image_t *img,
int num_thresholds, simple_color_t *l_thresholds, simple_color_t *h_thresholds,
bool invert, rectangle_t *r,
bool (*f_fun)(void*,void*,color_blob_t*), void *f_fun_arg_0, void *f_fun_arg_1);
array_t *imlib_find_markers(array_t *blobs_list, int margin,
bool (*f_fun)(void*,void*,color_blob_t*), void *f_fun_arg_0, void *f_fun_arg_1);
/* Clustering functions */
array_t *cluster_kmeans(array_t *points, int k);

View File

@ -696,6 +696,23 @@ static mp_obj_t py_image_median(uint n_args, const mp_obj_t *args, mp_map_t *kw_
return mp_const_none;
}
static bool py_image_find_blobs_f_fun(void *fun_obj, void *img_obj, color_blob_t *cb)
{
mp_obj_t blob_obj[10] = {
mp_obj_new_int(cb->x),
mp_obj_new_int(cb->y),
mp_obj_new_int(cb->w),
mp_obj_new_int(cb->h),
mp_obj_new_int(cb->pixels),
mp_obj_new_int(cb->cx),
mp_obj_new_int(cb->cy),
mp_obj_new_float(cb->rotation),
mp_obj_new_int(cb->code),
mp_obj_new_int(cb->count)
};
return mp_obj_is_true(mp_call_function_2(fun_obj, img_obj, mp_obj_new_tuple(10, blob_obj)));
}
static mp_obj_t py_image_find_blobs(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
image_t *arg_img = py_image_cobj(args[0]);
@ -742,10 +759,50 @@ static mp_obj_t py_image_find_blobs(uint n_args, const mp_obj_t *args, mp_map_t
py_helper_lookup_rectangle(kw_args, arg_img, &arg_r);
mp_map_elem_t *kw_arg = mp_map_lookup(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_feature_filter), MP_MAP_LOOKUP);
mp_obj_t kw_val = (kw_arg != NULL) ? kw_arg->value : MP_OBJ_NULL;
mp_obj_t kw_val = (kw_arg != NULL) ? kw_arg->value : NULL;
int arg_invert = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_invert), 0);
return imlib_find_blobs(args[0], arg_img, arg_t_len, l_t, u_t, arg_invert ? 1 : 0, &arg_r, kw_val);
array_t *blobs_list = imlib_find_blobs(arg_img, arg_t_len, l_t, u_t, arg_invert ? 1 : 0, &arg_r,
py_image_find_blobs_f_fun, kw_val, args[0]);
if (blobs_list == NULL) {
return mp_const_none;
}
mp_obj_t objects_list = mp_obj_new_list(0, NULL);
for (int i=0, j=array_length(blobs_list); i<j; i++) {
color_blob_t *cb = array_at(blobs_list, i);
mp_obj_t blob_obj[10] = {
mp_obj_new_int(cb->x),
mp_obj_new_int(cb->y),
mp_obj_new_int(cb->w),
mp_obj_new_int(cb->h),
mp_obj_new_int(cb->pixels),
mp_obj_new_int(cb->cx),
mp_obj_new_int(cb->cy),
mp_obj_new_float(cb->rotation),
mp_obj_new_int(cb->code),
mp_obj_new_int(cb->count)
};
mp_obj_list_append(objects_list, mp_obj_new_tuple(10, blob_obj));
}
array_free(blobs_list);
return objects_list;
}
static bool py_image_find_markers_f_fun(void *fun_obj, void *img_obj, color_blob_t *cb)
{
mp_obj_t blob_obj[10] = {
mp_obj_new_int(cb->x),
mp_obj_new_int(cb->y),
mp_obj_new_int(cb->w),
mp_obj_new_int(cb->h),
mp_obj_new_int(cb->pixels),
mp_obj_new_int(cb->cx),
mp_obj_new_int(cb->cy),
mp_obj_new_float(cb->rotation),
mp_obj_new_int(cb->code),
mp_obj_new_int(cb->count)
};
return mp_obj_is_true(mp_call_function_2(fun_obj, img_obj, mp_obj_new_tuple(10, blob_obj)));
}
static mp_obj_t py_image_find_markers(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
@ -757,9 +814,56 @@ static mp_obj_t py_image_find_markers(uint n_args, const mp_obj_t *args, mp_map_
int margin = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_margin), 2);
mp_map_elem_t *kw_arg = mp_map_lookup(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_feature_filter), MP_MAP_LOOKUP);
mp_obj_t kw_val = (kw_arg != NULL) ? kw_arg->value : MP_OBJ_NULL;
mp_obj_t kw_val = (kw_arg != NULL) ? kw_arg->value : NULL;
return imlib_find_markers(args[0], args[1], margin, kw_val);
mp_uint_t arg_t_len;
mp_obj_t *arg_t;
mp_obj_get_array(args[1], &arg_t_len, &arg_t);
if (!arg_t_len) return mp_const_none;
array_t *blobs_list;
array_alloc_init(&blobs_list, xfree, arg_t_len);
for (int i=0; i<arg_t_len; i++) {
mp_obj_t *temp;
mp_obj_get_array_fixed_n(arg_t[i], 10, &temp);
color_blob_t *cb = xalloc(sizeof(color_blob_t));
cb->x = mp_obj_get_int(temp[0]);
cb->y = mp_obj_get_int(temp[1]);
cb->w = mp_obj_get_int(temp[2]);
cb->h = mp_obj_get_int(temp[3]);
cb->pixels = mp_obj_get_int(temp[4]);
cb->cx = mp_obj_get_int(temp[5]);
cb->cy = mp_obj_get_int(temp[6]);
cb->rotation = mp_obj_get_float(temp[7]);
cb->code = mp_obj_get_int(temp[8]);
cb->count = mp_obj_get_int(temp[9]);
array_push_back(blobs_list, cb);
}
array_t *blobs_list_ret = imlib_find_markers(blobs_list, margin,
py_image_find_markers_f_fun, kw_val, args[0]);
if (blobs_list_ret == NULL) {
return mp_const_none;
}
array_free(blobs_list);
mp_obj_t objects_list = mp_obj_new_list(0, NULL);
for (int i=0, j=array_length(blobs_list_ret); i<j; i++) {
color_blob_t *cb = array_at(blobs_list_ret, i);
mp_obj_t blob_obj[10] = {
mp_obj_new_int(cb->x),
mp_obj_new_int(cb->y),
mp_obj_new_int(cb->w),
mp_obj_new_int(cb->h),
mp_obj_new_int(cb->pixels),
mp_obj_new_int(cb->cx),
mp_obj_new_int(cb->cy),
mp_obj_new_float(cb->rotation),
mp_obj_new_int(cb->code),
mp_obj_new_int(cb->count)
};
mp_obj_list_append(objects_list, mp_obj_new_tuple(10, blob_obj));
}
array_free(blobs_list_ret);
return objects_list;
}
static mp_obj_t py_image_scale(mp_obj_t image_obj, mp_obj_t size_obj)

View File

@ -33,10 +33,12 @@ while(True):
while(diff):
img = sensor.snapshot()
img.difference("temp/bg.bmp")
for blob_l in img.find_blobs([(20, 100, -128, 127, -128, 127)]):
for blob in blob_l:
# Over 100 pixels need to change to detect motion.
if (diff and (blob[4] > 100)): diff -= 1
stats = img.statistics()
# Stats 5 is the max of the lighting color channel. The below code
# triggers when the lighting max for the whole image goes above 10.
# The lighting difference maximum should be zero normally.
if (stats[5] > 10):
diff -= 1
pyb.LED(BLUE_LED_PIN).off()
print("Movement detected! Saving image...")

View File

@ -37,10 +37,12 @@ while(True):
while(diff):
img = sensor.snapshot()
img.difference("temp/bg.bmp")
for blob_l in img.find_blobs([(20, 100, -128, 127, -128, 127)]):
for blob in blob_l:
# Over 100 pixels need to change to detect motion.
if (diff and (blob[4] > 100)): diff -= 1
stats = img.statistics()
# Stats 5 is the max of the lighting color channel. The below code
# triggers when the lighting max for the whole image goes above 10.
# The lighting difference maximum should be zero normally.
if (stats[5] > 10):
diff -= 1
g = gif.Gif("example-%d.gif" % pyb.rng(), loop=True)

View File

@ -38,10 +38,12 @@ while(True):
while(diff):
img = sensor.snapshot()
img.difference("temp/bg.bmp")
for blob_l in img.find_blobs([(20, 100, -128, 127, -128, 127)]):
for blob in blob_l:
# Over 100 pixels need to change to detect motion.
if (diff and (blob[4] > 100)): diff -= 1
stats = img.statistics()
# Stats 5 is the max of the lighting color channel. The below code
# triggers when the lighting max for the whole image goes above 10.
# The lighting difference maximum should be zero normally.
if (stats[5] > 10):
diff -= 1
m = mjpeg.Mjpeg("example-%d.mjpeg" % pyb.rng())

View File

@ -1,7 +1,5 @@
import sensor, time, pyb
led_r = pyb.LED(1)
sensor.reset()
sensor.set_framesize(sensor.QVGA)
sensor.set_pixformat(sensor.RGB565)
@ -18,14 +16,10 @@ while (True):
image = sensor.snapshot()
# Detect blobs in image
blob_l = image.find_blobs([COLOR1])
led_r.off()
blobs = image.find_blobs([COLOR1])
# Draw rectangles around detected blobs
for blobs in blob_l:
for r in blobs:
if r[8]==1:
led_r.on()
image.draw_rectangle(r[0:4])
for blob in blobs:
image.draw_rectangle(blob[0:4])
print(clock.fps())