mirror of
https://github.com/openmv/openmv.git
synced 2025-09-26 23:09:13 +08:00
parent
a3e502a3a6
commit
b47dbe2c15
35
scripts/examples/03-Drawing/ellipse_drawing.py
Normal file
35
scripts/examples/03-Drawing/ellipse_drawing.py
Normal file
@ -0,0 +1,35 @@
|
||||
# Ellipse Drawing
|
||||
#
|
||||
# This example shows off drawing ellipses on the OpenMV Cam.
|
||||
|
||||
import sensor, image, time, pyb
|
||||
|
||||
sensor.reset()
|
||||
sensor.set_pixformat(sensor.RGB565) # or GRAYSCALE...
|
||||
sensor.set_framesize(sensor.QVGA) # or QQVGA...
|
||||
sensor.skip_frames(time = 2000)
|
||||
clock = time.clock()
|
||||
|
||||
while(True):
|
||||
clock.tick()
|
||||
|
||||
img = sensor.snapshot()
|
||||
|
||||
for i in range(10):
|
||||
x = (pyb.rng() % (2*img.width())) - (img.width()//2)
|
||||
y = (pyb.rng() % (2*img.height())) - (img.height()//2)
|
||||
radius_x = pyb.rng() % (max(img.height(), img.width())//2)
|
||||
radius_y = pyb.rng() % (max(img.height(), img.width())//2)
|
||||
rot = pyb.rng() % 45 # Avoid large rotation angles with fill on...
|
||||
|
||||
r = (pyb.rng() % 127) + 128
|
||||
g = (pyb.rng() % 127) + 128
|
||||
b = (pyb.rng() % 127) + 128
|
||||
|
||||
# If the first argument is a scaler then this method expects
|
||||
# to see x, y, radius x, and radius y.
|
||||
# Otherwise, it expects a (x,y,radius_x,radius_y) tuple.
|
||||
img.draw_ellipse(x, y, radius_x, radius_y, \
|
||||
rotation = rot, color = (r, g, b), thickness = 2, fill = False)
|
||||
|
||||
print(clock.fps())
|
@ -14,12 +14,12 @@ while(True):
|
||||
clock.tick()
|
||||
|
||||
img = sensor.snapshot()
|
||||
w = img.width()
|
||||
h = img.height()
|
||||
# Draws an image in the frame buffer. In this case we're
|
||||
# drawing the image we're currently drawing which causes
|
||||
# graphical glitches but is cool. Pass an optional mask
|
||||
# image to control what pixels are drawn.
|
||||
img.draw_image(img, w//4, h//4, x_scale=0.5, y_scale=0.5)
|
||||
small_img = img.mean_pooled(4, 4) # Makes a copy.
|
||||
|
||||
x = (img.width()//2)-(small_img.width()//2)
|
||||
y = (img.height()//2)-(small_img.height()//2)
|
||||
# Draws an image in the frame buffer.Pass an optional
|
||||
# mask image to control what pixels are drawn.
|
||||
img.draw_image(small_img, x, y, x_scale=1, y_scale=1)
|
||||
|
||||
print(clock.fps())
|
||||
|
@ -31,7 +31,7 @@
|
||||
//#define IMLIB_ENABLE_MIDPOINT
|
||||
|
||||
// Enable Gaussian
|
||||
#define IMLIB_ENABLE_GAUSSIAN
|
||||
//#define IMLIB_ENABLE_GAUSSIAN
|
||||
|
||||
// Enable Laplacian
|
||||
//#define IMLIB_ENABLE_LAPLACIAN
|
||||
|
@ -170,6 +170,104 @@ void imlib_draw_circle(image_t *img, int cx, int cy, int r, int c, int thickness
|
||||
}
|
||||
}
|
||||
|
||||
// https://scratch.mit.edu/projects/50039326/
|
||||
static void scratch_draw_pixel(image_t *img, int x0, int y0, int dx, int dy, float shear_dx, float shear_dy, int r0, int r1, int c)
|
||||
{
|
||||
point_fill(img, x0 + dx, y0 + dy + fast_floorf((dx * shear_dy) / shear_dx), r0, r1, c);
|
||||
}
|
||||
|
||||
// https://scratch.mit.edu/projects/50039326/
|
||||
static void scratch_draw_line(image_t *img, int x0, int y0, int dx, int dy0, int dy1, float shear_dx, float shear_dy, int c)
|
||||
{
|
||||
imlib_draw_line(img, x0 + dx, y0 + dy0 + fast_floorf((dx * shear_dy) / shear_dx),
|
||||
x0 + dx, y0 + dy1 + fast_floorf((dx * shear_dy) / shear_dx), c, 1);
|
||||
}
|
||||
|
||||
// https://scratch.mit.edu/projects/50039326/
|
||||
static void scratch_draw_sheared_ellipse(image_t *img, int x0, int y0, int width, int height, bool filled, float shear_dx, float shear_dy, int c, int thickness)
|
||||
{
|
||||
int thickness0 = (thickness - 0) / 2;
|
||||
int thickness1 = (thickness - 1) / 2;
|
||||
if (((thickness > 0) || filled) && (shear_dx != 0)) {
|
||||
int a_squared = width * width;
|
||||
int four_a_squared = a_squared * 4;
|
||||
int b_squared = height * height;
|
||||
int four_b_squared = b_squared * 4;
|
||||
|
||||
int x = 0;
|
||||
int y = height;
|
||||
int sigma = (2 * b_squared) + (a_squared * (1 - (2 * height)));
|
||||
|
||||
while ((b_squared * x) <= (a_squared * y)) {
|
||||
if (filled) {
|
||||
scratch_draw_line(img, x0, y0, x, -y, y, shear_dx, shear_dy, c);
|
||||
scratch_draw_line(img, x0, y0, -x, -y, y, shear_dx, shear_dy, c);
|
||||
} else {
|
||||
scratch_draw_pixel(img, x0, y0, x, y, shear_dx, shear_dy, -thickness0, thickness1, c);
|
||||
scratch_draw_pixel(img, x0, y0, -x, y, shear_dx, shear_dy, -thickness0, thickness1, c);
|
||||
scratch_draw_pixel(img, x0, y0, x, -y, shear_dx, shear_dy, -thickness0, thickness1, c);
|
||||
scratch_draw_pixel(img, x0, y0, -x, -y, shear_dx, shear_dy, -thickness0, thickness1, c);
|
||||
}
|
||||
|
||||
if (sigma >= 0) {
|
||||
sigma += four_a_squared * (1 - y);
|
||||
y -= 1;
|
||||
}
|
||||
|
||||
sigma += b_squared * ((4 * x) + 6);
|
||||
x += 1;
|
||||
}
|
||||
|
||||
x = width;
|
||||
y = 0;
|
||||
sigma = (2 * a_squared) + (b_squared * (1 - (2 * width)));
|
||||
|
||||
while ((a_squared * y) <= (b_squared * x)) {
|
||||
if (filled) {
|
||||
scratch_draw_line(img, x0, y0, x, -y, y, shear_dx, shear_dy, c);
|
||||
scratch_draw_line(img, x0, y0, -x, -y, y, shear_dx, shear_dy, c);
|
||||
} else {
|
||||
scratch_draw_pixel(img, x0, y0, x, y, shear_dx, shear_dy, -thickness0, thickness1, c);
|
||||
scratch_draw_pixel(img, x0, y0, -x, y, shear_dx, shear_dy, -thickness0, thickness1, c);
|
||||
scratch_draw_pixel(img, x0, y0, x, -y, shear_dx, shear_dy, -thickness0, thickness1, c);
|
||||
scratch_draw_pixel(img, x0, y0, -x, -y, shear_dx, shear_dy, -thickness0, thickness1, c);
|
||||
}
|
||||
|
||||
if (sigma >= 0) {
|
||||
sigma += four_b_squared * (1 - x);
|
||||
x -= 1;
|
||||
}
|
||||
|
||||
sigma += a_squared * ((4 * y) + 6);
|
||||
y += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://scratch.mit.edu/projects/50039326/
|
||||
static void scratch_draw_rotated_ellipse(image_t *img, int x, int y, int x_axis, int y_axis, int rotation, bool filled, int c, int thickness)
|
||||
{
|
||||
if ((x_axis > 0) && (y_axis > 0)) {
|
||||
if ((x_axis == y_axis) || ((rotation % 180) == 0)) {
|
||||
scratch_draw_sheared_ellipse(img, x, y, x_axis / 2, y_axis / 2, filled, 1, 0, c, thickness);
|
||||
} else if ((rotation % 180) == 90) {
|
||||
scratch_draw_sheared_ellipse(img, x, y, y_axis / 2, x_axis / 2, filled, 1, 0, c, thickness);
|
||||
} else {
|
||||
float theta = fast_atanf(IM_DIV(y_axis, x_axis) * (-tanf(IM_DEG2RAD(rotation))));
|
||||
float shear_dx = (x_axis * cosf(theta) * cosf(IM_DEG2RAD(rotation))) - (y_axis * sinf(theta) * sinf(IM_DEG2RAD(rotation)));
|
||||
float shear_dy = (x_axis * cosf(theta) * sinf(IM_DEG2RAD(rotation))) + (y_axis * sinf(theta) * cosf(IM_DEG2RAD(rotation)));
|
||||
float shear_x_axis = fast_fabsf(shear_dx);
|
||||
float shear_y_axis = IM_DIV((y_axis * x_axis), shear_x_axis);
|
||||
scratch_draw_sheared_ellipse(img, x, y, fast_floorf(shear_x_axis / 2), fast_floorf(shear_y_axis / 2), filled, shear_dx, shear_dy, c, thickness);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void imlib_draw_ellipse(image_t *img, int cx, int cy, int rx, int ry, int rotation, int c, int thickness, bool fill)
|
||||
{
|
||||
scratch_draw_rotated_ellipse(img, cx, cy, rx * 2, ry * 2, rotation, fill, c, thickness);
|
||||
}
|
||||
|
||||
void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int c, int scale, int x_spacing, int y_spacing, bool mono_space)
|
||||
{
|
||||
const int anchor = x_off;
|
||||
@ -246,6 +344,63 @@ void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int
|
||||
}
|
||||
}
|
||||
|
||||
static int safe_map_pixel(image_t *dst, image_t *src, int pixel)
|
||||
{
|
||||
switch (dst->bpp) {
|
||||
case IMAGE_BPP_BINARY: {
|
||||
switch (src->bpp) {
|
||||
case IMAGE_BPP_BINARY: {
|
||||
return pixel;
|
||||
}
|
||||
case IMAGE_BPP_GRAYSCALE: {
|
||||
return COLOR_GRAYSCALE_TO_BINARY(pixel);
|
||||
}
|
||||
case IMAGE_BPP_RGB565: {
|
||||
return COLOR_RGB565_TO_BINARY(pixel);
|
||||
}
|
||||
default: {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
case IMAGE_BPP_GRAYSCALE: {
|
||||
switch (src->bpp) {
|
||||
case IMAGE_BPP_BINARY: {
|
||||
return COLOR_BINARY_TO_GRAYSCALE(pixel);
|
||||
}
|
||||
case IMAGE_BPP_GRAYSCALE: {
|
||||
return pixel;
|
||||
}
|
||||
case IMAGE_BPP_RGB565: {
|
||||
return COLOR_RGB565_TO_GRAYSCALE(pixel);
|
||||
}
|
||||
default: {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
case IMAGE_BPP_RGB565: {
|
||||
switch (src->bpp) {
|
||||
case IMAGE_BPP_BINARY: {
|
||||
return COLOR_BINARY_TO_RGB565(pixel);
|
||||
}
|
||||
case IMAGE_BPP_GRAYSCALE: {
|
||||
return COLOR_GRAYSCALE_TO_RGB565(pixel);
|
||||
}
|
||||
case IMAGE_BPP_RGB565: {
|
||||
return pixel;
|
||||
}
|
||||
default: {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
default: {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void imlib_draw_image(image_t *img, image_t *other, int x_off, int y_off, float x_scale, float y_scale, image_t *mask)
|
||||
{
|
||||
float over_xscale = IM_DIV(1.0, x_scale), over_yscale = IM_DIV(1.0f, y_scale);
|
||||
@ -256,8 +411,9 @@ void imlib_draw_image(image_t *img, image_t *other, int x_off, int y_off, float
|
||||
for (int x = 0, xx = fast_roundf(other->w * x_scale); x < xx; x++) {
|
||||
int other_x = fast_roundf(x * over_xscale);
|
||||
|
||||
if (mask && (!image_get_mask_pixel(mask, other_x, other_y))) continue;
|
||||
imlib_set_pixel(img, x_off + x, y_off + y, imlib_get_pixel(other, other_x, other_y));
|
||||
if ((!mask) || image_get_mask_pixel(mask, other_x, other_y)) {
|
||||
imlib_set_pixel(img, x_off + x, y_off + y, safe_map_pixel(img, other, imlib_get_pixel(other, other_x, other_y)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1274,6 +1274,7 @@ void imlib_set_pixel(image_t *img, int x, int y, int p);
|
||||
void imlib_draw_line(image_t *img, int x0, int y0, int x1, int y1, int c, int thickness);
|
||||
void imlib_draw_rectangle(image_t *img, int rx, int ry, int rw, int rh, int c, int thickness, bool fill);
|
||||
void imlib_draw_circle(image_t *img, int cx, int cy, int r, int c, int thickness, bool fill);
|
||||
void imlib_draw_ellipse(image_t *img, int cx, int cy, int rx, int ry, int rotation, int c, int thickness, bool fill);
|
||||
void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int c, int scale, int x_spacing, int y_spacing, bool mono_space);
|
||||
void imlib_draw_image(image_t *img, image_t *other, int x_off, int y_off, float x_scale, float y_scale, image_t *mask);
|
||||
void imlib_flood_fill(image_t *img, int x, int y,
|
||||
|
@ -1309,6 +1309,31 @@ STATIC mp_obj_t py_image_draw_circle(uint n_args, const mp_obj_t *args, mp_map_t
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_draw_circle_obj, 2, py_image_draw_circle);
|
||||
|
||||
STATIC mp_obj_t py_image_draw_ellipse(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]);
|
||||
|
||||
const mp_obj_t *arg_vec;
|
||||
uint offset = py_helper_consume_array(n_args, args, 1, 4, &arg_vec);
|
||||
int arg_cx = mp_obj_get_int(arg_vec[0]);
|
||||
int arg_cy = mp_obj_get_int(arg_vec[1]);
|
||||
int arg_rx = mp_obj_get_int(arg_vec[2]);
|
||||
int arg_ry = mp_obj_get_int(arg_vec[3]);
|
||||
|
||||
int arg_rotation =
|
||||
py_helper_keyword_int(n_args, args, offset + 0, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_rotation), 0);
|
||||
int arg_c =
|
||||
py_helper_keyword_color(arg_img, n_args, args, offset + 1, kw_args, -1); // White.
|
||||
int arg_thickness =
|
||||
py_helper_keyword_int(n_args, args, offset + 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_thickness), 1);
|
||||
bool arg_fill =
|
||||
py_helper_keyword_int(n_args, args, offset + 3, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_fill), false);
|
||||
|
||||
imlib_draw_ellipse(arg_img, arg_cx, arg_cy, arg_rx, arg_ry, arg_rotation, arg_c, arg_thickness, arg_fill);
|
||||
return args[0];
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_draw_ellipse_obj, 2, py_image_draw_ellipse);
|
||||
|
||||
STATIC mp_obj_t py_image_draw_string(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]);
|
||||
@ -1403,7 +1428,7 @@ STATIC mp_obj_t py_image_draw_image(uint n_args, const mp_obj_t *args, mp_map_t
|
||||
image_t *arg_img = py_helper_arg_to_image_mutable(args[0]);
|
||||
|
||||
image_t *arg_other =
|
||||
py_helper_keyword_to_image_mutable_mask(n_args, args, 1, kw_args);
|
||||
py_helper_arg_to_image_mutable(args[1]);
|
||||
|
||||
const mp_obj_t *arg_vec;
|
||||
uint offset = py_helper_consume_array(n_args, args, 2, 2, &arg_vec);
|
||||
@ -5269,6 +5294,7 @@ static const mp_rom_map_elem_t locals_dict_table[] = {
|
||||
{MP_ROM_QSTR(MP_QSTR_draw_line), MP_ROM_PTR(&py_image_draw_line_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_draw_rectangle), MP_ROM_PTR(&py_image_draw_rectangle_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_draw_circle), MP_ROM_PTR(&py_image_draw_circle_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_draw_ellipse), MP_ROM_PTR(&py_image_draw_ellipse_obj)},
|
||||
{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)},
|
||||
|
@ -398,6 +398,13 @@ Q(draw_circle)
|
||||
// duplicate Q(thickness)
|
||||
// duplicate Q(fill)
|
||||
|
||||
// Draw Ellipse
|
||||
Q(draw_ellipse)
|
||||
Q(rotation)
|
||||
// duplicate Q(color)
|
||||
// duplicate Q(thickness)
|
||||
// duplicate Q(fill)
|
||||
|
||||
// Draw String
|
||||
Q(draw_string)
|
||||
// duplicate Q(color)
|
||||
@ -800,7 +807,7 @@ Q(h)
|
||||
Q(pixels)
|
||||
Q(cx)
|
||||
Q(cy)
|
||||
Q(rotation)
|
||||
// duplicate Q(rotation)
|
||||
Q(code)
|
||||
Q(count)
|
||||
Q(area)
|
||||
|
Loading…
Reference in New Issue
Block a user