mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Add support for loading haar cascade from file
This commit is contained in:
parent
156d194bf8
commit
492b1488e2
File diff suppressed because one or more lines are too long
174
src/imlib.c
174
src/imlib.c
@ -5,7 +5,7 @@
|
|||||||
#include <stm32f4xx.h>
|
#include <stm32f4xx.h>
|
||||||
#include "array.h"
|
#include "array.h"
|
||||||
#include "imlib.h"
|
#include "imlib.h"
|
||||||
#include "cascade.h"
|
#include "ff.h"
|
||||||
|
|
||||||
#define MIN(a,b) \
|
#define MIN(a,b) \
|
||||||
({ __typeof__ (a) _a = (a); \
|
({ __typeof__ (a) _a = (a); \
|
||||||
@ -270,47 +270,33 @@ void imlib_histeq(struct image *src)
|
|||||||
/* Viola-Jones face detector implementation
|
/* Viola-Jones face detector implementation
|
||||||
* Original Author: Francesco Comaschi (f.comaschi@tue.nl)
|
* Original Author: Francesco Comaschi (f.comaschi@tue.nl)
|
||||||
*/
|
*/
|
||||||
static int evalWeakClassifier(struct integral_image *sum, int std, int p_offset, int tree_index, int w_index, int r_index )
|
static int evalWeakClassifier(struct cascade *cascade, int std, int p_offset, int tree_index, int w_index, int r_index )
|
||||||
{
|
{
|
||||||
|
int i, sumw=0;
|
||||||
struct rectangle tr;
|
struct rectangle tr;
|
||||||
|
struct integral_image *sum = &cascade->sum;
|
||||||
/* the node threshold is multiplied by the standard deviation of the image */
|
/* the node threshold is multiplied by the standard deviation of the image */
|
||||||
int t = tree_thresh_array[tree_index] * std;
|
int t = cascade->tree_thresh_array[tree_index] * std;
|
||||||
|
|
||||||
/* this is just a hack will be removed when
|
for (i=0; i<cascade->num_rectangles_array[tree_index]; i++) {
|
||||||
we add the number of rects to the classifier */
|
tr.x = cascade->rectangles_array[r_index + i*4 + 0];
|
||||||
tr.x = rectangles_array[r_index + 8];
|
tr.y = cascade->rectangles_array[r_index + i*4 + 1];
|
||||||
tr.y = rectangles_array[r_index + 9];
|
tr.w = cascade->rectangles_array[r_index + i*4 + 2];
|
||||||
tr.w = rectangles_array[r_index + 10];
|
tr.h = cascade->rectangles_array[r_index + i*4 + 3];
|
||||||
tr.h = rectangles_array[r_index + 11];
|
|
||||||
|
|
||||||
int i,k, sumw=0;
|
|
||||||
|
|
||||||
if ((tr.x)&& (tr.y) &&(tr.w) &&(tr.h)) {
|
|
||||||
k = 3;
|
|
||||||
} else {
|
|
||||||
k = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<k; i++) {
|
|
||||||
tr.x = rectangles_array[r_index + i*4 + 0];
|
|
||||||
tr.y = rectangles_array[r_index + i*4 + 1];
|
|
||||||
tr.w = rectangles_array[r_index + i*4 + 2];
|
|
||||||
tr.h = rectangles_array[r_index + i*4 + 3];
|
|
||||||
|
|
||||||
sumw += (
|
sumw += (
|
||||||
*((sum->data + sum->w*(tr.y ) + (tr.x )) + p_offset)
|
*((sum->data + sum->w*(tr.y ) + (tr.x )) + p_offset)
|
||||||
- *((sum->data + sum->w*(tr.y ) + (tr.x + tr.w)) + p_offset)
|
- *((sum->data + sum->w*(tr.y ) + (tr.x + tr.w)) + p_offset)
|
||||||
- *((sum->data + sum->w*(tr.y + tr.h) + (tr.x )) + p_offset)
|
- *((sum->data + sum->w*(tr.y + tr.h) + (tr.x )) + p_offset)
|
||||||
+ *((sum->data + sum->w*(tr.y + tr.h) + (tr.x + tr.w)) + p_offset))
|
+ *((sum->data + sum->w*(tr.y + tr.h) + (tr.x + tr.w)) + p_offset))
|
||||||
* weights_array[w_index + i];
|
* cascade->weights_array[w_index + i]*4096;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sumw >= t) {
|
if (sumw >= t) {
|
||||||
return alpha2_array[tree_index];
|
return cascade->alpha2_array[tree_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
return alpha1_array[tree_index];
|
return cascade->alpha1_array[tree_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
static int runCascadeClassifier(struct cascade* cascade, struct point pt, int start_stage)
|
static int runCascadeClassifier(struct cascade* cascade, struct point pt, int start_stage)
|
||||||
@ -329,8 +315,8 @@ static int runCascadeClassifier(struct cascade* cascade, struct point pt, int st
|
|||||||
uint32_t sumsq=0;
|
uint32_t sumsq=0;
|
||||||
vec_t v0, v1;
|
vec_t v0, v1;
|
||||||
|
|
||||||
for (y=pt.y; y<24; y++) {
|
for (y=pt.y; y<cascade->window.w; y++) {
|
||||||
for (x=pt.x; x<24; x+=2) {
|
for (x=pt.x; x<cascade->window.w; x+=2) {
|
||||||
offset = y*cascade->img->w+x;
|
offset = y*cascade->img->w+x;
|
||||||
v0.s0 = cascade->img->pixels[offset+0];
|
v0.s0 = cascade->img->pixels[offset+0];
|
||||||
v0.s1 = cascade->img->pixels[offset+1];
|
v0.s1 = cascade->img->pixels[offset+1];
|
||||||
@ -356,13 +342,15 @@ static int runCascadeClassifier(struct cascade* cascade, struct point pt, int st
|
|||||||
|
|
||||||
for (i=start_stage; i<cascade->n_stages; i++) {
|
for (i=start_stage; i<cascade->n_stages; i++) {
|
||||||
stage_sum = 0;
|
stage_sum = 0;
|
||||||
for (j=0; j<stages_array[i]; j++, tree_index++, w_index+=3, r_index+=12) {
|
for (j=0; j<cascade->stages_array[i]; j++, tree_index++) {
|
||||||
/* send the shifted window to a haar filter */
|
/* send the shifted window to a haar filter */
|
||||||
stage_sum += evalWeakClassifier(&cascade->sum, std, p_offset, tree_index, w_index, r_index);
|
stage_sum += evalWeakClassifier(cascade, std, p_offset, tree_index, w_index, r_index);
|
||||||
|
w_index+=cascade->num_rectangles_array[tree_index];
|
||||||
|
r_index+=4 * cascade->num_rectangles_array[tree_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the sum is below the stage threshold, no faces are detected */
|
/* If the sum is below the stage threshold, no faces are detected */
|
||||||
if (stage_sum < 0.4*stages_thresh_array[i]) {
|
if (stage_sum < 0.4*cascade->stages_thresh_array[i]) {
|
||||||
return -i;
|
return -i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -549,10 +537,130 @@ struct array *imlib_detect_objects(struct image *image, struct cascade *cascade)
|
|||||||
|
|
||||||
/* process the current scale with the cascaded fitler. */
|
/* process the current scale with the cascaded fitler. */
|
||||||
ScaleImageInvoker(cascade, factor, sum.h, sum.w, objects);
|
ScaleImageInvoker(cascade, factor, sum.h, sum.w, objects);
|
||||||
}
|
}
|
||||||
|
|
||||||
//free(sum.data);
|
//free(sum.data);
|
||||||
|
|
||||||
objects = imlib_merge_detections(objects);
|
objects = imlib_merge_detections(objects);
|
||||||
return objects;
|
return objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int imlib_load_cascade(struct cascade* cascade, const char *path)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
UINT n_out;
|
||||||
|
|
||||||
|
FIL fp;
|
||||||
|
FRESULT res=FR_OK;
|
||||||
|
|
||||||
|
res = f_open(&fp, path, FA_READ|FA_OPEN_EXISTING);
|
||||||
|
if (res != FR_OK) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read detection window size */
|
||||||
|
res = f_read(&fp, &cascade->window, sizeof(cascade->window), &n_out);
|
||||||
|
if (res != FR_OK || n_out != sizeof(cascade->window)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read num stages */
|
||||||
|
res = f_read(&fp, &cascade->n_stages, sizeof(cascade->n_stages), &n_out);
|
||||||
|
if (res != FR_OK || n_out != sizeof(cascade->n_stages)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
cascade->stages_array = malloc (sizeof(*cascade->stages_array) * cascade->n_stages);
|
||||||
|
cascade->stages_thresh_array = malloc (sizeof(*cascade->stages_thresh_array) * cascade->n_stages);
|
||||||
|
|
||||||
|
if (cascade->stages_array == NULL ||
|
||||||
|
cascade->stages_thresh_array == NULL) {
|
||||||
|
res = 20;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read num features in each stages */
|
||||||
|
res = f_read(&fp, cascade->stages_array, sizeof(uint8_t) * cascade->n_stages, &n_out);
|
||||||
|
if (res != FR_OK || n_out != sizeof(uint8_t) * cascade->n_stages) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sum num of features in each stages*/
|
||||||
|
for (i=0, cascade->n_features=0; i<cascade->n_stages; i++) {
|
||||||
|
cascade->n_features += cascade->stages_array[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* alloc features thresh array, alpha1, alpha 2,rects weights and rects*/
|
||||||
|
cascade->tree_thresh_array = malloc (sizeof(*cascade->tree_thresh_array) * cascade->n_features);
|
||||||
|
cascade->alpha1_array = malloc (sizeof(*cascade->alpha1_array) * cascade->n_features);
|
||||||
|
cascade->alpha2_array = malloc (sizeof(*cascade->alpha2_array) * cascade->n_features);
|
||||||
|
cascade->num_rectangles_array = malloc (sizeof(*cascade->num_rectangles_array) * cascade->n_features);
|
||||||
|
|
||||||
|
if (cascade->tree_thresh_array == NULL ||
|
||||||
|
cascade->alpha1_array == NULL ||
|
||||||
|
cascade->alpha2_array == NULL ||
|
||||||
|
cascade->num_rectangles_array == NULL) {
|
||||||
|
res = 20;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read stages thresholds */
|
||||||
|
res = f_read(&fp, cascade->stages_thresh_array, sizeof(int16_t)*cascade->n_stages, &n_out);
|
||||||
|
if (res != FR_OK || n_out != sizeof(int16_t)*cascade->n_stages) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read features thresholds */
|
||||||
|
res = f_read(&fp, cascade->tree_thresh_array, sizeof(*cascade->tree_thresh_array)*cascade->n_features, &n_out);
|
||||||
|
if (res != FR_OK || n_out != sizeof(*cascade->tree_thresh_array)*cascade->n_features) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read alpha 1 */
|
||||||
|
res = f_read(&fp, cascade->alpha1_array, sizeof(*cascade->alpha1_array)*cascade->n_features, &n_out);
|
||||||
|
if (res != FR_OK || n_out != sizeof(*cascade->alpha1_array)*cascade->n_features) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read alpha 2 */
|
||||||
|
res = f_read(&fp, cascade->alpha2_array, sizeof(*cascade->alpha2_array)*cascade->n_features, &n_out);
|
||||||
|
if (res != FR_OK || n_out != sizeof(*cascade->alpha2_array)*cascade->n_features) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read num rectangles per feature*/
|
||||||
|
res = f_read(&fp, cascade->num_rectangles_array, sizeof(*cascade->num_rectangles_array)*cascade->n_features, &n_out);
|
||||||
|
if (res != FR_OK || n_out != sizeof(*cascade->num_rectangles_array)*cascade->n_features) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sum num of recatngles per feature*/
|
||||||
|
for (i=0, cascade->n_rectangles=0; i<cascade->n_features; i++) {
|
||||||
|
cascade->n_rectangles += cascade->num_rectangles_array[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
cascade->weights_array = malloc (sizeof(*cascade->weights_array) * cascade->n_rectangles);
|
||||||
|
cascade->rectangles_array = malloc (sizeof(*cascade->rectangles_array) * cascade->n_rectangles * 4);
|
||||||
|
|
||||||
|
if (cascade->weights_array == NULL ||
|
||||||
|
cascade->rectangles_array == NULL) {
|
||||||
|
res = 20;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read rectangles weights */
|
||||||
|
res =f_read(&fp, cascade->weights_array, sizeof(*cascade->weights_array)*cascade->n_rectangles, &n_out);
|
||||||
|
if (res != FR_OK || n_out != sizeof(*cascade->weights_array)*cascade->n_rectangles) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read rectangles num rectangles * 4 points */
|
||||||
|
res = f_read(&fp, cascade->rectangles_array, sizeof(*cascade->rectangles_array)*cascade->n_rectangles *4, &n_out);
|
||||||
|
if (res != FR_OK || n_out != sizeof(*cascade->rectangles_array)*cascade->n_rectangles *4) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
f_close(&fp);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|||||||
18
src/imlib.h
18
src/imlib.h
@ -72,12 +72,25 @@ struct cascade {
|
|||||||
float scale_factor;
|
float scale_factor;
|
||||||
/* number of stages in the cascade */
|
/* number of stages in the cascade */
|
||||||
int n_stages;
|
int n_stages;
|
||||||
|
/* number of features in the cascade */
|
||||||
|
int n_features;
|
||||||
|
/* number of rectangles in the cascade */
|
||||||
|
int n_rectangles;
|
||||||
/* size of the window used in the training set */
|
/* size of the window used in the training set */
|
||||||
struct size window;
|
struct size window;
|
||||||
/* pointer to current integral image */
|
|
||||||
struct integral_image sum;
|
|
||||||
/* pointer to current scaled image in the pyramid */
|
/* pointer to current scaled image in the pyramid */
|
||||||
struct image *img;
|
struct image *img;
|
||||||
|
/* pointer to current integral image */
|
||||||
|
struct integral_image sum;
|
||||||
|
/* haar cascade arrays */
|
||||||
|
uint8_t *stages_array;
|
||||||
|
int16_t *stages_thresh_array;
|
||||||
|
int16_t *tree_thresh_array;
|
||||||
|
int16_t *alpha1_array;
|
||||||
|
int16_t *alpha2_array;
|
||||||
|
int8_t *num_rectangles_array;
|
||||||
|
int8_t *weights_array;
|
||||||
|
int8_t *rectangles_array;
|
||||||
};
|
};
|
||||||
|
|
||||||
float imlib_distance(struct color *c0, struct color *c1);
|
float imlib_distance(struct color *c0, struct color *c1);
|
||||||
@ -90,4 +103,5 @@ void imlib_integral_image(struct image *src, struct integral_image *sum);
|
|||||||
void imlib_draw_rectangle(struct image *image, struct rectangle *r);
|
void imlib_draw_rectangle(struct image *image, struct rectangle *r);
|
||||||
void imlib_histeq(struct image *src);
|
void imlib_histeq(struct image *src);
|
||||||
struct array *imlib_detect_objects(struct image *image, struct cascade* cascade);
|
struct array *imlib_detect_objects(struct image *image, struct cascade* cascade);
|
||||||
|
int imlib_load_cascade(struct cascade* cascade, const char *path);
|
||||||
#endif //__IMLIB_H__
|
#endif //__IMLIB_H__
|
||||||
|
|||||||
@ -5,9 +5,40 @@
|
|||||||
#include "py_image.h"
|
#include "py_image.h"
|
||||||
#include "py_imlib.h"
|
#include "py_imlib.h"
|
||||||
#include "py_assert.h"
|
#include "py_assert.h"
|
||||||
|
#include "py_file.h"
|
||||||
|
|
||||||
|
typedef struct _py_cascade_obj_t {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
struct cascade _cobj;
|
||||||
|
} py_cascade_obj_t;
|
||||||
|
|
||||||
extern struct sensor_dev sensor;
|
extern struct sensor_dev sensor;
|
||||||
|
|
||||||
|
static void py_cascade_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind)
|
||||||
|
{
|
||||||
|
py_cascade_obj_t *self = self_in;
|
||||||
|
|
||||||
|
/* print some info */
|
||||||
|
print(env, "width:%d height:%d n_stages:%d n_features:%d n_rectangles:%d\n",
|
||||||
|
self->_cobj.window.w,
|
||||||
|
self->_cobj.window.h,
|
||||||
|
self->_cobj.n_stages,
|
||||||
|
self->_cobj.n_features,
|
||||||
|
self->_cobj.n_rectangles);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const mp_obj_type_t py_cascade_type = {
|
||||||
|
{ &mp_const_type },
|
||||||
|
"Cascade",
|
||||||
|
.print = py_cascade_print,
|
||||||
|
};
|
||||||
|
|
||||||
|
void *py_cascade_cobj(mp_obj_t cascade)
|
||||||
|
{
|
||||||
|
PY_ASSERT_TYPE(cascade, &py_cascade_type);
|
||||||
|
return &((py_cascade_obj_t *)cascade)->_cobj;
|
||||||
|
}
|
||||||
|
|
||||||
mp_obj_t py_imlib_histeq(mp_obj_t image_obj)
|
mp_obj_t py_imlib_histeq(mp_obj_t image_obj)
|
||||||
{
|
{
|
||||||
struct image *image;
|
struct image *image;
|
||||||
@ -69,49 +100,66 @@ mp_obj_t py_imlib_detect_color(mp_obj_t image_obj, mp_obj_t color_obj, mp_obj_t
|
|||||||
return rt_build_tuple(4, rec_obj);
|
return rt_build_tuple(4, rec_obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_obj_t py_imlib_detect_objects(mp_obj_t image_obj)
|
mp_obj_t py_imlib_detect_objects(mp_obj_t image_obj, mp_obj_t cascade_obj)
|
||||||
{
|
{
|
||||||
struct image *image = NULL;
|
struct image *image = NULL;
|
||||||
struct array *objects=NULL;
|
struct cascade *cascade = NULL;
|
||||||
mp_obj_t mp_objects = mp_const_none;
|
|
||||||
|
|
||||||
/* detection parameters */
|
struct array *objects_array=NULL;
|
||||||
struct cascade cascade = {
|
mp_obj_t objects_list = mp_const_none;
|
||||||
.step = 2,
|
|
||||||
.n_stages = 12,
|
|
||||||
.window = {24, 24},
|
|
||||||
.scale_factor = 1.25f,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* sanity checks */
|
/* sanity checks */
|
||||||
PY_ASSERT_TRUE(sensor.framesize <= FRAMESIZE_QQVGA);
|
PY_ASSERT_TRUE(sensor.framesize <= FRAMESIZE_QQVGA);
|
||||||
PY_ASSERT_TRUE(sensor.pixformat == PIXFORMAT_GRAYSCALE);
|
PY_ASSERT_TRUE(sensor.pixformat == PIXFORMAT_GRAYSCALE);
|
||||||
|
|
||||||
/* get image pointer */
|
/* get C image pointer */
|
||||||
image = (struct image*) py_image_cobj(image_obj);
|
image = py_image_cobj(image_obj);
|
||||||
|
/* get C cascade pointer */
|
||||||
|
cascade = py_cascade_cobj(cascade_obj);
|
||||||
|
|
||||||
objects = imlib_detect_objects(image, &cascade);
|
/* detect objects */
|
||||||
|
objects_array = imlib_detect_objects(image, cascade);
|
||||||
int size = array_length(objects);
|
int size = array_length(objects_array);
|
||||||
if (size) {
|
if (size) {
|
||||||
int i;
|
int i;
|
||||||
|
objects_list = rt_build_list(0, NULL);
|
||||||
for (i=0; i<size; i++) {
|
for (i=0; i<size; i++) {
|
||||||
imlib_draw_rectangle(image, array_at(objects, i));
|
struct rectangle *r = array_at(objects_array, 0);
|
||||||
|
mp_obj_t rec_obj[4];
|
||||||
|
rec_obj[0] = mp_obj_new_int(r->x);
|
||||||
|
rec_obj[1] = mp_obj_new_int(r->y);
|
||||||
|
rec_obj[2] = mp_obj_new_int(r->w);
|
||||||
|
rec_obj[3] = mp_obj_new_int(r->h);
|
||||||
|
rt_list_append(objects_list, rt_build_tuple(4, rec_obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct rectangle *r = array_at(objects, 0);
|
|
||||||
mp_obj_t rec_obj[4];
|
|
||||||
rec_obj[0] = mp_obj_new_int(r->x);
|
|
||||||
rec_obj[1] = mp_obj_new_int(r->y);
|
|
||||||
rec_obj[2] = mp_obj_new_int(r->w);
|
|
||||||
rec_obj[3] = mp_obj_new_int(r->h);
|
|
||||||
mp_objects = rt_build_tuple(4, rec_obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free objects array */
|
/* free objects array */
|
||||||
array_free(objects);
|
array_free(objects_array);
|
||||||
|
|
||||||
return mp_objects;
|
return objects_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t py_imlib_load_cascade(mp_obj_t path_obj)
|
||||||
|
{
|
||||||
|
py_cascade_obj_t *o =NULL;
|
||||||
|
|
||||||
|
/* detection parameters */
|
||||||
|
struct cascade cascade = {
|
||||||
|
.step = 2,
|
||||||
|
.scale_factor = 1.25f,
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *path = mp_obj_str_get_str(path_obj);
|
||||||
|
int res = imlib_load_cascade(&cascade, path);
|
||||||
|
if (res != FR_OK) {
|
||||||
|
nlr_jump(mp_obj_new_exception_msg(qstr_from_str("Imlib"), ffs_strerror(res)));
|
||||||
|
}
|
||||||
|
|
||||||
|
o = m_new_obj(py_cascade_obj_t);
|
||||||
|
o->base.type = &py_cascade_type;
|
||||||
|
o->_cobj = cascade;
|
||||||
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
void py_imlib_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind)
|
void py_imlib_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind)
|
||||||
@ -128,7 +176,8 @@ mp_obj_t py_imlib_init()
|
|||||||
rt_store_attr(m, qstr_from_str("histeq"), rt_make_function_n(1, py_imlib_histeq));
|
rt_store_attr(m, qstr_from_str("histeq"), rt_make_function_n(1, py_imlib_histeq));
|
||||||
rt_store_attr(m, qstr_from_str("draw_rectangle"), rt_make_function_n(2, py_imlib_draw_rectangle));
|
rt_store_attr(m, qstr_from_str("draw_rectangle"), rt_make_function_n(2, py_imlib_draw_rectangle));
|
||||||
rt_store_attr(m, qstr_from_str("detect_color"), rt_make_function_n(3, py_imlib_detect_color));
|
rt_store_attr(m, qstr_from_str("detect_color"), rt_make_function_n(3, py_imlib_detect_color));
|
||||||
rt_store_attr(m, qstr_from_str("detect_objects"), rt_make_function_n(1, py_imlib_detect_objects));
|
rt_store_attr(m, qstr_from_str("detect_objects"), rt_make_function_n(2, py_imlib_detect_objects));
|
||||||
|
rt_store_attr(m, qstr_from_str("load_cascade"), rt_make_function_n(1, py_imlib_load_cascade));
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user