Update blob code and examples.

This commit is contained in:
Kwabena W. Agyeman 2019-01-26 14:46:15 -08:00 committed by Ibrahim Abd Elkader
parent ae6427e06a
commit 3a8ac88f66
13 changed files with 1428 additions and 273 deletions

View File

@ -2,7 +2,7 @@
#
# This example shows off multi color blob tracking using the OpenMV Cam.
import sensor, image, time
import sensor, image, time, math
# Color Tracking Thresholds (L Min, L Max, A Min, A Max, B Min, B Max)
# The below thresholds track in general red/green things. You may wish to tune them...
@ -28,6 +28,14 @@ while(True):
clock.tick()
img = sensor.snapshot()
for blob in img.find_blobs(thresholds, pixels_threshold=200, area_threshold=200):
# These values depend on the blob not being circular - otherwise they will be shaky.
if blob.elongation() > 0.5:
img.draw_edges(blob.min_corners(), color=(255,0,0))
img.draw_line(blob.major_axis_line(), color=(0,255,0))
img.draw_line(blob.minor_axis_line(), color=(0,0,255))
# These values are stable all the time.
img.draw_rectangle(blob.rect())
img.draw_cross(blob.cx(), blob.cy())
# Note - the blob rotation is unique to 0-180 only.
img.draw_keypoints([(blob.cx(), blob.cy(), int(math.degrees(blob.rotation())))], size=20)
print(clock.fps())

View File

@ -5,7 +5,7 @@
# A color code is a blob composed of two or more colors. The example below will
# only track colored objects which have both the colors below in them.
import sensor, image, time
import sensor, image, time, math
# Color Tracking Thresholds (L Min, L Max, A Min, A Max, B Min, B Max)
# The below thresholds track in general red/green things. You may wish to tune them...
@ -30,6 +30,14 @@ while(True):
img = sensor.snapshot()
for blob in img.find_blobs(thresholds, pixels_threshold=100, area_threshold=100, merge=True):
if blob.code() == 3: # r/g code == (1 << 1) | (1 << 0)
# These values depend on the blob not being circular - otherwise they will be shaky.
if blob.elongation() > 0.5:
img.draw_edges(blob.min_corners(), color=(255,0,0))
img.draw_line(blob.major_axis_line(), color=(0,255,0))
img.draw_line(blob.minor_axis_line(), color=(0,0,255))
# These values are stable all the time.
img.draw_rectangle(blob.rect())
img.draw_cross(blob.cx(), blob.cy())
# Note - the blob rotation is unique to 0-180 only.
img.draw_keypoints([(blob.cx(), blob.cy(), int(math.degrees(blob.rotation())))], size=20)
print(clock.fps())

View File

@ -2,7 +2,7 @@
#
# This example shows off single color grayscale tracking using the OpenMV Cam.
import sensor, image, time
import sensor, image, time, math
# Color Tracking Thresholds (Grayscale Min, Grayscale Max)
# The below grayscale threshold is set to only find extremely bright white areas.
@ -24,6 +24,14 @@ while(True):
clock.tick()
img = sensor.snapshot()
for blob in img.find_blobs([thresholds], pixels_threshold=100, area_threshold=100, merge=True):
img.draw_rectangle(blob.rect())
img.draw_cross(blob.cx(), blob.cy())
# These values depend on the blob not being circular - otherwise they will be shaky.
if blob.elongation() > 0.5:
img.draw_edges(blob.min_corners(), color=0)
img.draw_line(blob.major_axis_line(), color=0)
img.draw_line(blob.minor_axis_line(), color=0)
# These values are stable all the time.
img.draw_rectangle(blob.rect(), color=127)
img.draw_cross(blob.cx(), blob.cy(), color=127)
# Note - the blob rotation is unique to 0-180 only.
img.draw_keypoints([(blob.cx(), blob.cy(), int(math.degrees(blob.rotation())))], size=40, color=127)
print(clock.fps())

View File

@ -2,7 +2,7 @@
#
# This example shows off single color RGB565 tracking using the OpenMV Cam.
import sensor, image, time
import sensor, image, time, math
threshold_index = 0 # 0 for red, 1 for green, 2 for blue
@ -28,6 +28,14 @@ while(True):
clock.tick()
img = sensor.snapshot()
for blob in img.find_blobs([thresholds[threshold_index]], pixels_threshold=200, area_threshold=200, merge=True):
# These values depend on the blob not being circular - otherwise they will be shaky.
if blob.elongation() > 0.5:
img.draw_edges(blob.min_corners(), color=(255,0,0))
img.draw_line(blob.major_axis_line(), color=(0,255,0))
img.draw_line(blob.minor_axis_line(), color=(0,0,255))
# These values are stable all the time.
img.draw_rectangle(blob.rect())
img.draw_cross(blob.cx(), blob.cy())
# Note - the blob rotation is unique to 0-180 only.
img.draw_keypoints([(blob.cx(), blob.cy(), int(math.degrees(blob.rotation())))], size=20)
print(clock.fps())

View File

@ -9,6 +9,12 @@
#ifndef __IMLIB_CONFIG_H__
#define __IMLIB_CONFIG_H__
// Enable mean pooling
//#define IMLIB_ENABLE_MEAN_POOLING
// Enable midpoint pooling
//#define IMLIB_ENABLE_MIDPOINT_POOLING
// Enable binary ops
//#define IMLIB_ENABLE_BINARY_OPS
@ -111,6 +117,19 @@
// Enable FAST (20+ KBs).
//#define IMLIB_ENABLE_FAST
// Enable find_template()
//#define IMLIB_FIND_TEMPLATE
// Enable find_lbp()
//#define IMLIB_ENABLE_FIND_LBP
// Enable find_keypoints()
//#define IMLIB_ENABLE_FIND_KEYPOINTS
#if defined(IMLIB_ENABLE_FIND_LBP) || defined(IMLIB_ENABLE_FIND_KEYPOINTS)
#define IMLIB_ENABLE_DESCRIPTOR
#endif
// Enable find_hog()
//#define IMLIB_ENABLE_HOG

View File

@ -9,6 +9,12 @@
#ifndef __IMLIB_CONFIG_H__
#define __IMLIB_CONFIG_H__
// Enable mean pooling
#define IMLIB_ENABLE_MEAN_POOLING
// Enable midpoint pooling
#define IMLIB_ENABLE_MIDPOINT_POOLING
// Enable binary ops
#define IMLIB_ENABLE_BINARY_OPS
@ -117,6 +123,19 @@
// Enable FAST (20+ KBs).
#define IMLIB_ENABLE_FAST
// Enable find_template()
#define IMLIB_FIND_TEMPLATE
// Enable find_lbp()
#define IMLIB_ENABLE_FIND_LBP
// Enable find_keypoints()
#define IMLIB_ENABLE_FIND_KEYPOINTS
#if defined(IMLIB_ENABLE_FIND_LBP) || defined(IMLIB_ENABLE_FIND_KEYPOINTS)
#define IMLIB_ENABLE_DESCRIPTOR
#endif
// Enable find_hog()
#define IMLIB_ENABLE_HOG

View File

@ -9,6 +9,12 @@
#ifndef __IMLIB_CONFIG_H__
#define __IMLIB_CONFIG_H__
// Enable mean pooling
#define IMLIB_ENABLE_MEAN_POOLING
// Enable midpoint pooling
#define IMLIB_ENABLE_MIDPOINT_POOLING
// Enable binary ops
#define IMLIB_ENABLE_BINARY_OPS
@ -117,6 +123,19 @@
// Enable FAST (20+ KBs).
#define IMLIB_ENABLE_FAST
// Enable find_template()
#define IMLIB_FIND_TEMPLATE
// Enable find_lbp()
#define IMLIB_ENABLE_FIND_LBP
// Enable find_keypoints()
#define IMLIB_ENABLE_FIND_KEYPOINTS
#if defined(IMLIB_ENABLE_FIND_LBP) || defined(IMLIB_ENABLE_FIND_KEYPOINTS)
#define IMLIB_ENABLE_DESCRIPTOR
#endif
// Enable find_hog()
#define IMLIB_ENABLE_HOG

File diff suppressed because it is too large Load Diff

View File

