mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
commit
a0d0949bbb
@ -9,16 +9,13 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <arm_math.h>
|
#include <arm_math.h>
|
||||||
#include <stm32f4xx.h>
|
|
||||||
#include <mp.h>
|
#include <mp.h>
|
||||||
#include "array.h"
|
|
||||||
#include "imlib.h"
|
|
||||||
#include "ff.h"
|
|
||||||
#include "ff_wrapper.h"
|
|
||||||
#include "mdefs.h"
|
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
|
#include "array.h"
|
||||||
|
#include "ff_wrapper.h"
|
||||||
#include "fb_alloc.h"
|
#include "fb_alloc.h"
|
||||||
#include "xalloc.h"
|
#include "xalloc.h"
|
||||||
|
#include "imlib.h"
|
||||||
|
|
||||||
// Gamma uncompress
|
// Gamma uncompress
|
||||||
extern const float xyz_table[256];
|
extern const float xyz_table[256];
|
||||||
@ -798,58 +795,67 @@ void imlib_blend(image_t *img, const char *path, image_t *other, int alpha)
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int imlib_image_mean(struct image *src)
|
void imlib_histeq(image_t *img)
|
||||||
|
{
|
||||||
|
if (IM_IS_GS(img)) {
|
||||||
|
int a = img->w * img->h;
|
||||||
|
float s = IM_MAX_GS / ((float)a);
|
||||||
|
uint32_t *hist = fb_alloc0(IM_G_HIST_SIZE * sizeof(uint32_t));
|
||||||
|
|
||||||
|
/* compute image histogram */
|
||||||
|
for (int i=0; i<a; i++) {
|
||||||
|
hist[img->pixels[i]] += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* compute the CDF */
|
||||||
|
for (int i=0, sum=0; i<IM_G_HIST_SIZE; i++) {
|
||||||
|
sum += hist[i];
|
||||||
|
hist[i] = sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=0; i<a; i++) {
|
||||||
|
img->pixels[i] = s * hist[img->pixels[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
fb_free();
|
||||||
|
} else {
|
||||||
|
// do nothing for now
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int imlib_image_mean(image_t *src)
|
||||||
{
|
{
|
||||||
int s=0;
|
int s=0;
|
||||||
int x,y;
|
int n=src->w*src->h;
|
||||||
int n = src->w*src->h;
|
|
||||||
|
|
||||||
for (y=0; y<src->h; y++) {
|
for (int i=0; i<n; i++) {
|
||||||
for (x=0; x<src->w; x++) {
|
s += src->pixels[i];
|
||||||
s += src->data[src->w*y+x];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* mean */
|
/* mean */
|
||||||
return s/n;
|
return s/n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void imlib_histeq(struct image *src)
|
// One pass standard deviation.
|
||||||
|
int imlib_image_std(image_t *src)
|
||||||
{
|
{
|
||||||
int i, sum;
|
int w=src->w;
|
||||||
int a = src->w*src->h;
|
int h=src->h;
|
||||||
uint32_t hist[IM_MAX_GS+1]={0};
|
int n=w*h;
|
||||||
|
uint8_t *data=src->pixels;
|
||||||
/* compute image histogram */
|
|
||||||
for (i=0; i<a; i++) {
|
|
||||||
hist[src->pixels[i]]+=1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* compute the CDF */
|
|
||||||
for (i=0, sum=0; i<IM_MAX_GS+1; i++) {
|
|
||||||
sum += hist[i];
|
|
||||||
hist[i] = sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<a; i++) {
|
|
||||||
src->pixels[i] = (uint8_t) ((IM_MAX_GS/(float)a) * hist[src->pixels[i]]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// One pass standard deviation
|
|
||||||
int imlib_std(image_t *image)
|
|
||||||
{
|
|
||||||
int w=image->w;
|
|
||||||
int h=image->h;
|
|
||||||
int n = w*h;
|
|
||||||
uint8_t *data = image->pixels;
|
|
||||||
|
|
||||||
uint32_t s=0, sq=0;
|
uint32_t s=0, sq=0;
|
||||||
for (int i=0; i<n; i+=2) {
|
for (int i=0; i<n; i+=2) {
|
||||||
s += data[i+0] + data[i+1];
|
s += data[i+0]+data[i+1];
|
||||||
uint32_t v0 = __PKHBT(data[i+0],
|
uint32_t tmp = __PKHBT(data[i+0], data[i+1], 16);
|
||||||
data[i+1], 16);
|
sq = __SMLAD(tmp, tmp, sq);
|
||||||
sq = __SMLAD(v0, v0, sq);
|
}
|
||||||
|
|
||||||
|
if (n%2) {
|
||||||
|
s += data[n-1];
|
||||||
|
sq += data[n-1]*data[n-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* mean */
|
/* mean */
|
||||||
|
|||||||
@ -192,18 +192,15 @@ typedef struct rectangle {
|
|||||||
|
|
||||||
typedef struct simple_color {
|
typedef struct simple_color {
|
||||||
uint8_t G;
|
uint8_t G;
|
||||||
union
|
union {
|
||||||
{
|
|
||||||
int8_t L;
|
int8_t L;
|
||||||
uint8_t red; // RGB888 not RGB565
|
uint8_t red; // RGB888 not RGB565
|
||||||
};
|
};
|
||||||
union
|
union {
|
||||||
{
|
|
||||||
int8_t A;
|
int8_t A;
|
||||||
uint8_t green; // RGB888 not RGB565
|
uint8_t green; // RGB888 not RGB565
|
||||||
};
|
};
|
||||||
union
|
union {
|
||||||
{
|
|
||||||
int8_t B;
|
int8_t B;
|
||||||
uint8_t blue; // RGB888 not RGB565
|
uint8_t blue; // RGB888 not RGB565
|
||||||
};
|
};
|
||||||
@ -243,32 +240,6 @@ typedef struct color_blob { // organized this way to pack it...
|
|||||||
}
|
}
|
||||||
color_blob_t;
|
color_blob_t;
|
||||||
|
|
||||||
typedef struct color {
|
|
||||||
union {
|
|
||||||
uint8_t vec[3];
|
|
||||||
struct {
|
|
||||||
uint8_t r;
|
|
||||||
uint8_t g;
|
|
||||||
uint8_t b;
|
|
||||||
};
|
|
||||||
struct {
|
|
||||||
int h;
|
|
||||||
int s;
|
|
||||||
int v;
|
|
||||||
};
|
|
||||||
struct {
|
|
||||||
int8_t L;
|
|
||||||
int8_t A;
|
|
||||||
int8_t B;
|
|
||||||
};
|
|
||||||
struct {
|
|
||||||
float x;
|
|
||||||
float y;
|
|
||||||
float z;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
} color_t;
|
|
||||||
|
|
||||||
typedef struct image {
|
typedef struct image {
|
||||||
int w;
|
int w;
|
||||||
int h;
|
int h;
|
||||||
@ -338,12 +309,6 @@ typedef struct cascade {
|
|||||||
int8_t *rectangles_array; // Rectangles array.
|
int8_t *rectangles_array; // Rectangles array.
|
||||||
} cascade_t;
|
} cascade_t;
|
||||||
|
|
||||||
typedef enum interp {
|
|
||||||
INTERP_NEAREST,
|
|
||||||
INTERP_BILINEAR,
|
|
||||||
INTERP_BICUBIC
|
|
||||||
} interp_t;
|
|
||||||
|
|
||||||
typedef struct bmp_read_settings {
|
typedef struct bmp_read_settings {
|
||||||
int32_t bmp_w;
|
int32_t bmp_w;
|
||||||
int32_t bmp_h;
|
int32_t bmp_h;
|
||||||
@ -396,6 +361,7 @@ bool bmp_read_geometry(FIL *fp, image_t *img, const char *path, bmp_read_setting
|
|||||||
void bmp_read_pixels(FIL *fp, image_t *img, int line_start, int line_end, bmp_read_settings_t *rs);
|
void bmp_read_pixels(FIL *fp, image_t *img, int line_start, int line_end, bmp_read_settings_t *rs);
|
||||||
void bmp_read(image_t *img, const char *path);
|
void bmp_read(image_t *img, const char *path);
|
||||||
void bmp_write_subimg(image_t *img, const char *path, rectangle_t *r);
|
void bmp_write_subimg(image_t *img, const char *path, rectangle_t *r);
|
||||||
|
void jpeg_compress(image_t *src, image_t *dst, int quality);
|
||||||
void jpeg_read_geometry(FIL *fp, image_t *img, const char *path);
|
void jpeg_read_geometry(FIL *fp, image_t *img, const char *path);
|
||||||
void jpeg_read_pixels(FIL *fp, image_t *img);
|
void jpeg_read_pixels(FIL *fp, image_t *img);
|
||||||
void jpeg_read(image_t *img, const char *path);
|
void jpeg_read(image_t *img, const char *path);
|
||||||
@ -463,12 +429,15 @@ void imlib_morph(image_t *img, const int ksize, const int8_t *krn, const float m
|
|||||||
/* Image Statistics */
|
/* Image Statistics */
|
||||||
int32_t *imlib_histogram(image_t *img, rectangle_t *r);
|
int32_t *imlib_histogram(image_t *img, rectangle_t *r);
|
||||||
void imlib_statistics(image_t *img, rectangle_t *r, statistics_t *out);
|
void imlib_statistics(image_t *img, rectangle_t *r, statistics_t *out);
|
||||||
|
int imlib_image_mean(image_t *src); // grayscale only
|
||||||
|
int imlib_image_std(image_t *src); // grayscale only
|
||||||
|
|
||||||
/* Image Filtering */
|
/* Image Filtering */
|
||||||
void imlib_midpoint_filter(image_t *img, const int ksize, const int bias);
|
void imlib_midpoint_filter(image_t *img, const int ksize, const int bias);
|
||||||
void imlib_mean_filter(image_t *img, const int ksize);
|
void imlib_mean_filter(image_t *img, const int ksize);
|
||||||
void imlib_mode_filter(image_t *img, const int ksize);
|
void imlib_mode_filter(image_t *img, const int ksize);
|
||||||
void imlib_median_filter(image_t *img, const int ksize, const int percentile);
|
void imlib_median_filter(image_t *img, const int ksize, const int percentile);
|
||||||
|
void imlib_histeq(image_t *img);
|
||||||
|
|
||||||
/* Color Tracking */
|
/* Color Tracking */
|
||||||
array_t *imlib_find_blobs(image_t *img,
|
array_t *imlib_find_blobs(image_t *img,
|
||||||
@ -481,10 +450,6 @@ array_t *imlib_find_markers(array_t *blobs_list, int margin,
|
|||||||
/* Clustering functions */
|
/* Clustering functions */
|
||||||
array_t *cluster_kmeans(array_t *points, int k);
|
array_t *cluster_kmeans(array_t *points, int k);
|
||||||
|
|
||||||
/* Image filtering functions */
|
|
||||||
int imlib_image_mean(struct image *src);
|
|
||||||
void imlib_histeq(struct image *src);
|
|
||||||
|
|
||||||
/* Integral image functions */
|
/* Integral image functions */
|
||||||
void imlib_integral_image_alloc(struct integral_image *sum, int w, int h);
|
void imlib_integral_image_alloc(struct integral_image *sum, int w, int h);
|
||||||
void imlib_integral_image_free(struct integral_image *sum);
|
void imlib_integral_image_free(struct integral_image *sum);
|
||||||
@ -529,9 +494,6 @@ int imlib_lbp_desc_load(FIL *fp, uint8_t **desc);
|
|||||||
/* Iris detector */
|
/* Iris detector */
|
||||||
void imlib_find_iris(image_t *src, point_t *iris, rectangle_t *roi);
|
void imlib_find_iris(image_t *src, point_t *iris, rectangle_t *roi);
|
||||||
|
|
||||||
/* Misc */
|
|
||||||
void jpeg_compress(image_t *src, image_t *dst, int quality);
|
|
||||||
|
|
||||||
// Image filter functions
|
// Image filter functions
|
||||||
void im_filter_bw(uint8_t *src, uint8_t *dst, int size, int bpp, void *args);
|
void im_filter_bw(uint8_t *src, uint8_t *dst, int size, int bpp, void *args);
|
||||||
void im_filter_skin(uint8_t *src, uint8_t *dst, int size, int bpp, void *args);
|
void im_filter_skin(uint8_t *src, uint8_t *dst, int size, int bpp, void *args);
|
||||||
|
|||||||
@ -1,5 +1,11 @@
|
|||||||
#include "mp.h"
|
/*
|
||||||
#include "imlib.h"
|
* This file is part of the OpenMV project.
|
||||||
|
* Copyright (c) 2013/2014 Ibrahim Abdelkader <i.abdalkader@gmail.com>
|
||||||
|
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||||
|
*
|
||||||
|
* MicroPython helper functions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
#include "py_helper.h"
|
#include "py_helper.h"
|
||||||
|
|
||||||
int py_helper_lookup_int(mp_map_t *kw_args, mp_obj_t kw, int default_val)
|
int py_helper_lookup_int(mp_map_t *kw_args, mp_obj_t kw, int default_val)
|
||||||
|
|||||||
@ -8,6 +8,8 @@
|
|||||||
*/
|
*/
|
||||||
#ifndef __PY_HELPER_H__
|
#ifndef __PY_HELPER_H__
|
||||||
#define __PY_HELPER_H__
|
#define __PY_HELPER_H__
|
||||||
|
#include <mp.h>
|
||||||
|
#include "imlib.h"
|
||||||
int py_helper_lookup_int(mp_map_t *kw_args, mp_obj_t kw, int default_val);
|
int py_helper_lookup_int(mp_map_t *kw_args, mp_obj_t kw, int default_val);
|
||||||
float py_helper_lookup_float(mp_map_t *kw_args, mp_obj_t kw, float default_val);
|
float py_helper_lookup_float(mp_map_t *kw_args, mp_obj_t kw, float default_val);
|
||||||
int py_helper_lookup_color(mp_map_t *kw_args, int default_color);
|
int py_helper_lookup_color(mp_map_t *kw_args, int default_color);
|
||||||
|
|||||||
@ -6,27 +6,26 @@
|
|||||||
* Image Python module.
|
* Image Python module.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include "mp.h"
|
#include <arm_math.h>
|
||||||
|
#include <mp.h>
|
||||||
#include "imlib.h"
|
#include "imlib.h"
|
||||||
#include "array.h"
|
#include "array.h"
|
||||||
#include "sensor.h"
|
#include "sensor.h"
|
||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
#include "xalloc.h"
|
#include "xalloc.h"
|
||||||
#include "fb_alloc.h"
|
#include "fb_alloc.h"
|
||||||
#include "arm_math.h"
|
#include "framebuffer.h"
|
||||||
#include "py_assert.h"
|
#include "py_assert.h"
|
||||||
#include "py_helper.h"
|
#include "py_helper.h"
|
||||||
#include "py_image.h"
|
#include "py_image.h"
|
||||||
#include "omv_boardconfig.h"
|
|
||||||
#include "framebuffer.h"
|
|
||||||
|
|
||||||
extern sensor_t sensor;
|
|
||||||
static const mp_obj_type_t py_cascade_type;
|
static const mp_obj_type_t py_cascade_type;
|
||||||
static const mp_obj_type_t py_image_type;
|
static const mp_obj_type_t py_image_type;
|
||||||
|
|
||||||
extern const char *ffs_strerror(FRESULT res);
|
extern const char *ffs_strerror(FRESULT res);
|
||||||
|
|
||||||
/* Haar Cascade */
|
// Haar Cascade ///////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
typedef struct _py_cascade_obj_t {
|
typedef struct _py_cascade_obj_t {
|
||||||
mp_obj_base_t base;
|
mp_obj_base_t base;
|
||||||
struct cascade _cobj;
|
struct cascade _cobj;
|
||||||
@ -41,9 +40,9 @@ void *py_cascade_cobj(mp_obj_t cascade)
|
|||||||
static void py_cascade_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind)
|
static void py_cascade_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind)
|
||||||
{
|
{
|
||||||
py_cascade_obj_t *self = self_in;
|
py_cascade_obj_t *self = self_in;
|
||||||
/* print some info */
|
mp_printf(print, "width:%d height:%d n_stages:%d n_features:%d n_rectangles:%d\n",
|
||||||
mp_printf(print, "width:%d height:%d n_stages:%d n_features:%d n_rectangles:%d\n", self->_cobj.window.w,
|
self->_cobj.window.w, self->_cobj.window.h, self->_cobj.n_stages,
|
||||||
self->_cobj.window.h, self->_cobj.n_stages, self->_cobj.n_features, self->_cobj.n_rectangles);
|
self->_cobj.n_features, self->_cobj.n_rectangles);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const mp_obj_type_t py_cascade_type = {
|
static const mp_obj_type_t py_cascade_type = {
|
||||||
@ -52,7 +51,8 @@ static const mp_obj_type_t py_cascade_type = {
|
|||||||
.print = py_cascade_print,
|
.print = py_cascade_print,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Keypoints object */
|
// Keypoints object ///////////////////////////////////////////////////////////
|
||||||
|
|
||||||
typedef struct _py_kp_obj_t {
|
typedef struct _py_kp_obj_t {
|
||||||
mp_obj_base_t base;
|
mp_obj_base_t base;
|
||||||
array_t *kpts;
|
array_t *kpts;
|
||||||
@ -72,7 +72,8 @@ static const mp_obj_type_t py_kp_type = {
|
|||||||
.print = py_kp_print,
|
.print = py_kp_print,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* LBP descriptor */
|
// LBP descriptor /////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
typedef struct _py_lbp_obj_t {
|
typedef struct _py_lbp_obj_t {
|
||||||
mp_obj_base_t base;
|
mp_obj_base_t base;
|
||||||
uint8_t *hist;
|
uint8_t *hist;
|
||||||
@ -89,16 +90,17 @@ static const mp_obj_type_t py_lbp_type = {
|
|||||||
.print = py_lbp_print,
|
.print = py_lbp_print,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Image */
|
// Image //////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
typedef struct _py_image_obj_t {
|
typedef struct _py_image_obj_t {
|
||||||
mp_obj_base_t base;
|
mp_obj_base_t base;
|
||||||
struct image _cobj;
|
image_t _cobj;
|
||||||
} py_image_obj_t;
|
} py_image_obj_t;
|
||||||
|
|
||||||
void *py_image_cobj(mp_obj_t image)
|
void *py_image_cobj(mp_obj_t img_obj)
|
||||||
{
|
{
|
||||||
PY_ASSERT_TYPE(image, &py_image_type);
|
PY_ASSERT_TYPE(img_obj, &py_image_type);
|
||||||
return &((py_image_obj_t *)image)->_cobj;
|
return &((py_image_obj_t *)img_obj)->_cobj;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void py_image_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind)
|
static void py_image_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind)
|
||||||
@ -107,20 +109,64 @@ static void py_image_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k
|
|||||||
mp_printf(print, "<image width:%d height:%d bpp:%d>", self->_cobj.w, self->_cobj.h, self->_cobj.bpp);
|
mp_printf(print, "<image width:%d height:%d bpp:%d>", self->_cobj.w, self->_cobj.h, self->_cobj.bpp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static mp_int_t py_image_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
|
static mp_obj_t py_image_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value)
|
||||||
image_t *image = py_image_cobj(self_in);
|
{
|
||||||
|
py_image_obj_t *o = self_in;
|
||||||
if (flags == MP_BUFFER_READ) {
|
image_t *arg_img = py_image_cobj(self_in);
|
||||||
bufinfo->buf = (void*)image->pixels;
|
if (value == MP_OBJ_NULL) {
|
||||||
if (image->bpp > 2) { //JPEG
|
// delete
|
||||||
bufinfo->len = image->bpp;
|
// not supported
|
||||||
|
return MP_OBJ_NULL;
|
||||||
|
} else if (value == MP_OBJ_SENTINEL) {
|
||||||
|
// load
|
||||||
|
if (IM_IS_GS(arg_img)) {
|
||||||
|
int i = mp_get_index(o->base.type, arg_img->w*arg_img->h, index, false);
|
||||||
|
int x = (i % arg_img->w);
|
||||||
|
int y = (i / arg_img->w);
|
||||||
|
return mp_obj_new_int(IM_GET_GS_PIXEL(arg_img, x, y));
|
||||||
|
} else if (IM_IS_RGB565(arg_img)) {
|
||||||
|
int i = mp_get_index(o->base.type, arg_img->w*arg_img->h, index, false);
|
||||||
|
int x = (i % arg_img->w);
|
||||||
|
int y = (i / arg_img->w);
|
||||||
|
return mp_obj_new_int(IM_GET_RGB565_PIXEL(arg_img, x, y));
|
||||||
} else {
|
} else {
|
||||||
bufinfo->len = image->w*image->h*image->bpp;
|
int i = mp_get_index(o->base.type, arg_img->bpp, index, false);
|
||||||
|
return mp_obj_new_int(arg_img->pixels[i]); // JPEG
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// store
|
||||||
|
if (IM_IS_GS(arg_img)) {
|
||||||
|
int i = mp_get_index(o->base.type, arg_img->w*arg_img->h, index, false);
|
||||||
|
int x = (i % arg_img->w);
|
||||||
|
int y = (i / arg_img->w);
|
||||||
|
IM_SET_GS_PIXEL(arg_img, x, y, mp_obj_get_int(value));
|
||||||
|
} else if (IM_IS_RGB565(arg_img)) {
|
||||||
|
int i = mp_get_index(o->base.type, arg_img->w*arg_img->h, index, false);
|
||||||
|
int x = (i % arg_img->w);
|
||||||
|
int y = (i / arg_img->w);
|
||||||
|
IM_SET_RGB565_PIXEL(arg_img, x, y, mp_obj_get_int(value));
|
||||||
|
} else {
|
||||||
|
int i = mp_get_index(o->base.type, arg_img->bpp, index, false);
|
||||||
|
arg_img->pixels[i] = mp_obj_get_int(value); // JPEG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mp_int_t py_image_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags)
|
||||||
|
{
|
||||||
|
image_t *arg_img = py_image_cobj(self_in);
|
||||||
|
if (flags == MP_BUFFER_READ) {
|
||||||
|
bufinfo->buf = arg_img->pixels;
|
||||||
|
if (IM_IS_JPEG(arg_img)) {
|
||||||
|
bufinfo->len = arg_img->bpp;
|
||||||
|
} else {
|
||||||
|
bufinfo->len = arg_img->w*arg_img->h*arg_img->bpp;
|
||||||
}
|
}
|
||||||
bufinfo->typecode = 'b';
|
bufinfo->typecode = 'b';
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
// disable write for now
|
// not supported
|
||||||
bufinfo->buf = NULL;
|
bufinfo->buf = NULL;
|
||||||
bufinfo->len = 0;
|
bufinfo->len = 0;
|
||||||
bufinfo->typecode = -1;
|
bufinfo->typecode = -1;
|
||||||
@ -128,34 +174,6 @@ static mp_int_t py_image_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static mp_obj_t py_image_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) {
|
|
||||||
py_image_obj_t *o = self_in;
|
|
||||||
image_t *image = py_image_cobj(self_in);
|
|
||||||
|
|
||||||
if (value == MP_OBJ_NULL) {
|
|
||||||
// delete
|
|
||||||
return MP_OBJ_NULL; // op not supported
|
|
||||||
} else if (value == MP_OBJ_SENTINEL) {
|
|
||||||
// load
|
|
||||||
mp_uint_t pixel;
|
|
||||||
mp_uint_t index = mp_get_index(o->base.type, image->w*image->h, index_in, false);
|
|
||||||
switch (image->bpp) {
|
|
||||||
case 1:
|
|
||||||
pixel = image->pixels[index];
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
pixel = image->pixels[index*2]<<8 | image->pixels[index*2+1];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return MP_OBJ_NULL; // op not supported
|
|
||||||
}
|
|
||||||
return mp_obj_new_int(pixel);
|
|
||||||
} else {
|
|
||||||
// store
|
|
||||||
return mp_const_none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static mp_obj_t py_image_copy(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
static mp_obj_t py_image_copy(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
||||||
{
|
{
|
||||||
image_t *arg_img = py_image_cobj(args[0]);
|
image_t *arg_img = py_image_cobj(args[0]);
|
||||||
@ -818,6 +836,16 @@ static mp_obj_t py_image_median(uint n_args, const mp_obj_t *args, mp_map_t *kw_
|
|||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static mp_obj_t py_image_histeq(mp_obj_t img_obj)
|
||||||
|
{
|
||||||
|
image_t *arg_img = py_image_cobj(img_obj);
|
||||||
|
PY_ASSERT_FALSE_MSG(IM_IS_JPEG(arg_img),
|
||||||
|
"Operation not supported on JPEG");
|
||||||
|
|
||||||
|
imlib_histeq(arg_img);
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
|
||||||
static bool py_image_find_blobs_f_fun(void *fun_obj, void *img_obj, color_blob_t *cb)
|
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_t blob_obj[10] = {
|
||||||
@ -844,7 +872,7 @@ static mp_obj_t py_image_find_blobs(uint n_args, const mp_obj_t *args, mp_map_t
|
|||||||
mp_uint_t arg_t_len;
|
mp_uint_t arg_t_len;
|
||||||
mp_obj_t *arg_t;
|
mp_obj_t *arg_t;
|
||||||
mp_obj_get_array(args[1], &arg_t_len, &arg_t);
|
mp_obj_get_array(args[1], &arg_t_len, &arg_t);
|
||||||
if (!arg_t_len) return mp_const_none;
|
if (!arg_t_len) return mp_obj_new_list(0, NULL); // return an empty array to be iteratable
|
||||||
|
|
||||||
simple_color_t l_t[arg_t_len], u_t[arg_t_len];
|
simple_color_t l_t[arg_t_len], u_t[arg_t_len];
|
||||||
if (IM_IS_GS(arg_img)) {
|
if (IM_IS_GS(arg_img)) {
|
||||||
@ -887,7 +915,7 @@ static mp_obj_t py_image_find_blobs(uint n_args, const mp_obj_t *args, mp_map_t
|
|||||||
array_t *blobs_list = imlib_find_blobs(arg_img, arg_t_len, l_t, u_t, arg_invert ? 1 : 0, &arg_r,
|
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]);
|
py_image_find_blobs_f_fun, kw_val, args[0]);
|
||||||
if (blobs_list == NULL) {
|
if (blobs_list == NULL) {
|
||||||
return mp_const_none;
|
return mp_obj_new_list(0, NULL); // return an empty array to be iteratable
|
||||||
}
|
}
|
||||||
mp_obj_t objects_list = mp_obj_new_list(0, NULL);
|
mp_obj_t objects_list = mp_obj_new_list(0, NULL);
|
||||||
for (int i=0, j=array_length(blobs_list); i<j; i++) {
|
for (int i=0, j=array_length(blobs_list); i<j; i++) {
|
||||||
@ -941,7 +969,7 @@ static mp_obj_t py_image_find_markers(uint n_args, const mp_obj_t *args, mp_map_
|
|||||||
mp_uint_t arg_t_len;
|
mp_uint_t arg_t_len;
|
||||||
mp_obj_t *arg_t;
|
mp_obj_t *arg_t;
|
||||||
mp_obj_get_array(args[1], &arg_t_len, &arg_t);
|
mp_obj_get_array(args[1], &arg_t_len, &arg_t);
|
||||||
if (!arg_t_len) return mp_const_none;
|
if (!arg_t_len) return mp_obj_new_list(0, NULL); // return an empty array to be iteratable
|
||||||
|
|
||||||
array_t *blobs_list;
|
array_t *blobs_list;
|
||||||
array_alloc_init(&blobs_list, xfree, arg_t_len);
|
array_alloc_init(&blobs_list, xfree, arg_t_len);
|
||||||
@ -964,7 +992,7 @@ static mp_obj_t py_image_find_markers(uint n_args, const mp_obj_t *args, mp_map_
|
|||||||
array_t *blobs_list_ret = imlib_find_markers(blobs_list, margin,
|
array_t *blobs_list_ret = imlib_find_markers(blobs_list, margin,
|
||||||
py_image_find_markers_f_fun, kw_val, args[0]);
|
py_image_find_markers_f_fun, kw_val, args[0]);
|
||||||
if (blobs_list_ret == NULL) {
|
if (blobs_list_ret == NULL) {
|
||||||
return mp_const_none;
|
return mp_obj_new_list(0, NULL); // return an empty array to be iteratable
|
||||||
}
|
}
|
||||||
array_free(blobs_list);
|
array_free(blobs_list);
|
||||||
mp_obj_t objects_list = mp_obj_new_list(0, NULL);
|
mp_obj_t objects_list = mp_obj_new_list(0, NULL);
|
||||||
@ -988,58 +1016,32 @@ static mp_obj_t py_image_find_markers(uint n_args, const mp_obj_t *args, mp_map_
|
|||||||
return objects_list;
|
return objects_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
static mp_obj_t py_image_histeq(mp_obj_t image_obj)
|
|
||||||
{
|
|
||||||
struct image *image;
|
|
||||||
/* get image pointer */
|
|
||||||
image = (struct image*) py_image_cobj(image_obj);
|
|
||||||
|
|
||||||
/* sanity checks */
|
|
||||||
PY_ASSERT_TRUE_MSG(image->bpp == 1,
|
|
||||||
"This function is only supported on GRAYSCALE images");
|
|
||||||
|
|
||||||
imlib_histeq(image);
|
|
||||||
return mp_const_none;
|
|
||||||
}
|
|
||||||
|
|
||||||
static mp_obj_t py_image_find_features(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
static mp_obj_t py_image_find_features(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
||||||
{
|
{
|
||||||
rectangle_t roi;
|
image_t *arg_img = py_image_cobj(args[0]);
|
||||||
image_t *image = NULL;
|
PY_ASSERT_TRUE_MSG(IM_IS_GS(arg_img),
|
||||||
cascade_t *cascade = NULL;
|
|
||||||
|
|
||||||
// Sanity checks
|
|
||||||
PY_ASSERT_TRUE_MSG(sensor.pixformat == PIXFORMAT_GRAYSCALE,
|
|
||||||
"This function is only supported on GRAYSCALE images");
|
"This function is only supported on GRAYSCALE images");
|
||||||
|
|
||||||
PY_ASSERT_TRUE_MSG(sensor.framesize <= OMV_MAX_INT_FRAME,
|
cascade_t *cascade = py_cascade_cobj(args[1]);
|
||||||
"This function is only supported on "OMV_MAX_INT_FRAME_STR" and smaller frames");
|
|
||||||
|
|
||||||
// Read positional arguments
|
|
||||||
image = py_image_cobj(args[0]);
|
|
||||||
cascade = py_cascade_cobj(args[1]);
|
|
||||||
|
|
||||||
// Read keyword arguments
|
|
||||||
py_helper_lookup_rectangle(kw_args, image, &roi);
|
|
||||||
cascade->threshold = py_helper_lookup_float(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_threshold), 0.5f);
|
cascade->threshold = py_helper_lookup_float(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_threshold), 0.5f);
|
||||||
cascade->scale_factor = py_helper_lookup_float(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_scale), 1.5f);
|
cascade->scale_factor = py_helper_lookup_float(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_scale), 1.5f);
|
||||||
|
|
||||||
// Make sure ROI is not negative
|
rectangle_t arg_r;
|
||||||
PY_ASSERT_FALSE_MSG((roi.x < 0) || (roi.y < 0) || (roi.w < 0) || (roi.h < 0),
|
py_helper_lookup_rectangle(kw_args, arg_img, &arg_r);
|
||||||
"Region of interest is negative!");
|
|
||||||
|
rectangle_t rect;
|
||||||
|
if (!rectangle_subimg(arg_img, &arg_r, &rect)) {
|
||||||
|
return mp_obj_new_list(0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure ROI is bigger than feature size
|
// Make sure ROI is bigger than feature size
|
||||||
PY_ASSERT_TRUE_MSG((roi.w > cascade->window.w && roi.h > cascade->window.h),
|
PY_ASSERT_TRUE_MSG((rect.w > cascade->window.w && rect.h > cascade->window.h),
|
||||||
"Region of interest is smaller than detector window!");
|
"Region of interest is smaller than detector window!");
|
||||||
|
|
||||||
// Make sure ROI is smaller than image size
|
|
||||||
PY_ASSERT_TRUE_MSG(((roi.x+roi.w) <= image->w && (roi.y+roi.h) <= image->h),
|
|
||||||
"Region of interest is bigger than frame size!");
|
|
||||||
|
|
||||||
// Detect objects
|
// Detect objects
|
||||||
array_t *objects_array = imlib_detect_objects(image, cascade, &roi);
|
array_t *objects_array = imlib_detect_objects(arg_img, cascade, &rect);
|
||||||
|
|
||||||
// Add detected objects to a new Python list
|
// Add detected objects to a new Python list...
|
||||||
mp_obj_t objects_list = mp_obj_new_list(0, NULL);
|
mp_obj_t objects_list = mp_obj_new_list(0, NULL);
|
||||||
for (int i=0; i<array_length(objects_array); i++) {
|
for (int i=0; i<array_length(objects_array); i++) {
|
||||||
rectangle_t *r = array_at(objects_array, i);
|
rectangle_t *r = array_at(objects_array, i);
|
||||||
@ -1051,70 +1053,111 @@ static mp_obj_t py_image_find_features(uint n_args, const mp_obj_t *args, mp_map
|
|||||||
};
|
};
|
||||||
mp_obj_list_append(objects_list, mp_obj_new_tuple(4, rec_obj));
|
mp_obj_list_append(objects_list, mp_obj_new_tuple(4, rec_obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free the objects array
|
|
||||||
array_free(objects_array);
|
array_free(objects_array);
|
||||||
|
|
||||||
return objects_list;
|
return objects_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
static mp_obj_t py_image_find_template(mp_obj_t image_obj, mp_obj_t template_obj, mp_obj_t threshold)
|
static mp_obj_t py_image_find_eye(mp_obj_t img_obj, mp_obj_t roi_obj)
|
||||||
{
|
{
|
||||||
struct rectangle r;
|
image_t *arg_img = py_image_cobj(img_obj);
|
||||||
struct image *image = NULL;
|
PY_ASSERT_TRUE_MSG(IM_IS_GS(arg_img),
|
||||||
struct image *template = NULL;
|
|
||||||
mp_obj_t rec_obj[4];
|
|
||||||
mp_obj_t obj=mp_const_none;
|
|
||||||
|
|
||||||
/* sanity checks */
|
|
||||||
PY_ASSERT_TRUE_MSG(sensor.pixformat == PIXFORMAT_GRAYSCALE,
|
|
||||||
"This function is only supported on GRAYSCALE images");
|
"This function is only supported on GRAYSCALE images");
|
||||||
|
|
||||||
PY_ASSERT_TRUE_MSG(sensor.framesize <= OMV_MAX_INT_FRAME,
|
mp_obj_t *array;
|
||||||
"This function is only supported on "OMV_MAX_INT_FRAME_STR" and smaller frames");
|
mp_obj_get_array_fixed_n(roi_obj, 4, &array);
|
||||||
|
|
||||||
|
rectangle_t arg_r = {
|
||||||
|
mp_obj_get_int(array[0]),
|
||||||
|
mp_obj_get_int(array[1]),
|
||||||
|
mp_obj_get_int(array[2]),
|
||||||
|
mp_obj_get_int(array[3]),
|
||||||
|
};
|
||||||
|
|
||||||
/* get C image pointer */
|
rectangle_t rect;
|
||||||
image = py_image_cobj(image_obj);
|
if (!rectangle_subimg(arg_img, &arg_r, &rect)) {
|
||||||
template= py_image_cobj(template_obj);
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
point_t iris;
|
||||||
|
imlib_find_iris(arg_img, &iris, &rect);
|
||||||
|
|
||||||
|
mp_obj_t eye_obj[2] = {
|
||||||
|
mp_obj_new_int(iris.x),
|
||||||
|
mp_obj_new_int(iris.y),
|
||||||
|
};
|
||||||
|
|
||||||
|
return mp_obj_new_tuple(2, eye_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static mp_obj_t py_image_find_template(mp_obj_t img_obj, mp_obj_t template_obj, mp_obj_t threshold)
|
||||||
|
{
|
||||||
|
image_t *arg_img = py_image_cobj(img_obj);
|
||||||
|
PY_ASSERT_TRUE_MSG(IM_IS_GS(arg_img),
|
||||||
|
"This function is only supported on GRAYSCALE images");
|
||||||
|
|
||||||
|
image_t *arg_template = py_image_cobj(template_obj);
|
||||||
|
PY_ASSERT_TRUE_MSG(IM_IS_GS(arg_template),
|
||||||
|
"This function is only supported on GRAYSCALE images");
|
||||||
|
|
||||||
float t = mp_obj_get_float(threshold);
|
float t = mp_obj_get_float(threshold);
|
||||||
|
|
||||||
/* look for object */
|
rectangle_t r;
|
||||||
float corr = imlib_template_match(image, template, &r);
|
float corr = imlib_template_match(arg_img, arg_template, &r);
|
||||||
//printf("t:%f coor:%f\n", (double)t, (double)corr);
|
|
||||||
if (corr > t) {
|
if (corr > t) {
|
||||||
rec_obj[0] = mp_obj_new_int(r.x);
|
mp_obj_t rec_obj[4] = {
|
||||||
rec_obj[1] = mp_obj_new_int(r.y);
|
mp_obj_new_int(r.x),
|
||||||
rec_obj[2] = mp_obj_new_int(r.w);
|
mp_obj_new_int(r.y),
|
||||||
rec_obj[3] = mp_obj_new_int(r.h);
|
mp_obj_new_int(r.w),
|
||||||
obj = mp_obj_new_tuple(4, rec_obj);
|
mp_obj_new_int(r.h)
|
||||||
|
};
|
||||||
|
return mp_obj_new_tuple(4, rec_obj);
|
||||||
}
|
}
|
||||||
return obj;
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mp_obj_t py_image_find_lbp(mp_obj_t img_obj, mp_obj_t roi_obj)
|
||||||
|
{
|
||||||
|
image_t *arg_img = py_image_cobj(img_obj);
|
||||||
|
PY_ASSERT_TRUE_MSG(IM_IS_GS(arg_img),
|
||||||
|
"This function is only supported on GRAYSCALE images");
|
||||||
|
|
||||||
|
mp_obj_t *array;
|
||||||
|
mp_obj_get_array_fixed_n(roi_obj, 4, &array);
|
||||||
|
|
||||||
|
rectangle_t roi = {
|
||||||
|
mp_obj_get_int(array[0]),
|
||||||
|
mp_obj_get_int(array[1]),
|
||||||
|
mp_obj_get_int(array[2]),
|
||||||
|
mp_obj_get_int(array[3]),
|
||||||
|
};
|
||||||
|
|
||||||
|
py_lbp_obj_t *lbp_obj = m_new_obj(py_lbp_obj_t);
|
||||||
|
lbp_obj->base.type = &py_lbp_type;
|
||||||
|
lbp_obj->hist = imlib_lbp_cascade(arg_img, &roi);
|
||||||
|
return lbp_obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
static mp_obj_t py_image_find_keypoints(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
static mp_obj_t py_image_find_keypoints(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
||||||
{
|
{
|
||||||
rectangle_t roi;
|
image_t *arg_img = py_image_cobj(args[0]);
|
||||||
image_t *image = py_image_cobj(args[0]);
|
PY_ASSERT_TRUE_MSG(IM_IS_GS(arg_img),
|
||||||
|
|
||||||
// Sanity checks
|
|
||||||
PY_ASSERT_TRUE_MSG(sensor.pixformat == PIXFORMAT_GRAYSCALE,
|
|
||||||
"This function is only supported on GRAYSCALE images");
|
"This function is only supported on GRAYSCALE images");
|
||||||
|
|
||||||
PY_ASSERT_TRUE_MSG(sensor.framesize <= OMV_MAX_INT_FRAME,
|
rectangle_t arg_r;
|
||||||
"This function is only supported on "OMV_MAX_INT_FRAME_STR" and smaller frames");
|
py_helper_lookup_rectangle(kw_args, arg_img, &arg_r);
|
||||||
|
|
||||||
|
rectangle_t rect;
|
||||||
|
if (!rectangle_subimg(arg_img, &arg_r, &rect)) {
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
|
||||||
// Read keyword arguments
|
|
||||||
py_helper_lookup_rectangle(kw_args, image, &roi);
|
|
||||||
int threshold = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_threshold), 32);
|
int threshold = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_threshold), 32);
|
||||||
bool normalized = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(qstr_from_str("normalized")), false);
|
bool normalized = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_normalized), false);
|
||||||
|
|
||||||
// Run keypoint descriptor on ROI
|
array_t *kpts = freak_find_keypoints(arg_img, normalized, threshold, &rect);
|
||||||
array_t *kpts= freak_find_keypoints(image, normalized, threshold, &roi);
|
|
||||||
|
|
||||||
if (array_length(kpts)) {
|
if (array_length(kpts)) {
|
||||||
// Return keypoints MP object
|
|
||||||
py_kp_obj_t *kp_obj = m_new_obj(py_kp_obj_t);
|
py_kp_obj_t *kp_obj = m_new_obj(py_kp_obj_t);
|
||||||
kp_obj->base.type = &py_kp_type;
|
kp_obj->base.type = &py_kp_type;
|
||||||
kp_obj->kpts = kpts;
|
kp_obj->kpts = kpts;
|
||||||
@ -1125,62 +1168,6 @@ static mp_obj_t py_image_find_keypoints(uint n_args, const mp_obj_t *args, mp_ma
|
|||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
static mp_obj_t py_image_find_lbp(mp_obj_t image_obj, mp_obj_t roi_obj)
|
|
||||||
{
|
|
||||||
image_t *image;
|
|
||||||
py_lbp_obj_t *lbp_obj;
|
|
||||||
|
|
||||||
image = py_image_cobj(image_obj);
|
|
||||||
/* sanity checks */
|
|
||||||
PY_ASSERT_TRUE_MSG(image->bpp == 1,
|
|
||||||
"This function is only supported on GRAYSCALE images");
|
|
||||||
|
|
||||||
mp_obj_t *array;
|
|
||||||
mp_obj_get_array_fixed_n(roi_obj, 4, &array);
|
|
||||||
|
|
||||||
rectangle_t roi = {
|
|
||||||
mp_obj_get_int(array[0]),
|
|
||||||
mp_obj_get_int(array[1]),
|
|
||||||
mp_obj_get_int(array[2]),
|
|
||||||
mp_obj_get_int(array[3]),
|
|
||||||
};
|
|
||||||
|
|
||||||
lbp_obj = m_new_obj(py_lbp_obj_t);
|
|
||||||
lbp_obj->base.type = &py_lbp_type;
|
|
||||||
lbp_obj->hist = imlib_lbp_cascade(image, &roi);
|
|
||||||
return lbp_obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
static mp_obj_t py_image_find_eyes(mp_obj_t image_obj, mp_obj_t roi_obj)
|
|
||||||
{
|
|
||||||
image_t *image;
|
|
||||||
|
|
||||||
image = py_image_cobj(image_obj);
|
|
||||||
/* sanity checks */
|
|
||||||
PY_ASSERT_TRUE_MSG(image->bpp == 1,
|
|
||||||
"This function is only supported on GRAYSCALE images");
|
|
||||||
|
|
||||||
mp_obj_t *array;
|
|
||||||
mp_obj_get_array_fixed_n(roi_obj, 4, &array);
|
|
||||||
|
|
||||||
rectangle_t roi = {
|
|
||||||
mp_obj_get_int(array[0]),
|
|
||||||
mp_obj_get_int(array[1]),
|
|
||||||
mp_obj_get_int(array[2]),
|
|
||||||
mp_obj_get_int(array[3]),
|
|
||||||
};
|
|
||||||
|
|
||||||
point_t iris;
|
|
||||||
imlib_find_iris(image, &iris, &roi);
|
|
||||||
|
|
||||||
mp_obj_t eyes_obj[2] = {
|
|
||||||
mp_obj_new_int(iris.x),
|
|
||||||
mp_obj_new_int(iris.y),
|
|
||||||
};
|
|
||||||
|
|
||||||
return mp_obj_new_tuple(2, eyes_obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Image file functions */
|
/* Image file functions */
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_copy_obj, 1, py_image_copy);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_copy_obj, 1, py_image_copy);
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_save_obj, 2, py_image_save);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_save_obj, 2, py_image_save);
|
||||||
@ -1225,17 +1212,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_midpoint_obj, 2, py_image_midpoint);
|
|||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_mean_obj, py_image_mean);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_mean_obj, py_image_mean);
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_mode_obj, py_image_mode);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_mode_obj, py_image_mode);
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_median_obj, 2, py_image_median);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_median_obj, 2, py_image_median);
|
||||||
|
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_histeq_obj, py_image_histeq);
|
||||||
/* Color Tracking */
|
/* Color Tracking */
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_find_blobs_obj, 2, py_image_find_blobs);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_find_blobs_obj, 2, py_image_find_blobs);
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_find_markers_obj, 2, py_image_find_markers);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_find_markers_obj, 2, py_image_find_markers);
|
||||||
|
/* Feature Detection */
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_histeq_obj, py_image_histeq);
|
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(py_image_find_template_obj, py_image_find_template);
|
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_find_features_obj, 2, py_image_find_features);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_find_features_obj, 2, py_image_find_features);
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_find_keypoints_obj, 1, py_image_find_keypoints);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_find_eye_obj, py_image_find_eye);
|
||||||
|
STATIC MP_DEFINE_CONST_FUN_OBJ_3(py_image_find_template_obj, py_image_find_template);
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_find_lbp_obj, py_image_find_lbp);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_find_lbp_obj, py_image_find_lbp);
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_find_eyes_obj, py_image_find_eyes);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_find_keypoints_obj, 1, py_image_find_keypoints);
|
||||||
|
|
||||||
static const mp_map_elem_t locals_dict_table[] = {
|
static const mp_map_elem_t locals_dict_table[] = {
|
||||||
/* Image file functions */
|
/* Image file functions */
|
||||||
{MP_OBJ_NEW_QSTR(MP_QSTR_copy), (mp_obj_t)&py_image_copy_obj},
|
{MP_OBJ_NEW_QSTR(MP_QSTR_copy), (mp_obj_t)&py_image_copy_obj},
|
||||||
@ -1281,26 +1267,23 @@ static const mp_map_elem_t locals_dict_table[] = {
|
|||||||
{MP_OBJ_NEW_QSTR(MP_QSTR_mean), (mp_obj_t)&py_image_mean_obj},
|
{MP_OBJ_NEW_QSTR(MP_QSTR_mean), (mp_obj_t)&py_image_mean_obj},
|
||||||
{MP_OBJ_NEW_QSTR(MP_QSTR_mode), (mp_obj_t)&py_image_mode_obj},
|
{MP_OBJ_NEW_QSTR(MP_QSTR_mode), (mp_obj_t)&py_image_mode_obj},
|
||||||
{MP_OBJ_NEW_QSTR(MP_QSTR_median), (mp_obj_t)&py_image_median_obj},
|
{MP_OBJ_NEW_QSTR(MP_QSTR_median), (mp_obj_t)&py_image_median_obj},
|
||||||
|
{MP_OBJ_NEW_QSTR(MP_QSTR_histeq), (mp_obj_t)&py_image_histeq_obj},
|
||||||
/* Color Tracking */
|
/* Color Tracking */
|
||||||
{MP_OBJ_NEW_QSTR(MP_QSTR_find_blobs), (mp_obj_t)&py_image_find_blobs_obj},
|
{MP_OBJ_NEW_QSTR(MP_QSTR_find_blobs), (mp_obj_t)&py_image_find_blobs_obj},
|
||||||
{MP_OBJ_NEW_QSTR(MP_QSTR_find_markers), (mp_obj_t)&py_image_find_markers_obj},
|
{MP_OBJ_NEW_QSTR(MP_QSTR_find_markers), (mp_obj_t)&py_image_find_markers_obj},
|
||||||
|
/* Feature Detection */
|
||||||
{MP_OBJ_NEW_QSTR(MP_QSTR_histeq), (mp_obj_t)&py_image_histeq_obj},
|
|
||||||
/* objects/feature detection */
|
|
||||||
{MP_OBJ_NEW_QSTR(MP_QSTR_find_template), (mp_obj_t)&py_image_find_template_obj},
|
|
||||||
{MP_OBJ_NEW_QSTR(MP_QSTR_find_features), (mp_obj_t)&py_image_find_features_obj},
|
{MP_OBJ_NEW_QSTR(MP_QSTR_find_features), (mp_obj_t)&py_image_find_features_obj},
|
||||||
{MP_OBJ_NEW_QSTR(MP_QSTR_find_keypoints), (mp_obj_t)&py_image_find_keypoints_obj},
|
{MP_OBJ_NEW_QSTR(MP_QSTR_find_eye), (mp_obj_t)&py_image_find_eye_obj},
|
||||||
|
{MP_OBJ_NEW_QSTR(MP_QSTR_find_template), (mp_obj_t)&py_image_find_template_obj},
|
||||||
{MP_OBJ_NEW_QSTR(MP_QSTR_find_lbp), (mp_obj_t)&py_image_find_lbp_obj},
|
{MP_OBJ_NEW_QSTR(MP_QSTR_find_lbp), (mp_obj_t)&py_image_find_lbp_obj},
|
||||||
{MP_OBJ_NEW_QSTR(MP_QSTR_find_eyes), (mp_obj_t)&py_image_find_eyes_obj},
|
{MP_OBJ_NEW_QSTR(MP_QSTR_find_keypoints), (mp_obj_t)&py_image_find_keypoints_obj},
|
||||||
|
|
||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
STATIC MP_DEFINE_CONST_DICT(locals_dict, locals_dict_table);
|
STATIC MP_DEFINE_CONST_DICT(locals_dict, locals_dict_table);
|
||||||
|
|
||||||
static const mp_obj_type_t py_image_type = {
|
static const mp_obj_type_t py_image_type = {
|
||||||
{ &mp_type_type },
|
{ &mp_type_type },
|
||||||
.name = MP_QSTR_image,
|
.name = MP_QSTR_Image,
|
||||||
.print = py_image_print,
|
.print = py_image_print,
|
||||||
.buffer_p = { .get_buffer = py_image_get_buffer },
|
.buffer_p = { .get_buffer = py_image_get_buffer },
|
||||||
.subscr = py_image_subscr,
|
.subscr = py_image_subscr,
|
||||||
@ -1311,45 +1294,21 @@ mp_obj_t py_image(int w, int h, int bpp, void *pixels)
|
|||||||
{
|
{
|
||||||
py_image_obj_t *o = m_new_obj(py_image_obj_t);
|
py_image_obj_t *o = m_new_obj(py_image_obj_t);
|
||||||
o->base.type = &py_image_type;
|
o->base.type = &py_image_type;
|
||||||
|
o->_cobj.w = w;
|
||||||
o->_cobj.w =w;
|
o->_cobj.h = h;
|
||||||
o->_cobj.h =h;
|
o->_cobj.bpp = bpp;
|
||||||
o->_cobj.bpp =bpp;
|
o->_cobj.pixels = pixels;
|
||||||
o->_cobj.pixels =pixels;
|
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_obj_t py_image_from_struct(image_t *image)
|
mp_obj_t py_image_from_struct(image_t *img)
|
||||||
{
|
{
|
||||||
py_image_obj_t *o = m_new_obj(py_image_obj_t);
|
py_image_obj_t *o = m_new_obj(py_image_obj_t);
|
||||||
o->base.type = &py_image_type;
|
o->base.type = &py_image_type;
|
||||||
o->_cobj =*image;
|
o->_cobj = *img;
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
int py_image_descriptor_from_roi(image_t *image, const char *path, rectangle_t *roi)
|
|
||||||
{
|
|
||||||
FIL fp;
|
|
||||||
FRESULT res = FR_OK;
|
|
||||||
|
|
||||||
array_t *kpts = freak_find_keypoints(image, false, 10, roi);
|
|
||||||
printf("Save Descriptor: KPTS(%d)\n", array_length(kpts));
|
|
||||||
printf("Save Descriptor: ROI(%d %d %d %d)\n", roi->x, roi->y, roi->w, roi->h);
|
|
||||||
|
|
||||||
if (array_length(kpts)) {
|
|
||||||
if ((res = f_open(&fp, path, FA_WRITE|FA_CREATE_ALWAYS)) == FR_OK) {
|
|
||||||
res = freak_save_descriptor(&fp, kpts);
|
|
||||||
f_close(&fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// File open/write error
|
|
||||||
if (res != FR_OK) {
|
|
||||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, ffs_strerror(res)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
mp_obj_t py_image_rgb_to_lab(mp_obj_t tuple)
|
mp_obj_t py_image_rgb_to_lab(mp_obj_t tuple)
|
||||||
{
|
{
|
||||||
mp_obj_t *rgb;
|
mp_obj_t *rgb;
|
||||||
@ -1410,19 +1369,10 @@ mp_obj_t py_image_grayscale_to_rgb(mp_obj_t not_tuple)
|
|||||||
mp_obj_new_int(rgb_color.blue)});
|
mp_obj_new_int(rgb_color.blue)});
|
||||||
}
|
}
|
||||||
|
|
||||||
// The image module (it's different from the Image class!)
|
|
||||||
mp_obj_t py_image_load_image(mp_obj_t path_obj)
|
mp_obj_t py_image_load_image(mp_obj_t path_obj)
|
||||||
{
|
{
|
||||||
mp_obj_t image_obj =NULL;
|
mp_obj_t image_obj = py_image(0, 0, 0, 0);
|
||||||
struct image *image;
|
imlib_load_image(py_image_cobj(image_obj), mp_obj_str_get_str(path_obj));
|
||||||
const char *path = mp_obj_str_get_str(path_obj);
|
|
||||||
image_obj = py_image(0, 0, 0, 0);
|
|
||||||
|
|
||||||
/* get image pointer */
|
|
||||||
image = py_image_cobj(image_obj);
|
|
||||||
|
|
||||||
imlib_load_image(image, path);
|
|
||||||
|
|
||||||
return image_obj;
|
return image_obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1595,21 +1545,41 @@ static mp_obj_t py_image_match_descriptor(uint n_args, const mp_obj_t *args, mp_
|
|||||||
return match_obj;
|
return match_obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int py_image_descriptor_from_roi(image_t *img, const char *path, rectangle_t *roi)
|
||||||
|
{
|
||||||
|
FIL fp;
|
||||||
|
FRESULT res = FR_OK;
|
||||||
|
|
||||||
|
printf("Save Descriptor: ROI(%d %d %d %d)\n", roi->x, roi->y, roi->w, roi->h);
|
||||||
|
array_t *kpts = freak_find_keypoints(img, false, 10, roi);
|
||||||
|
printf("Save Descriptor: KPTS(%d)\n", array_length(kpts));
|
||||||
|
|
||||||
|
if (array_length(kpts)) {
|
||||||
|
if ((res = f_open(&fp, path, FA_WRITE|FA_CREATE_ALWAYS)) == FR_OK) {
|
||||||
|
res = freak_save_descriptor(&fp, kpts);
|
||||||
|
f_close(&fp);
|
||||||
|
}
|
||||||
|
// File open/write error
|
||||||
|
if (res != FR_OK) {
|
||||||
|
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, ffs_strerror(res)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Color space functions */
|
/* Color space functions */
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_rgb_to_lab_obj, py_image_rgb_to_lab);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_rgb_to_lab_obj, py_image_rgb_to_lab);
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_lab_to_rgb_obj, py_image_lab_to_rgb);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_lab_to_rgb_obj, py_image_lab_to_rgb);
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_rgb_to_grayscale_obj, py_image_rgb_to_grayscale);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_rgb_to_grayscale_obj, py_image_rgb_to_grayscale);
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_grayscale_to_rgb_obj, py_image_grayscale_to_rgb);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_grayscale_to_rgb_obj, py_image_grayscale_to_rgb);
|
||||||
|
/* Image Module Functions */
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_load_image_obj, py_image_load_image);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_load_image_obj, py_image_load_image);
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_load_cascade_obj, 1, py_image_load_cascade);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_load_cascade_obj, 1, py_image_load_cascade);
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_load_descriptor_obj, 2, py_image_load_descriptor);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_load_descriptor_obj, 2, py_image_load_descriptor);
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_save_descriptor_obj, 3, py_image_save_descriptor);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_save_descriptor_obj, 3, py_image_save_descriptor);
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_match_descriptor_obj, 3, py_image_match_descriptor);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_match_descriptor_obj, 3, py_image_match_descriptor);
|
||||||
|
|
||||||
static const mp_map_elem_t globals_dict_table[] = {
|
static const mp_map_elem_t globals_dict_table[] = {
|
||||||
{MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_image)},
|
{MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_image)},
|
||||||
/* Descriptor types */
|
|
||||||
{MP_OBJ_NEW_QSTR(MP_QSTR_LBP), MP_OBJ_NEW_SMALL_INT(DESC_LBP)},
|
{MP_OBJ_NEW_QSTR(MP_QSTR_LBP), MP_OBJ_NEW_SMALL_INT(DESC_LBP)},
|
||||||
{MP_OBJ_NEW_QSTR(MP_QSTR_FREAK), MP_OBJ_NEW_SMALL_INT(DESC_FREAK)},
|
{MP_OBJ_NEW_QSTR(MP_QSTR_FREAK), MP_OBJ_NEW_SMALL_INT(DESC_FREAK)},
|
||||||
/* Color space functions */
|
/* Color space functions */
|
||||||
@ -1617,17 +1587,14 @@ static const mp_map_elem_t globals_dict_table[] = {
|
|||||||
{MP_OBJ_NEW_QSTR(MP_QSTR_lab_to_rgb), (mp_obj_t)&py_image_lab_to_rgb_obj},
|
{MP_OBJ_NEW_QSTR(MP_QSTR_lab_to_rgb), (mp_obj_t)&py_image_lab_to_rgb_obj},
|
||||||
{MP_OBJ_NEW_QSTR(MP_QSTR_rgb_to_grayscale), (mp_obj_t)&py_image_rgb_to_grayscale_obj},
|
{MP_OBJ_NEW_QSTR(MP_QSTR_rgb_to_grayscale), (mp_obj_t)&py_image_rgb_to_grayscale_obj},
|
||||||
{MP_OBJ_NEW_QSTR(MP_QSTR_grayscale_to_rgb), (mp_obj_t)&py_image_grayscale_to_rgb_obj},
|
{MP_OBJ_NEW_QSTR(MP_QSTR_grayscale_to_rgb), (mp_obj_t)&py_image_grayscale_to_rgb_obj},
|
||||||
|
/* Image Module Functions */
|
||||||
// Image module functions
|
|
||||||
{MP_OBJ_NEW_QSTR(MP_QSTR_Image), (mp_obj_t)&py_image_load_image_obj},
|
{MP_OBJ_NEW_QSTR(MP_QSTR_Image), (mp_obj_t)&py_image_load_image_obj},
|
||||||
{MP_OBJ_NEW_QSTR(MP_QSTR_HaarCascade), (mp_obj_t)&py_image_load_cascade_obj},
|
{MP_OBJ_NEW_QSTR(MP_QSTR_HaarCascade), (mp_obj_t)&py_image_load_cascade_obj},
|
||||||
{MP_OBJ_NEW_QSTR(MP_QSTR_load_descriptor), (mp_obj_t)&py_image_load_descriptor_obj},
|
{MP_OBJ_NEW_QSTR(MP_QSTR_load_descriptor), (mp_obj_t)&py_image_load_descriptor_obj},
|
||||||
{MP_OBJ_NEW_QSTR(MP_QSTR_save_descriptor), (mp_obj_t)&py_image_save_descriptor_obj},
|
{MP_OBJ_NEW_QSTR(MP_QSTR_save_descriptor), (mp_obj_t)&py_image_save_descriptor_obj},
|
||||||
{MP_OBJ_NEW_QSTR(MP_QSTR_match_descriptor), (mp_obj_t)&py_image_match_descriptor_obj},
|
{MP_OBJ_NEW_QSTR(MP_QSTR_match_descriptor), (mp_obj_t)&py_image_match_descriptor_obj},
|
||||||
|
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
STATIC MP_DEFINE_CONST_DICT(globals_dict, globals_dict_table);
|
STATIC MP_DEFINE_CONST_DICT(globals_dict, globals_dict_table);
|
||||||
|
|
||||||
const mp_obj_module_t image_module = {
|
const mp_obj_module_t image_module = {
|
||||||
|
|||||||
@ -8,10 +8,10 @@
|
|||||||
*/
|
*/
|
||||||
#ifndef __PY_IMAGE_H__
|
#ifndef __PY_IMAGE_H__
|
||||||
#define __PY_IMAGE_H__
|
#define __PY_IMAGE_H__
|
||||||
|
// DISABLED #include <mp.h>
|
||||||
#include "imlib.h"
|
#include "imlib.h"
|
||||||
mp_obj_t py_image(int width, int height, int bpp, void *pixels);
|
mp_obj_t py_image(int width, int height, int bpp, void *pixels);
|
||||||
mp_obj_t py_image_from_struct(image_t *image);
|
mp_obj_t py_image_from_struct(image_t *img);
|
||||||
void *py_image_cobj(mp_obj_t image);
|
void *py_image_cobj(mp_obj_t img_obj);
|
||||||
int py_image_descriptor_from_roi(image_t *image, const char *path, rectangle_t *roi);
|
int py_image_descriptor_from_roi(image_t *img, const char *path, rectangle_t *roi);
|
||||||
#endif // __PY_IMAGE_H__
|
#endif // __PY_IMAGE_H__
|
||||||
|
|
||||||
|
|||||||
@ -68,7 +68,7 @@ Q(find_template)
|
|||||||
Q(find_features)
|
Q(find_features)
|
||||||
Q(find_keypoints)
|
Q(find_keypoints)
|
||||||
Q(find_lbp)
|
Q(find_lbp)
|
||||||
Q(find_eyes)
|
Q(find_eye)
|
||||||
Q(cmp_lbp)
|
Q(cmp_lbp)
|
||||||
Q(quality)
|
Q(quality)
|
||||||
Q(color)
|
Q(color)
|
||||||
@ -80,6 +80,7 @@ Q(bias)
|
|||||||
Q(percentile)
|
Q(percentile)
|
||||||
Q(feature_filter)
|
Q(feature_filter)
|
||||||
Q(margin)
|
Q(margin)
|
||||||
|
Q(normalized)
|
||||||
|
|
||||||
// Lcd Module
|
// Lcd Module
|
||||||
Q(lcd)
|
Q(lcd)
|
||||||
|
|||||||
@ -42,7 +42,7 @@ while (True):
|
|||||||
# Note: Use a higher threshold here (more detections) and lower scale (to find small objects)
|
# Note: Use a higher threshold here (more detections) and lower scale (to find small objects)
|
||||||
eyes = img.find_features(eyes_cascade, threshold=0.5, scale=1.2, roi=face)
|
eyes = img.find_features(eyes_cascade, threshold=0.5, scale=1.2, roi=face)
|
||||||
for e in eyes:
|
for e in eyes:
|
||||||
iris = img.find_eyes(e)
|
iris = img.find_eye(e)
|
||||||
img.draw_rectangle(e)
|
img.draw_rectangle(e)
|
||||||
img.draw_cross(iris[0], iris[1])
|
img.draw_cross(iris[0], iris[1])
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user