@ -42,6 +42,67 @@ int point_quadrance(point_t *ptr0, point_t *ptr1)
return (delta_x * delta_x) + (delta_y * delta_y);
}
void point_rotate(int x, int y, float r, int center_x, int center_y, int16_t *new_x, int16_t *new_y)
{
x -= center_x;
y -= center_y;
*new_x = (x * cosf(r)) - (y * sinf(r)) + center_x;
*new_y = (x * sinf(r)) + (y * cosf(r)) + center_y;
}
void point_min_area_rectangle(point_t *corners, point_t *new_corners, int corners_len) // Corners need to be sorted!
{
int i_min = 0;
int i_min_area = INT_MAX;
int i_x0 = 0, i_y0 = 0;
int i_x1 = 0, i_y1 = 0;
int i_x2 = 0, i_y2 = 0;
int i_x3 = 0, i_y3 = 0;
float i_r = 0;
// This algorithm aligns the 4 edges produced by the 4 corners to the x axis and then computes the
// min area rect for each alignment. The smallest rect is choosen and then re-rotated and returned.
for (int i = 0; i < corners_len; i++) {
int16_t x0 = corners[i].x, y0 = corners[i].y;
int x_diff = corners[(i+1)%corners_len].x - corners[i].x;
int y_diff = corners[(i+1)%corners_len].y - corners[i].y;
float r = -fast_atan2f(y_diff, x_diff);
int16_t x1[corners_len-1];
int16_t y1[corners_len-1];
for (int j = 0, jj = corners_len - 1; j < jj; j++) {
point_rotate(corners[(i+j+1)%corners_len].x, corners[(i+j+1)%corners_len].y, r, x0, y0, x1 + j, y1 + j);
}
int minx = x0;
int maxx = x0;
int miny = y0;
int maxy = y0;
for (int j = 0, jj = corners_len - 1; j < jj; j++) {
minx = MIN(minx, x1[j]);
maxx = MAX(maxx, x1[j]);
miny = MIN(miny, y1[j]);
maxy = MAX(maxy, y1[j]);
}
int area = (maxx - minx + 1) * (maxy - miny + 1);
if (area < i_min_area) {
i_min = i;
i_min_area = area;
i_x0 = minx, i_y0 = miny;
i_x1 = maxx, i_y1 = miny;
i_x2 = maxx, i_y2 = maxy;
i_x3 = minx, i_y3 = maxy;
i_r = r;
}
}
point_rotate(i_x0, i_y0, -i_r, corners[i_min].x, corners[i_min].y, &new_corners[0].x, &new_corners[0].y);
point_rotate(i_x1, i_y1, -i_r, corners[i_min].x, corners[i_min].y, &new_corners[1].x, &new_corners[1].y);
point_rotate(i_x2, i_y2, -i_r, corners[i_min].x, corners[i_min].y, &new_corners[2].x, &new_corners[2].y);
point_rotate(i_x3, i_y3, -i_r, corners[i_min].x, corners[i_min].y, &new_corners[3].x, &new_corners[3].y);
}
////////////////
// Line Stuff //
////////////////

View File

@ -83,6 +83,8 @@ void point_init(point_t *ptr, int x, int y);
void point_copy(point_t *dst, point_t *src);
bool point_equal_fast(point_t *ptr0, point_t *ptr1);
int point_quadrance(point_t *ptr0, point_t *ptr1);
void point_rotate(int x, int y, float r, int center_x, int center_y, int16_t *new_x, int16_t *new_y);
void point_min_area_rectangle(point_t *corners, point_t *new_corners, int corners_len);
////////////////
// Line Stuff //
@ -1049,12 +1051,16 @@ typedef struct statistics {
int8_t BMean, BMedian, BMode, BSTDev, BMin, BMax, BLQ, BUQ;
} statistics_t;
#define FIND_BLOBS_CORNERS_RESOLUTION 20 // multiple of 4
#define FIND_BLOBS_ANGLE_RESOLUTION (360 / FIND_BLOBS_CORNERS_RESOLUTION)
typedef struct find_blobs_list_lnk_data {
point_t corners[FIND_BLOBS_CORNERS_RESOLUTION];
rectangle_t rect;
uint32_t pixels;
point_t centroid;
float rotation;
uint16_t code, count;
uint32_t pixels, perimeter, code, count;
float centroid_x, centroid_y, rotation, roundness;
uint16_t x_hist_bins_count, y_hist_bins_count, *x_hist_bins, *y_hist_bins;
float centroid_x_acc, centroid_y_acc, rotation_acc_x, rotation_acc_y, roundness_acc;
} find_blobs_list_lnk_data_t;
typedef struct find_lines_list_lnk_data {
@ -1341,7 +1347,8 @@ void imlib_find_blobs(list_t *out, image_t *ptr, rectangle_t *roi, unsigned int
list_t *thresholds, bool invert, unsigned int area_threshold, unsigned int pixels_threshold,
bool merge, int margin,
bool (*threshold_cb)(void*,find_blobs_list_lnk_data_t*), void *threshold_cb_arg,
bool (*merge_cb)(void*,find_blobs_list_lnk_data_t*,find_blobs_list_lnk_data_t*), void *merge_cb_arg);
bool (*merge_cb)(void*,find_blobs_list_lnk_data_t*,find_blobs_list_lnk_data_t*), void *merge_cb_arg,
unsigned int x_hist_bins_max, unsigned int y_hist_bins_max);
// Shape Detection
size_t trace_line(image_t *ptr, line_t *l, int *theta_buffer, uint32_t *mag_buffer, point_t *point_buffer); // helper/internal
void merge_alot(list_t *out, int threshold, int theta_threshold); // helper/internal

View File

@ -8,6 +8,7 @@
*/
#include "imlib.h"
#ifdef IMLIB_ENABLE_MIDPOINT_POOLING
void imlib_midpoint_pool(image_t *img_i, image_t *img_o, int x_div, int y_div, const int bias)
{
int min_bias = (256-bias);
@ -55,7 +56,9 @@ void imlib_midpoint_pool(image_t *img_i, image_t *img_o, int x_div, int y_div, c
}
}
}
#endif // IMLIB_ENABLE_MIDPOINT_POOLING
#ifdef IMLIB_ENABLE_MEAN_POOLING
void imlib_mean_pool(image_t *img_i, image_t *img_o, int x_div, int y_div)
{
int n = x_div * y_div;
@ -93,3 +96,4 @@ void imlib_mean_pool(image_t *img_i, image_t *img_o, int x_div, int y_div)
}
}
}
#endif // IMLIB_ENABLE_MEAN_POOLING

View File

@ -57,6 +57,8 @@ static const mp_obj_type_t py_cascade_type = {
// Keypoints object ///////////////////////////////////////////////////////////
#ifdef IMLIB_ENABLE_FIND_KEYPOINTS
typedef struct _py_kp_obj_t {
mp_obj_base_t base;
array_t *kpts;
@ -112,8 +114,12 @@ py_kp_obj_t *py_kpts_obj(mp_obj_t kpts_obj)
return kpts_obj;
}
#endif // IMLIB_ENABLE_FIND_KEYPOINTS
// LBP descriptor /////////////////////////////////////////////////////////////
#ifdef IMLIB_ENABLE_FIND_LBP
typedef struct _py_lbp_obj_t {
mp_obj_base_t base;
uint8_t *hist;
@ -130,7 +136,12 @@ static const mp_obj_type_t py_lbp_type = {
.print = py_lbp_print,
};
// Keypoints match object /////////////////////////////////////////////////////
#endif // IMLIB_ENABLE_FIND_LBP
// Keypoints Match Object /////////////////////////////////////////////////////
#ifdef IMLIB_ENABLE_FIND_KEYPOINTS
#define kptmatch_obj_size 9
typedef struct _py_kptmatch_obj_t {
mp_obj_base_t base;
@ -227,6 +238,8 @@ static const mp_obj_type_t py_kptmatch_type = {
.locals_dict = (mp_obj_t) &py_kptmatch_locals_dict
};
#endif // IMLIB_ENABLE_FIND_KEYPOINTS
// Image //////////////////////////////////////////////////////////////////////
typedef struct _py_image_obj_t {
@ -630,6 +643,7 @@ STATIC mp_obj_t py_image_set_pixel(uint n_args, const mp_obj_t *args, mp_map_t *
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_set_pixel_obj, 2, py_image_set_pixel);
#ifdef IMLIB_ENABLE_MEAN_POOLING
static mp_obj_t py_image_mean_pool(mp_obj_t img_obj, mp_obj_t x_div_obj, mp_obj_t y_div_obj)
{
image_t *arg_img = py_helper_arg_to_image_mutable(img_obj);
@ -681,7 +695,9 @@ static mp_obj_t py_image_mean_pooled(mp_obj_t img_obj, mp_obj_t x_div_obj, mp_ob
return py_image_from_struct(&out_img);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(py_image_mean_pooled_obj, py_image_mean_pooled);
#endif // IMLIB_ENABLE_MEAN_POOLING
#ifdef IMLIB_ENABLE_MIDPOINT_POOLING
static mp_obj_t py_image_midpoint_pool(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
image_t *arg_img = py_helper_arg_to_image_mutable(args[0]);
@ -739,6 +755,7 @@ static mp_obj_t py_image_midpoint_pooled(uint n_args, const mp_obj_t *args, mp_m
return py_image_from_struct(&out_img);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_midpoint_pooled_obj, 3, py_image_midpoint_pooled);
#endif // IMLIB_ENABLE_MIDPOINT_POOLING
static mp_obj_t py_image_to_bitmap(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
@ -1424,6 +1441,52 @@ STATIC mp_obj_t py_image_draw_arrow(uint n_args, const mp_obj_t *args, mp_map_t
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_draw_arrow_obj, 2, py_image_draw_arrow);
STATIC mp_obj_t py_image_draw_edges(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
image_t *arg_img = py_helper_arg_to_image_mutable(args[0]);
mp_obj_t *corners, *p0, *p1, *p2, *p3;
mp_obj_get_array_fixed_n(args[1], 4, &corners);
mp_obj_get_array_fixed_n(corners[0], 2, &p0);
mp_obj_get_array_fixed_n(corners[1], 2, &p1);
mp_obj_get_array_fixed_n(corners[2], 2, &p2);
mp_obj_get_array_fixed_n(corners[3], 2, &p3);
int x0, y0, x1, y1, x2, y2, x3, y3;
x0 = mp_obj_get_int(p0[0]);
y0 = mp_obj_get_int(p0[1]);
x1 = mp_obj_get_int(p1[0]);
y1 = mp_obj_get_int(p1[1]);
x2 = mp_obj_get_int(p2[0]);
y2 = mp_obj_get_int(p2[1]);
x3 = mp_obj_get_int(p3[0]);
y3 = mp_obj_get_int(p3[1]);
int arg_c =
py_helper_keyword_color(arg_img, n_args, args, 2, kw_args, -1); // White.
int arg_s =
py_helper_keyword_int(n_args, args, 3, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_size), 0);
int arg_thickness =
py_helper_keyword_int(n_args, args, 4, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_thickness), 1);
bool arg_fill =
py_helper_keyword_int(n_args, args, 5, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_fill), false);
imlib_draw_line(arg_img, x0, y0, x1, y1, arg_c, arg_thickness);
imlib_draw_line(arg_img, x1, y1, x2, y2, arg_c, arg_thickness);
imlib_draw_line(arg_img, x2, y2, x3, y3, arg_c, arg_thickness);
imlib_draw_line(arg_img, x3, y3, x0, y0, arg_c, arg_thickness);
if (arg_s >= 1) {
imlib_draw_circle(arg_img, x0, y0, arg_s, arg_c, arg_thickness, arg_fill);
imlib_draw_circle(arg_img, x1, y1, arg_s, arg_c, arg_thickness, arg_fill);
imlib_draw_circle(arg_img, x2, y2, arg_s, arg_c, arg_thickness, arg_fill);
imlib_draw_circle(arg_img, x3, y3, arg_s, arg_c, arg_thickness, arg_fill);
}
return args[0];
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_draw_edges_obj, 2, py_image_draw_edges);
STATIC mp_obj_t py_image_draw_image(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
image_t *arg_img = py_helper_arg_to_image_mutable(args[0]);
@ -1482,6 +1545,7 @@ STATIC mp_obj_t py_image_draw_keypoints(uint n_args, const mp_obj_t *args, mp_ma
imlib_draw_circle(arg_img, cx, cy, (arg_s - 2) / 2, arg_c, arg_thickness, arg_fill);
}
} else {
#ifdef IMLIB_ENABLE_FIND_KEYPOINTS
py_kp_obj_t *kpts_obj = py_kpts_obj(args[1]);
for (int i = 0, ii = array_length(kpts_obj->kpts); i < ii; i++) {
kp_t *kp = array_at(kpts_obj->kpts, i);
@ -1493,6 +1557,9 @@ STATIC mp_obj_t py_image_draw_keypoints(uint n_args, const mp_obj_t *args, mp_ma
imlib_draw_line(arg_img, cx, cy, cx + co, cy + si, arg_c, arg_thickness);
imlib_draw_circle(arg_img, cx, cy, (arg_s - 2) / 2, arg_c, arg_thickness, arg_fill);
}
#else
PY_ASSERT_TRUE_MSG(false, "Expected a list of tuples!");
#endif // IMLIB_ENABLE_FIND_KEYPOINTS
}
return args[0];
@ -3743,27 +3810,35 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_get_regression_obj, 2, py_image_get_r
///////////////
// Blob Object //
#define py_blob_obj_size 10
#define py_blob_obj_size 12
typedef struct py_blob_obj {
mp_obj_base_t base;
mp_obj_t x, y, w, h, pixels, cx, cy, rotation, code, count;
mp_obj_t corners;
mp_obj_t min_corners;
mp_obj_t x, y, w, h, pixels, cx, cy, rotation, code, count, perimeter, roundness;
mp_obj_t x_hist_bins;
mp_obj_t y_hist_bins;
} py_blob_obj_t;
static void py_blob_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind)
{
py_blob_obj_t *self = self_in;
mp_printf(print,
"{\"x\":%d, \"y\":%d, \"w\":%d, \"h\":%d, \"pixels\":%d, \"cx\":%d, \"cy\":%d, \"rotation\":%f, \"code\":%d, \"count\":%d}",
"{\"x\":%d, \"y\":%d, \"w\":%d, \"h\":%d,"
" \"pixels\":%d, \"cx\":%d, \"cy\":%d, \"rotation\":%f, \"code\":%d, \"count\":%d,"
" \"perimeter\":%d, \"roundness:%f\"}",
mp_obj_get_int(self->x),
mp_obj_get_int(self->y),
mp_obj_get_int(self->w),
mp_obj_get_int(self->h),
mp_obj_get_int(self->pixels),
mp_obj_get_int(self->cx),
mp_obj_get_int(self->cy),
fast_roundf(mp_obj_get_float(self->cx)),
fast_roundf(mp_obj_get_float(self->cy)),
(double) mp_obj_get_float(self->rotation),
mp_obj_get_int(self->code),
mp_obj_get_int(self->count));
mp_obj_get_int(self->count),
mp_obj_get_int(self->perimeter),
(double) mp_obj_get_float(self->roundness));
}
static mp_obj_t py_blob_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value)
@ -3785,16 +3860,20 @@ static mp_obj_t py_blob_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value)
case 2: return self->w;
case 3: return self->h;
case 4: return self->pixels;
case 5: return self->cx;
case 6: return self->cy;
case 5: return mp_obj_new_int(fast_roundf(mp_obj_get_float(self->cx)));
case 6: return mp_obj_new_int(fast_roundf(mp_obj_get_float(self->cy)));
case 7: return self->rotation;
case 8: return self->code;
case 9: return self->count;
case 10: return self->perimeter;
case 11: return self->roundness;
}
}
return MP_OBJ_NULL; // op not supported
}
mp_obj_t py_blob_corners(mp_obj_t self_in) { return ((py_blob_obj_t *) self_in)->corners; }
mp_obj_t py_blob_min_corners(mp_obj_t self_in) { return ((py_blob_obj_t *) self_in)->min_corners; }
mp_obj_t py_blob_rect(mp_obj_t self_in)
{
return mp_obj_new_tuple(4, (mp_obj_t []) {((py_blob_obj_t *) self_in)->x,
@ -3808,20 +3887,261 @@ mp_obj_t py_blob_y(mp_obj_t self_in) { return ((py_blob_obj_t *) self_in)->y; }
mp_obj_t py_blob_w(mp_obj_t self_in) { return ((py_blob_obj_t *) self_in)->w; }
mp_obj_t py_blob_h(mp_obj_t self_in) { return ((py_blob_obj_t *) self_in)->h; }
mp_obj_t py_blob_pixels(mp_obj_t self_in) { return ((py_blob_obj_t *) self_in)->pixels; }
mp_obj_t py_blob_cx(mp_obj_t self_in) { return ((py_blob_obj_t *) self_in)->cx; }
mp_obj_t py_blob_cy(mp_obj_t self_in) { return ((py_blob_obj_t *) self_in)->cy; }
mp_obj_t py_blob_cx(mp_obj_t self_in) { return mp_obj_new_int(fast_roundf(mp_obj_get_float(((py_blob_obj_t *) self_in)->cx))); }
mp_obj_t py_blob_cxf(mp_obj_t self_in) { return ((py_blob_obj_t *) self_in)->cx; }
mp_obj_t py_blob_cy(mp_obj_t self_in) { return mp_obj_new_int(fast_roundf(mp_obj_get_float(((py_blob_obj_t *) self_in)->cy))); }
mp_obj_t py_blob_cyf(mp_obj_t self_in) { return ((py_blob_obj_t *) self_in)->cy; }
mp_obj_t py_blob_rotation(mp_obj_t self_in) { return ((py_blob_obj_t *) self_in)->rotation; }
mp_obj_t py_blob_rotation_deg(mp_obj_t self_in) { return mp_obj_new_int(IM_RAD2DEG(mp_obj_get_float(((py_blob_obj_t *) self_in)->rotation))); }
mp_obj_t py_blob_rotation_rad(mp_obj_t self_in) { return ((py_blob_obj_t *) self_in)->rotation; }
mp_obj_t py_blob_code(mp_obj_t self_in) { return ((py_blob_obj_t *) self_in)->code; }
mp_obj_t py_blob_count(mp_obj_t self_in) { return ((py_blob_obj_t *) self_in)->count; }
mp_obj_t py_blob_perimeter(mp_obj_t self_in) { return ((py_blob_obj_t *) self_in)->perimeter; }
mp_obj_t py_blob_roundness(mp_obj_t self_in) { return ((py_blob_obj_t *) self_in)->roundness; }
mp_obj_t py_blob_elongation(mp_obj_t self_in) { return mp_obj_new_float(1 - mp_obj_get_float(((py_blob_obj_t *) self_in)->roundness)); }
mp_obj_t py_blob_area(mp_obj_t self_in) {
return mp_obj_new_int(mp_obj_get_int(((py_blob_obj_t *) self_in)->w) * mp_obj_get_int(((py_blob_obj_t *) self_in)->h));
}
mp_obj_t py_blob_density(mp_obj_t self_in) {
int area = mp_obj_get_int(((py_blob_obj_t *) self_in)->w) * mp_obj_get_int(((py_blob_obj_t *) self_in)->h);
if (area) return mp_obj_new_float(mp_obj_get_int(((py_blob_obj_t *) self_in)->pixels) / ((float) area));
return mp_obj_new_float(0.0f);
int pixels = mp_obj_get_int(((py_blob_obj_t *) self_in)->pixels);
return mp_obj_new_float(IM_DIV(pixels, ((float) area)));
}
// Rect-area versus pixels (e.g. blob area) -> Above.
// Rect-area versus perimeter -> Basically the same as the above with a different scale factor.
// Rect-perimeter versus pixels (e.g. blob area) -> Basically the same as the above with a different scale factor.
// Rect-perimeter versus perimeter -> Basically the same as the above with a different scale factor.
mp_obj_t py_blob_compactness(mp_obj_t self_in) {
int pixels = mp_obj_get_int(((py_blob_obj_t *) self_in)->pixels);
float perimeter = mp_obj_get_int(((py_blob_obj_t *) self_in)->perimeter);
return mp_obj_new_float(IM_DIV((pixels * 4 * M_PI), (perimeter * perimeter)));
}
mp_obj_t py_blob_solidity(mp_obj_t self_in) {
mp_obj_t *corners, *p0, *p1, *p2, *p3;
mp_obj_get_array_fixed_n(((py_blob_obj_t *) self_in)->min_corners, 4, &corners);
mp_obj_get_array_fixed_n(corners[0], 2, &p0);
mp_obj_get_array_fixed_n(corners[1], 2, &p1);
mp_obj_get_array_fixed_n(corners[2], 2, &p2);
mp_obj_get_array_fixed_n(corners[3], 2, &p3);
int x0, y0, x1, y1, x2, y2, x3, y3;
x0 = mp_obj_get_int(p0[0]);
y0 = mp_obj_get_int(p0[1]);
x1 = mp_obj_get_int(p1[0]);
y1 = mp_obj_get_int(p1[1]);
x2 = mp_obj_get_int(p2[0]);
y2 = mp_obj_get_int(p2[1]);
x3 = mp_obj_get_int(p3[0]);
y3 = mp_obj_get_int(p3[1]);
// Shoelace Formula
float min_area = (((x0*y1)+(x1*y2)+(x2*y3)+(x3*y0))-((y0*x1)+(y1*x2)+(y2*x3)+(y3*x0)))/2.0f;
int pixels = mp_obj_get_int(((py_blob_obj_t *) self_in)->pixels);
return mp_obj_new_float(IM_MIN(IM_DIV(pixels, min_area), 1));
}
mp_obj_t py_blob_convexity(mp_obj_t self_in) {
mp_obj_t *corners, *p0, *p1, *p2, *p3;
mp_obj_get_array_fixed_n(((py_blob_obj_t *) self_in)->min_corners, 4, &corners);
mp_obj_get_array_fixed_n(corners[0], 2, &p0);
mp_obj_get_array_fixed_n(corners[1], 2, &p1);
mp_obj_get_array_fixed_n(corners[2], 2, &p2);
mp_obj_get_array_fixed_n(corners[3], 2, &p3);
int x0, y0, x1, y1, x2, y2, x3, y3;
x0 = mp_obj_get_int(p0[0]);
y0 = mp_obj_get_int(p0[1]);
x1 = mp_obj_get_int(p1[0]);
y1 = mp_obj_get_int(p1[1]);
x2 = mp_obj_get_int(p2[0]);
y2 = mp_obj_get_int(p2[1]);
x3 = mp_obj_get_int(p3[0]);
y3 = mp_obj_get_int(p3[1]);
float d0 = fast_sqrtf(((x0 - x1) * (x0 - x1)) + ((y0 - y1) * (y0 - y1)));
float d1 = fast_sqrtf(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
float d2 = fast_sqrtf(((x2 - x3) * (x2 - x3)) + ((y2 - y3) * (y2 - y3)));
float d3 = fast_sqrtf(((x3 - x0) * (x3 - x0)) + ((y3 - y0) * (y3 - y0)));
int perimeter = mp_obj_get_int(((py_blob_obj_t *) self_in)->perimeter);
return mp_obj_new_float(IM_MIN(IM_DIV(d0 + d1 + d2 + d3, perimeter), 1));
}
// Min rect-area versus pixels (e.g. blob area) -> Above.
// Min rect-area versus perimeter -> Basically the same as the above with a different scale factor.
// Min rect-perimeter versus pixels (e.g. blob area) -> Basically the same as the above with a different scale factor.
// Min rect-perimeter versus perimeter -> Above
mp_obj_t py_blob_x_hist_bins(mp_obj_t self_in) { return ((py_blob_obj_t *) self_in)->x_hist_bins; }
mp_obj_t py_blob_y_hist_bins(mp_obj_t self_in) { return ((py_blob_obj_t *) self_in)->y_hist_bins; }
mp_obj_t py_blob_major_axis_line(mp_obj_t self_in) {
mp_obj_t *corners, *p0, *p1, *p2, *p3;
mp_obj_get_array_fixed_n(((py_blob_obj_t *) self_in)->min_corners, 4, &corners);
mp_obj_get_array_fixed_n(corners[0], 2, &p0);
mp_obj_get_array_fixed_n(corners[1], 2, &p1);
mp_obj_get_array_fixed_n(corners[2], 2, &p2);
mp_obj_get_array_fixed_n(corners[3], 2, &p3);
int x0, y0, x1, y1, x2, y2, x3, y3;
x0 = mp_obj_get_int(p0[0]);
y0 = mp_obj_get_int(p0[1]);
x1 = mp_obj_get_int(p1[0]);
y1 = mp_obj_get_int(p1[1]);
x2 = mp_obj_get_int(p2[0]);
y2 = mp_obj_get_int(p2[1]);
x3 = mp_obj_get_int(p3[0]);
y3 = mp_obj_get_int(p3[1]);
int m0x = (x0 + x1) / 2;
int m0y = (y0 + y1) / 2;
int m1x = (x1 + x2) / 2;
int m1y = (y1 + y2) / 2;
int m2x = (x2 + x3) / 2;
int m2y = (y2 + y3) / 2;
int m3x = (x3 + x0) / 2;
int m3y = (y3 + y0) / 2;
float l0 = fast_sqrtf(((m0x - m2x) * (m0x - m2x)) + ((m0y - m2y) * (m0y - m2y)));
float l1 = fast_sqrtf(((m1x - m3x) * (m1x - m3x)) + ((m1y - m3y) * (m1y - m3y)));
if (l0 >= l1) {
return mp_obj_new_tuple(4, (mp_obj_t []) {mp_obj_new_int(m0x),
mp_obj_new_int(m0y),
mp_obj_new_int(m2x),
mp_obj_new_int(m2y)});
} else {
return mp_obj_new_tuple(4, (mp_obj_t []) {mp_obj_new_int(m1x),
mp_obj_new_int(m1y),
mp_obj_new_int(m3x),
mp_obj_new_int(m3y)});
}
}
mp_obj_t py_blob_minor_axis_line(mp_obj_t self_in) {
mp_obj_t *corners, *p0, *p1, *p2, *p3;
mp_obj_get_array_fixed_n(((py_blob_obj_t *) self_in)->min_corners, 4, &corners);
mp_obj_get_array_fixed_n(corners[0], 2, &p0);
mp_obj_get_array_fixed_n(corners[1], 2, &p1);
mp_obj_get_array_fixed_n(corners[2], 2, &p2);
mp_obj_get_array_fixed_n(corners[3], 2, &p3);
int x0, y0, x1, y1, x2, y2, x3, y3;
x0 = mp_obj_get_int(p0[0]);
y0 = mp_obj_get_int(p0[1]);
x1 = mp_obj_get_int(p1[0]);
y1 = mp_obj_get_int(p1[1]);
x2 = mp_obj_get_int(p2[0]);
y2 = mp_obj_get_int(p2[1]);
x3 = mp_obj_get_int(p3[0]);
y3 = mp_obj_get_int(p3[1]);
int m0x = (x0 + x1) / 2;
int m0y = (y0 + y1) / 2;
int m1x = (x1 + x2) / 2;
int m1y = (y1 + y2) / 2;
int m2x = (x2 + x3) / 2;
int m2y = (y2 + y3) / 2;
int m3x = (x3 + x0) / 2;
int m3y = (y3 + y0) / 2;
float l0 = fast_sqrtf(((m0x - m2x) * (m0x - m2x)) + ((m0y - m2y) * (m0y - m2y)));
float l1 = fast_sqrtf(((m1x - m3x) * (m1x - m3x)) + ((m1y - m3y) * (m1y - m3y)));
if (l0 < l1) {
return mp_obj_new_tuple(4, (mp_obj_t []) {mp_obj_new_int(m0x),
mp_obj_new_int(m0y),
mp_obj_new_int(m2x),
mp_obj_new_int(m2y)});
} else {
return mp_obj_new_tuple(4, (mp_obj_t []) {mp_obj_new_int(m1x),
mp_obj_new_int(m1y),
mp_obj_new_int(m3x),
mp_obj_new_int(m3y)});
}
}
mp_obj_t py_blob_enclosing_circle(mp_obj_t self_in) {
mp_obj_t *corners, *p0, *p1, *p2, *p3;
mp_obj_get_array_fixed_n(((py_blob_obj_t *) self_in)->min_corners, 4, &corners);
mp_obj_get_array_fixed_n(corners[0], 2, &p0);
mp_obj_get_array_fixed_n(corners[1], 2, &p1);
mp_obj_get_array_fixed_n(corners[2], 2, &p2);
mp_obj_get_array_fixed_n(corners[3], 2, &p3);
int x0, y0, x1, y1, x2, y2, x3, y3;
x0 = mp_obj_get_int(p0[0]);
y0 = mp_obj_get_int(p0[1]);
x1 = mp_obj_get_int(p1[0]);
y1 = mp_obj_get_int(p1[1]);
x2 = mp_obj_get_int(p2[0]);
y2 = mp_obj_get_int(p2[1]);
x3 = mp_obj_get_int(p3[0]);
y3 = mp_obj_get_int(p3[1]);
int cx = (x0 + x1 + x2 + x3) / 4;
int cy = (y0 + y1 + y2 + y3) / 4;
float d0 = fast_sqrtf(((x0 - cx) * (x0 - cx)) + ((y0 - cy) * (y0 - cy)));
float d1 = fast_sqrtf(((x1 - cx) * (x1 - cx)) + ((y1 - cy) * (y1 - cy)));
float d2 = fast_sqrtf(((x2 - cx) * (x2 - cx)) + ((y2 - cy) * (y2 - cy)));
float d3 = fast_sqrtf(((x3 - cx) * (x3 - cx)) + ((y3 - cy) * (y3 - cy)));
float d = IM_MAX(d0, IM_MAX(d1, IM_MAX(d2, d3)));
return mp_obj_new_tuple(3, (mp_obj_t []) {mp_obj_new_int(cx),
mp_obj_new_int(cy),
mp_obj_new_int(fast_roundf(d))});
}
mp_obj_t py_blob_enclosed_ellipse(mp_obj_t self_in) {
mp_obj_t *corners, *p0, *p1, *p2, *p3;
mp_obj_get_array_fixed_n(((py_blob_obj_t *) self_in)->min_corners, 4, &corners);
mp_obj_get_array_fixed_n(corners[0], 2, &p0);
mp_obj_get_array_fixed_n(corners[1], 2, &p1);
mp_obj_get_array_fixed_n(corners[2], 2, &p2);
mp_obj_get_array_fixed_n(corners[3], 2, &p3);
int x0, y0, x1, y1, x2, y2, x3, y3;
x0 = mp_obj_get_int(p0[0]);
y0 = mp_obj_get_int(p0[1]);
x1 = mp_obj_get_int(p1[0]);
y1 = mp_obj_get_int(p1[1]);
x2 = mp_obj_get_int(p2[0]);
y2 = mp_obj_get_int(p2[1]);
x3 = mp_obj_get_int(p3[0]);
y3 = mp_obj_get_int(p3[1]);
int m0x = (x0 + x1) / 2;
int m0y = (y0 + y1) / 2;
int m1x = (x1 + x2) / 2;
int m1y = (y1 + y2) / 2;
int m2x = (x2 + x3) / 2;
int m2y = (y2 + y3) / 2;
int m3x = (x3 + x0) / 2;
int m3y = (y3 + y0) / 2;
int cx = (x0 + x1 + x2 + x3) / 4;
int cy = (y0 + y1 + y2 + y3) / 4;
float d0 = fast_sqrtf(((m0x - cx) * (m0x - cx)) + ((m0y - cy) * (m0y - cy)));
float d1 = fast_sqrtf(((m1x - cx) * (m1x - cx)) + ((m1y - cy) * (m1y - cy)));
float d2 = fast_sqrtf(((m2x - cx) * (m2x - cx)) + ((m2y - cy) * (m2y - cy)));
float d3 = fast_sqrtf(((m3x - cx) * (m3x - cx)) + ((m3y - cy) * (m3y - cy)));
float a = IM_MIN(d0, d2);
float b = IM_MIN(d1, d3);
float l0 = fast_sqrtf(((m0x - m2x) * (m0x - m2x)) + ((m0y - m2y) * (m0y - m2y)));
float l1 = fast_sqrtf(((m1x - m3x) * (m1x - m3x)) + ((m1y - m3y) * (m1y - m3y)));
float r;
if (l0 >= l1) {
r = IM_RAD2DEG(fast_atan2f(m0y - m2y, m0x - m2x));
} else {
r = IM_RAD2DEG(fast_atan2f(m1y - m3y, m1x - m3x) + M_PI_2);
}
return mp_obj_new_tuple(5, (mp_obj_t []) {mp_obj_new_int(cx),
mp_obj_new_int(cy),
mp_obj_new_int(a),
mp_obj_new_int(b),
mp_obj_new_int(r)});
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_corners_obj, py_blob_corners);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_min_corners_obj, py_blob_min_corners);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_rect_obj, py_blob_rect);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_x_obj, py_blob_x);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_y_obj, py_blob_y);
@ -3829,14 +4149,32 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_w_obj, py_blob_w);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_h_obj, py_blob_h);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_pixels_obj, py_blob_pixels);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_cx_obj, py_blob_cx);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_cxf_obj, py_blob_cxf);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_cy_obj, py_blob_cy);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_cyf_obj, py_blob_cyf);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_rotation_obj, py_blob_rotation);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_rotation_deg_obj, py_blob_rotation_deg);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_rotation_rad_obj, py_blob_rotation_rad);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_code_obj, py_blob_code);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_count_obj, py_blob_count);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_perimeter_obj, py_blob_perimeter);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_roundness_obj, py_blob_roundness);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_elongation_obj, py_blob_elongation);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_area_obj, py_blob_area);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_density_obj, py_blob_density);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_compactness_obj, py_blob_compactness);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_solidity_obj, py_blob_solidity);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_convexity_obj, py_blob_convexity);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_x_hist_bins_obj, py_blob_x_hist_bins);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_y_hist_bins_obj, py_blob_y_hist_bins);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_major_axis_line_obj, py_blob_major_axis_line);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_minor_axis_line_obj, py_blob_minor_axis_line);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_enclosing_circle_obj, py_blob_enclosing_circle);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_blob_enclosed_ellipse_obj, py_blob_enclosed_ellipse);
STATIC const mp_rom_map_elem_t py_blob_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_corners), MP_ROM_PTR(&py_blob_corners_obj) },
{ MP_ROM_QSTR(MP_QSTR_min_corners), MP_ROM_PTR(&py_blob_min_corners_obj) },
{ MP_ROM_QSTR(MP_QSTR_rect), MP_ROM_PTR(&py_blob_rect_obj) },
{ MP_ROM_QSTR(MP_QSTR_x), MP_ROM_PTR(&py_blob_x_obj) },
{ MP_ROM_QSTR(MP_QSTR_y), MP_ROM_PTR(&py_blob_y_obj) },
@ -3844,12 +4182,29 @@ STATIC const mp_rom_map_elem_t py_blob_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_h), MP_ROM_PTR(&py_blob_h_obj) },
{ MP_ROM_QSTR(MP_QSTR_pixels), MP_ROM_PTR(&py_blob_pixels_obj) },
{ MP_ROM_QSTR(MP_QSTR_cx), MP_ROM_PTR(&py_blob_cx_obj) },
{ MP_ROM_QSTR(MP_QSTR_cxf), MP_ROM_PTR(&py_blob_cxf_obj) },
{ MP_ROM_QSTR(MP_QSTR_cy), MP_ROM_PTR(&py_blob_cy_obj) },
{ MP_ROM_QSTR(MP_QSTR_cyf), MP_ROM_PTR(&py_blob_cyf_obj) },
{ MP_ROM_QSTR(MP_QSTR_rotation), MP_ROM_PTR(&py_blob_rotation_obj) },
{ MP_ROM_QSTR(MP_QSTR_rotation_deg), MP_ROM_PTR(&py_blob_rotation_deg_obj) },
{ MP_ROM_QSTR(MP_QSTR_rotation_rad), MP_ROM_PTR(&py_blob_rotation_rad_obj) },
{ MP_ROM_QSTR(MP_QSTR_code), MP_ROM_PTR(&py_blob_code_obj) },
{ MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&py_blob_count_obj) },
{ MP_ROM_QSTR(MP_QSTR_perimeter), MP_ROM_PTR(&py_blob_perimeter_obj) },
{ MP_ROM_QSTR(MP_QSTR_roundness), MP_ROM_PTR(&py_blob_roundness_obj) },
{ MP_ROM_QSTR(MP_QSTR_elongation), MP_ROM_PTR(&py_blob_elongation_obj) },
{ MP_ROM_QSTR(MP_QSTR_area), MP_ROM_PTR(&py_blob_area_obj) } ,
{ MP_ROM_QSTR(MP_QSTR_density), MP_ROM_PTR(&py_blob_density_obj) }
{ MP_ROM_QSTR(MP_QSTR_density), MP_ROM_PTR(&py_blob_density_obj) },
{ MP_ROM_QSTR(MP_QSTR_extent), MP_ROM_PTR(&py_blob_density_obj) },
{ MP_ROM_QSTR(MP_QSTR_compactness), MP_ROM_PTR(&py_blob_compactness_obj) },
{ MP_ROM_QSTR(MP_QSTR_solidity), MP_ROM_PTR(&py_blob_solidity_obj) },
{ MP_ROM_QSTR(MP_QSTR_convexity), MP_ROM_PTR(&py_blob_convexity_obj) },
{ MP_ROM_QSTR(MP_QSTR_x_hist_bins), MP_ROM_PTR(&py_blob_x_hist_bins_obj) },
{ MP_ROM_QSTR(MP_QSTR_y_hist_bins), MP_ROM_PTR(&py_blob_y_hist_bins_obj) },
{ MP_ROM_QSTR(MP_QSTR_major_axis_line), MP_ROM_PTR(&py_blob_major_axis_line_obj) },
{ MP_ROM_QSTR(MP_QSTR_minor_axis_line), MP_ROM_PTR(&py_blob_minor_axis_line_obj) },
{ MP_ROM_QSTR(MP_QSTR_enclosing_circle), MP_ROM_PTR(&py_blob_enclosing_circle_obj) },
{ MP_ROM_QSTR(MP_QSTR_enclosed_ellipse), MP_ROM_PTR(&py_blob_enclosed_ellipse_obj) }
};
STATIC MP_DEFINE_CONST_DICT(py_blob_locals_dict, py_blob_locals_dict_table);
@ -3866,16 +4221,44 @@ static bool py_image_find_blobs_threshold_cb(void *fun_obj, find_blobs_list_lnk_
{
py_blob_obj_t *o = m_new_obj(py_blob_obj_t);
o->base.type = &py_blob_type;
o->corners = mp_obj_new_tuple(4, (mp_obj_t [])
{mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(blob->corners[(FIND_BLOBS_CORNERS_RESOLUTION*0)/4].x),
mp_obj_new_int(blob->corners[(FIND_BLOBS_CORNERS_RESOLUTION*0)/4].y)}),
mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(blob->corners[(FIND_BLOBS_CORNERS_RESOLUTION*1)/4].x),
mp_obj_new_int(blob->corners[(FIND_BLOBS_CORNERS_RESOLUTION*1)/4].y)}),
mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(blob->corners[(FIND_BLOBS_CORNERS_RESOLUTION*2)/4].x),
mp_obj_new_int(blob->corners[(FIND_BLOBS_CORNERS_RESOLUTION*2)/4].y)}),
mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(blob->corners[(FIND_BLOBS_CORNERS_RESOLUTION*3)/4].x),
mp_obj_new_int(blob->corners[(FIND_BLOBS_CORNERS_RESOLUTION*3)/4].y)})});
point_t min_corners[4];
point_min_area_rectangle(blob->corners, min_corners, FIND_BLOBS_CORNERS_RESOLUTION);
o->min_corners = mp_obj_new_tuple(4, (mp_obj_t [])
{mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(min_corners[0].x), mp_obj_new_int(min_corners[0].y)}),
mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(min_corners[1].x), mp_obj_new_int(min_corners[1].y)}),
mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(min_corners[2].x), mp_obj_new_int(min_corners[2].y)}),
mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(min_corners[3].x), mp_obj_new_int(min_corners[3].y)})});
o->x = mp_obj_new_int(blob->rect.x);
o->y = mp_obj_new_int(blob->rect.y);
o->w = mp_obj_new_int(blob->rect.w);
o->h = mp_obj_new_int(blob->rect.h);
o->pixels = mp_obj_new_int(blob->pixels);
o->cx = mp_obj_new_int(blob->centroid.x);
o->cy = mp_obj_new_int(blob->centroid.y);
o->cx = mp_obj_new_float(blob->centroid_x);
o->cy = mp_obj_new_float(blob->centroid_y);
o->rotation = mp_obj_new_float(blob->rotation);
o->code = mp_obj_new_int(blob->code);
o->count = mp_obj_new_int(blob->count);
o->perimeter = mp_obj_new_int(blob->perimeter);
o->roundness = mp_obj_new_float(blob->roundness);
o->x_hist_bins = mp_obj_new_list(blob->x_hist_bins_count, NULL);
o->y_hist_bins = mp_obj_new_list(blob->y_hist_bins_count, NULL);
for (int i = 0; i < blob->x_hist_bins_count; i++) {
((mp_obj_list_t *) o->x_hist_bins)->items[i] = mp_obj_new_int(blob->x_hist_bins[i]);
}
for (int i = 0; i < blob->y_hist_bins_count; i++) {
((mp_obj_list_t *) o->y_hist_bins)->items[i] = mp_obj_new_int(blob->y_hist_bins[i]);
}
return mp_obj_is_true(mp_call_function_1(fun_obj, o));
}
@ -3884,29 +4267,85 @@ static bool py_image_find_blobs_merge_cb(void *fun_obj, find_blobs_list_lnk_data
{
py_blob_obj_t *o0 = m_new_obj(py_blob_obj_t);
o0->base.type = &py_blob_type;
o0->corners = mp_obj_new_tuple(4, (mp_obj_t [])
{mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(blob0->corners[(FIND_BLOBS_CORNERS_RESOLUTION*0)/4].x),
mp_obj_new_int(blob0->corners[(FIND_BLOBS_CORNERS_RESOLUTION*0)/4].y)}),
mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(blob0->corners[(FIND_BLOBS_CORNERS_RESOLUTION*1)/4].x),
mp_obj_new_int(blob0->corners[(FIND_BLOBS_CORNERS_RESOLUTION*1)/4].y)}),
mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(blob0->corners[(FIND_BLOBS_CORNERS_RESOLUTION*2)/4].x),
mp_obj_new_int(blob0->corners[(FIND_BLOBS_CORNERS_RESOLUTION*2)/4].y)}),
mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(blob0->corners[(FIND_BLOBS_CORNERS_RESOLUTION*3)/4].x),
mp_obj_new_int(blob0->corners[(FIND_BLOBS_CORNERS_RESOLUTION*3)/4].y)})});
point_t min_area_rect_corners0[4];
point_min_area_rectangle(blob0->corners, min_area_rect_corners0, FIND_BLOBS_CORNERS_RESOLUTION);
o0->min_corners = mp_obj_new_tuple(4, (mp_obj_t [])
{mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(min_area_rect_corners0[0].x), mp_obj_new_int(min_area_rect_corners0[0].y)}),
mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(min_area_rect_corners0[1].x), mp_obj_new_int(min_area_rect_corners0[1].y)}),
mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(min_area_rect_corners0[2].x), mp_obj_new_int(min_area_rect_corners0[2].y)}),
mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(min_area_rect_corners0[3].x), mp_obj_new_int(min_area_rect_corners0[3].y)})});
o0->x = mp_obj_new_int(blob0->rect.x);
o0->y = mp_obj_new_int(blob0->rect.y);
o0->w = mp_obj_new_int(blob0->rect.w);
o0->h = mp_obj_new_int(blob0->rect.h);
o0->pixels = mp_obj_new_int(blob0->pixels);
o0->cx = mp_obj_new_int(blob0->centroid.x);
o0->cy = mp_obj_new_int(blob0->centroid.y);
o0->cx = mp_obj_new_float(blob0->centroid_x);
o0->cy = mp_obj_new_float(blob0->centroid_y);
o0->rotation = mp_obj_new_float(blob0->rotation);
o0->code = mp_obj_new_int(blob0->code);
o0->count = mp_obj_new_int(blob0->count);
o0->perimeter = mp_obj_new_int(blob0->perimeter);
o0->roundness = mp_obj_new_float(blob0->roundness);
o0->x_hist_bins = mp_obj_new_list(blob0->x_hist_bins_count, NULL);
o0->y_hist_bins = mp_obj_new_list(blob0->y_hist_bins_count, NULL);
for (int i = 0; i < blob0->x_hist_bins_count; i++) {
((mp_obj_list_t *) o0->x_hist_bins)->items[i] = mp_obj_new_int(blob0->x_hist_bins[i]);
}
for (int i = 0; i < blob0->y_hist_bins_count; i++) {
((mp_obj_list_t *) o0->y_hist_bins)->items[i] = mp_obj_new_int(blob0->y_hist_bins[i]);
}
py_blob_obj_t *o1 = m_new_obj(py_blob_obj_t);
o1->base.type = &py_blob_type;
o1->corners = mp_obj_new_tuple(4, (mp_obj_t [])
{mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(blob1->corners[(FIND_BLOBS_CORNERS_RESOLUTION*0)/4].x),
mp_obj_new_int(blob1->corners[(FIND_BLOBS_CORNERS_RESOLUTION*0)/4].y)}),
mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(blob1->corners[(FIND_BLOBS_CORNERS_RESOLUTION*1)/4].x),
mp_obj_new_int(blob1->corners[(FIND_BLOBS_CORNERS_RESOLUTION*1)/4].y)}),
mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(blob1->corners[(FIND_BLOBS_CORNERS_RESOLUTION*2)/4].x),
mp_obj_new_int(blob1->corners[(FIND_BLOBS_CORNERS_RESOLUTION*2)/4].y)}),
mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(blob1->corners[(FIND_BLOBS_CORNERS_RESOLUTION*3)/4].x),
mp_obj_new_int(blob1->corners[(FIND_BLOBS_CORNERS_RESOLUTION*3)/4].y)})});
point_t min_area_rect_corners1[4];
point_min_area_rectangle(blob1->corners, min_area_rect_corners1, FIND_BLOBS_CORNERS_RESOLUTION);
o1->min_corners = mp_obj_new_tuple(4, (mp_obj_t [])
{mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(min_area_rect_corners1[0].x), mp_obj_new_int(min_area_rect_corners1[0].y)}),
mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(min_area_rect_corners1[1].x), mp_obj_new_int(min_area_rect_corners1[1].y)}),
mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(min_area_rect_corners1[2].x), mp_obj_new_int(min_area_rect_corners1[2].y)}),
mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(min_area_rect_corners1[3].x), mp_obj_new_int(min_area_rect_corners1[3].y)})});
o1->x = mp_obj_new_int(blob1->rect.x);
o1->y = mp_obj_new_int(blob1->rect.y);
o1->w = mp_obj_new_int(blob1->rect.w);
o1->h = mp_obj_new_int(blob1->rect.h);
o1->pixels = mp_obj_new_int(blob1->pixels);
o1->cx = mp_obj_new_int(blob1->centroid.x);
o1->cy = mp_obj_new_int(blob1->centroid.y);
o1->cx = mp_obj_new_float(blob1->centroid_x);
o1->cy = mp_obj_new_float(blob1->centroid_y);
o1->rotation = mp_obj_new_float(blob1->rotation);
o1->code = mp_obj_new_int(blob1->code);
o1->count = mp_obj_new_int(blob1->count);
o1->perimeter = mp_obj_new_int(blob1->perimeter);
o1->roundness = mp_obj_new_float(blob1->roundness);
o1->x_hist_bins = mp_obj_new_list(blob1->x_hist_bins_count, NULL);
o1->y_hist_bins = mp_obj_new_list(blob1->y_hist_bins_count, NULL);
for (int i = 0; i < blob1->x_hist_bins_count; i++) {
((mp_obj_list_t *) o1->x_hist_bins)->items[i] = mp_obj_new_int(blob1->x_hist_bins[i]);
}
for (int i = 0; i < blob1->y_hist_bins_count; i++) {
((mp_obj_list_t *) o1->y_hist_bins)->items[i] = mp_obj_new_int(blob1->y_hist_bins[i]);
}
return mp_obj_is_true(mp_call_function_2(fun_obj, o0, o1));
}
@ -3924,22 +4363,34 @@ static mp_obj_t py_image_find_blobs(uint n_args, const mp_obj_t *args, mp_map_t
rectangle_t roi;
py_helper_keyword_rectangle_roi(arg_img, n_args, args, 3, kw_args, &roi);
unsigned int x_stride = py_helper_keyword_int(n_args, args, 4, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_x_stride), 2);
unsigned int x_stride =
py_helper_keyword_int(n_args, args, 4, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_x_stride), 2);
PY_ASSERT_TRUE_MSG(x_stride > 0, "x_stride must not be zero.");
unsigned int y_stride = py_helper_keyword_int(n_args, args, 5, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_y_stride), 1);
unsigned int y_stride =
py_helper_keyword_int(n_args, args, 5, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_y_stride), 1);
PY_ASSERT_TRUE_MSG(y_stride > 0, "y_stride must not be zero.");
unsigned int area_threshold = py_helper_keyword_int(n_args, args, 6, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_area_threshold), 10);
unsigned int pixels_threshold = py_helper_keyword_int(n_args, args, 7, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_pixels_threshold), 10);
bool merge = py_helper_keyword_int(n_args, args, 8, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_merge), false);
int margin = py_helper_keyword_int(n_args, args, 9, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_margin), 0);
mp_obj_t threshold_cb = py_helper_keyword_object(n_args, args, 10, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_threshold_cb));
mp_obj_t merge_cb = py_helper_keyword_object(n_args, args, 11, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_merge_cb));
unsigned int area_threshold =
py_helper_keyword_int(n_args, args, 6, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_area_threshold), 10);
unsigned int pixels_threshold =
py_helper_keyword_int(n_args, args, 7, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_pixels_threshold), 10);
bool merge =
py_helper_keyword_int(n_args, args, 8, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_merge), false);
int margin =
py_helper_keyword_int(n_args, args, 9, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_margin), 0);
mp_obj_t threshold_cb =
py_helper_keyword_object(n_args, args, 10, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_threshold_cb));
mp_obj_t merge_cb =
py_helper_keyword_object(n_args, args, 11, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_merge_cb));
unsigned int x_hist_bins_max =
py_helper_keyword_int(n_args, args, 12, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_x_hist_bins_max), 0);
unsigned int y_hist_bins_max =
py_helper_keyword_int(n_args, args, 13, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_y_hist_bins_max), 0);
list_t out;
fb_alloc_mark();
imlib_find_blobs(&out, arg_img, &roi, x_stride, y_stride, &thresholds, invert,
area_threshold, pixels_threshold, merge, margin,
py_image_find_blobs_threshold_cb, threshold_cb, py_image_find_blobs_merge_cb, merge_cb);
py_image_find_blobs_threshold_cb, threshold_cb, py_image_find_blobs_merge_cb, merge_cb, x_hist_bins_max, y_hist_bins_max);
fb_alloc_free_till_mark();
list_free(&thresholds);
@ -3950,18 +4401,48 @@ static mp_obj_t py_image_find_blobs(uint n_args, const mp_obj_t *args, mp_map_t
py_blob_obj_t *o = m_new_obj(py_blob_obj_t);
o->base.type = &py_blob_type;
o->corners = mp_obj_new_tuple(4, (mp_obj_t [])
{mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(lnk_data.corners[(FIND_BLOBS_CORNERS_RESOLUTION*0)/4].x),
mp_obj_new_int(lnk_data.corners[(FIND_BLOBS_CORNERS_RESOLUTION*0)/4].y)}),
mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(lnk_data.corners[(FIND_BLOBS_CORNERS_RESOLUTION*1)/4].x),
mp_obj_new_int(lnk_data.corners[(FIND_BLOBS_CORNERS_RESOLUTION*1)/4].y)}),
mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(lnk_data.corners[(FIND_BLOBS_CORNERS_RESOLUTION*2)/4].x),
mp_obj_new_int(lnk_data.corners[(FIND_BLOBS_CORNERS_RESOLUTION*2)/4].y)}),
mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(lnk_data.corners[(FIND_BLOBS_CORNERS_RESOLUTION*3)/4].x),
mp_obj_new_int(lnk_data.corners[(FIND_BLOBS_CORNERS_RESOLUTION*3)/4].y)})});
point_t min_corners[4];
point_min_area_rectangle(lnk_data.corners, min_corners, FIND_BLOBS_CORNERS_RESOLUTION);
o->min_corners = mp_obj_new_tuple(4, (mp_obj_t [])
{mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(min_corners[0].x), mp_obj_new_int(min_corners[0].y)}),
mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(min_corners[1].x), mp_obj_new_int(min_corners[1].y)}),
mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(min_corners[2].x), mp_obj_new_int(min_corners[2].y)}),
mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(min_corners[3].x), mp_obj_new_int(min_corners[3].y)})});
o->x = mp_obj_new_int(lnk_data.rect.x);
o->y = mp_obj_new_int(lnk_data.rect.y);
o->w = mp_obj_new_int(lnk_data.rect.w);
o->h = mp_obj_new_int(lnk_data.rect.h);
o->pixels = mp_obj_new_int(lnk_data.pixels);
o->cx = mp_obj_new_int(lnk_data.centroid.x);
o->cy = mp_obj_new_int(lnk_data.centroid.y);
o->cx = mp_obj_new_float(lnk_data.centroid_x);
o->cy = mp_obj_new_float(lnk_data.centroid_y);
o->rotation = mp_obj_new_float(lnk_data.rotation);
o->code = mp_obj_new_int(lnk_data.code);
o->count = mp_obj_new_int(lnk_data.count);
o->perimeter = mp_obj_new_int(lnk_data.perimeter);
o->roundness = mp_obj_new_float(lnk_data.roundness);
o->x_hist_bins = mp_obj_new_list(lnk_data.x_hist_bins_count, NULL);
o->y_hist_bins = mp_obj_new_list(lnk_data.y_hist_bins_count, NULL);
for (int i = 0; i < lnk_data.x_hist_bins_count; i++) {
((mp_obj_list_t *) o->x_hist_bins)->items[i] = mp_obj_new_int(lnk_data.x_hist_bins[i]);
}
for (int i = 0; i < lnk_data.y_hist_bins_count; i++) {
((mp_obj_list_t *) o->y_hist_bins)->items[i] = mp_obj_new_int(lnk_data.y_hist_bins[i]);
}
objects_list->items[i] = o;
if (lnk_data.x_hist_bins) xfree(lnk_data.x_hist_bins);
if (lnk_data.y_hist_bins) xfree(lnk_data.y_hist_bins);
}
return objects_list;
@ -5117,6 +5598,7 @@ static mp_obj_t py_image_find_displacement(uint n_args, const mp_obj_t *args, mp
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_find_displacement_obj, 2, py_image_find_displacement);
#endif // IMLIB_ENABLE_FIND_DISPLACEMENT
#ifdef IMLIB_FIND_TEMPLATE
static mp_obj_t py_image_find_template(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
image_t *arg_img = py_helper_arg_to_image_grayscale(args[0]);
@ -5158,6 +5640,7 @@ static mp_obj_t py_image_find_template(uint n_args, const mp_obj_t *args, mp_map
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_find_template_obj, 3, py_image_find_template);
#endif // IMLIB_FIND_TEMPLATE
static mp_obj_t py_image_find_features(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
@ -5212,6 +5695,7 @@ static mp_obj_t py_image_find_eye(uint n_args, const mp_obj_t *args, mp_map_t *k
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_find_eye_obj, 2, py_image_find_eye);
#ifdef IMLIB_ENABLE_FIND_LBP
static mp_obj_t py_image_find_lbp(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
image_t *arg_img = py_helper_arg_to_image_grayscale(args[0]);
@ -5225,7 +5709,9 @@ static mp_obj_t py_image_find_lbp(uint n_args, const mp_obj_t *args, mp_map_t *k
return lbp_obj;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_find_lbp_obj, 2, py_image_find_lbp);
#endif // IMLIB_ENABLE_FIND_LBP
#ifdef IMLIB_ENABLE_FIND_KEYPOINTS
static mp_obj_t py_image_find_keypoints(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
image_t *arg_img = py_helper_arg_to_image_mutable(args[0]);
@ -5263,6 +5749,7 @@ static mp_obj_t py_image_find_keypoints(uint n_args, const mp_obj_t *args, mp_ma
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_find_keypoints_obj, 1, py_image_find_keypoints);
#endif // IMLIB_ENABLE_FIND_KEYPOINTS
#ifdef IMLIB_ENABLE_BINARY_OPS
static mp_obj_t py_image_find_edges(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
@ -5355,10 +5842,20 @@ static const mp_rom_map_elem_t locals_dict_table[] = {
{MP_ROM_QSTR(MP_QSTR_size), MP_ROM_PTR(&py_image_size_obj)},
{MP_ROM_QSTR(MP_QSTR_get_pixel), MP_ROM_PTR(&py_image_get_pixel_obj)},
{MP_ROM_QSTR(MP_QSTR_set_pixel), MP_ROM_PTR(&py_image_set_pixel_obj)},
#ifdef IMLIB_ENABLE_MEAN_POOLING
{MP_ROM_QSTR(MP_QSTR_mean_pool), MP_ROM_PTR(&py_image_mean_pool_obj)},
{MP_ROM_QSTR(MP_QSTR_mean_pooled), MP_ROM_PTR(&py_image_mean_pooled_obj)},
#else
{MP_ROM_QSTR(MP_QSTR_mean_pool), MP_ROM_PTR(&py_func_unavailable_obj)},
{MP_ROM_QSTR(MP_QSTR_mean_pooled), MP_ROM_PTR(&py_func_unavailable_obj)},
#endif
#ifdef IMLIB_ENABLE_MIDPOINT_POOLING
{MP_ROM_QSTR(MP_QSTR_midpoint_pool), MP_ROM_PTR(&py_image_midpoint_pool_obj)},
{MP_ROM_QSTR(MP_QSTR_midpoint_pooled), MP_ROM_PTR(&py_image_midpoint_pooled_obj)},
#else
{MP_ROM_QSTR(MP_QSTR_midpoint_pool), MP_ROM_PTR(&py_func_unavailable_obj)},
{MP_ROM_QSTR(MP_QSTR_midpoint_pooled), MP_ROM_PTR(&py_func_unavailable_obj)},
#endif
{MP_ROM_QSTR(MP_QSTR_to_bitmap), MP_ROM_PTR(&py_image_to_bitmap_obj)},
{MP_ROM_QSTR(MP_QSTR_to_grayscale), MP_ROM_PTR(&py_image_to_grayscale_obj)},
{MP_ROM_QSTR(MP_QSTR_to_rgb565), MP_ROM_PTR(&py_image_to_rgb565_obj)},
@ -5378,6 +5875,7 @@ static const mp_rom_map_elem_t locals_dict_table[] = {
{MP_ROM_QSTR(MP_QSTR_draw_string), MP_ROM_PTR(&py_image_draw_string_obj)},
{MP_ROM_QSTR(MP_QSTR_draw_cross), MP_ROM_PTR(&py_image_draw_cross_obj)},
{MP_ROM_QSTR(MP_QSTR_draw_arrow), MP_ROM_PTR(&py_image_draw_arrow_obj)},
{MP_ROM_QSTR(MP_QSTR_draw_edges), MP_ROM_PTR(&py_image_draw_edges_obj)},
{MP_ROM_QSTR(MP_QSTR_draw_image), MP_ROM_PTR(&py_image_draw_image_obj)},
#ifdef IMLIB_ENABLE_FLOOD_FILL
{MP_ROM_QSTR(MP_QSTR_flood_fill), MP_ROM_PTR(&py_image_flood_fill_obj)},
@ -5602,11 +6100,23 @@ static const mp_rom_map_elem_t locals_dict_table[] = {
#else
{MP_ROM_QSTR(MP_QSTR_find_displacement), MP_ROM_PTR(&py_func_unavailable_obj)},
#endif
#ifdef IMLIB_FIND_TEMPLATE
{MP_ROM_QSTR(MP_QSTR_find_template), MP_ROM_PTR(&py_image_find_template_obj)},
#else
{MP_ROM_QSTR(MP_QSTR_find_template), MP_ROM_PTR(&py_func_unavailable_obj)},
#endif
{MP_ROM_QSTR(MP_QSTR_find_features), MP_ROM_PTR(&py_image_find_features_obj)},
{MP_ROM_QSTR(MP_QSTR_find_eye), MP_ROM_PTR(&py_image_find_eye_obj)},
#ifdef IMLIB_ENABLE_FIND_LBP
{MP_ROM_QSTR(MP_QSTR_find_lbp), MP_ROM_PTR(&py_image_find_lbp_obj)},
#else
{MP_ROM_QSTR(MP_QSTR_find_lbp), MP_ROM_PTR(&py_func_unavailable_obj)},
#endif
#ifdef IMLIB_ENABLE_FIND_KEYPOINTS
{MP_ROM_QSTR(MP_QSTR_find_keypoints), MP_ROM_PTR(&py_image_find_keypoints_obj)},
#else
{MP_ROM_QSTR(MP_QSTR_find_keypoints), MP_ROM_PTR(&py_func_unavailable_obj)},
#endif
#ifdef IMLIB_ENABLE_BINARY_OPS
{MP_ROM_QSTR(MP_QSTR_find_edges), MP_ROM_PTR(&py_image_find_edges_obj)},
#else
@ -5976,6 +6486,7 @@ mp_obj_t py_image_load_cascade(uint n_args, const mp_obj_t *args, mp_map_t *kw_a
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_load_cascade_obj, 1, py_image_load_cascade);
#ifdef IMLIB_ENABLE_DESCRIPTOR
mp_obj_t py_image_load_descriptor(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
FIL fp;
@ -6169,6 +6680,7 @@ static mp_obj_t py_image_match_descriptor(uint n_args, const mp_obj_t *args, mp_
return match_obj;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_match_descriptor_obj, 2, py_image_match_descriptor);
#endif // IMLIB_ENABLE_DESCRIPTOR
int py_image_descriptor_from_roi(image_t *img, const char *path, rectangle_t *roi)
{
@ -6194,8 +6706,10 @@ int py_image_descriptor_from_roi(image_t *img, const char *path, rectangle_t *ro
static const mp_rom_map_elem_t globals_dict_table[] = {
{MP_ROM_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_image)},
#ifdef IMLIB_FIND_TEMPLATE
{MP_ROM_QSTR(MP_QSTR_SEARCH_EX), MP_ROM_INT(SEARCH_EX)},
{MP_ROM_QSTR(MP_QSTR_SEARCH_DS), MP_ROM_INT(SEARCH_DS)},
#endif
{MP_ROM_QSTR(MP_QSTR_EDGE_CANNY), MP_ROM_INT(EDGE_CANNY)},
{MP_ROM_QSTR(MP_QSTR_EDGE_SIMPLE), MP_ROM_INT(EDGE_SIMPLE)},
{MP_ROM_QSTR(MP_QSTR_CORNER_FAST), MP_ROM_INT(CORNER_FAST)},
@ -6234,9 +6748,15 @@ static const mp_rom_map_elem_t globals_dict_table[] = {
{MP_ROM_QSTR(MP_QSTR_grayscale_to_rgb), MP_ROM_PTR(&py_image_grayscale_to_rgb_obj)},
{MP_ROM_QSTR(MP_QSTR_Image), MP_ROM_PTR(&py_image_load_image_obj)},
{MP_ROM_QSTR(MP_QSTR_HaarCascade), MP_ROM_PTR(&py_image_load_cascade_obj)},
#ifdef IMLIB_ENABLE_DESCRIPTOR
{MP_ROM_QSTR(MP_QSTR_load_descriptor), MP_ROM_PTR(&py_image_load_descriptor_obj)},
{MP_ROM_QSTR(MP_QSTR_save_descriptor), MP_ROM_PTR(&py_image_save_descriptor_obj)},
{MP_ROM_QSTR(MP_QSTR_match_descriptor), MP_ROM_PTR(&py_image_match_descriptor_obj)}
#else
{MP_ROM_QSTR(MP_QSTR_load_descriptor), MP_ROM_PTR(&py_func_unavailable_obj)},
{MP_ROM_QSTR(MP_QSTR_save_descriptor), MP_ROM_PTR(&py_func_unavailable_obj)},
{MP_ROM_QSTR(MP_QSTR_match_descriptor), MP_ROM_PTR(&py_func_unavailable_obj)}
#endif
};
STATIC MP_DEFINE_CONST_DICT(globals_dict, globals_dict_table);

View File

@ -428,6 +428,13 @@ Q(draw_arrow)
// duplicate Q(size)
// duplicate Q(thickness)
// Draw Edges
Q(draw_edges)
// duplicate Q(color)
// duplicate Q(size)
// duplicate Q(thickness)
// duplicate Q(fill)
// Draw Image
Q(draw_image)
Q(x_scale)
@ -811,8 +818,12 @@ Q(merge)
Q(margin)
Q(threshold_cb)
Q(merge_cb)
Q(x_hist_bins_max)
Q(y_hist_bins_max)
// Blob Object
Q(blob)
Q(corners)
Q(min_corners)
Q(rect)
Q(x)
Q(y)
@ -820,12 +831,29 @@ Q(w)
Q(h)
Q(pixels)
Q(cx)
Q(cxf)
Q(cy)
Q(cyf)
// duplicate Q(rotation)
Q(rotation_deg)
Q(rotation_rad)
Q(code)
Q(count)
Q(perimeter)
Q(roundness)
Q(elongation)
Q(area)
Q(density)
Q(extent)
Q(compactness)
Q(solidity)
Q(convexity)
Q(x_hist_bins)
Q(y_hist_bins)
Q(major_axis_line)
Q(minor_axis_line)
Q(enclosing_circle)
Q(enclosed_ellipse)
// Find Lines
Q(find_lines)
@ -868,7 +896,7 @@ Q(find_rects)
// duplicate Q(threshold)
// Rect Object
// duplicate Q(rect)
Q(corners)
// duplicate Q(corners)
// duplicate Q(rect)
// duplicate Q(x)
// duplicate Q(y)