mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Make Haar detector work on ROIs.
This commit is contained in:
parent
1d4b95353a
commit
032a6e3e4d
@ -65,7 +65,7 @@ static int run_cascade_classifier(cascade_t* cascade, point_t pt)
|
||||
return 1;
|
||||
}
|
||||
|
||||
array_t *imlib_detect_objects(image_t *image, cascade_t *cascade)
|
||||
array_t *imlib_detect_objects(image_t *image, cascade_t *cascade, rectangle_t *roi)
|
||||
{
|
||||
// Integral images
|
||||
mw_image_t sum;
|
||||
@ -86,7 +86,7 @@ array_t *imlib_detect_objects(image_t *image, cascade_t *cascade)
|
||||
// Viola and Jones achieved best results using a scaling factor
|
||||
// of 1.25 and a scanning factor proportional to the current scale.
|
||||
// Start with a step of 5% of the image width and reduce at each scaling step
|
||||
cascade->step = (image->w*50)/1000;
|
||||
cascade->step = (roi->w*50)/1000;
|
||||
|
||||
// Make sure step is less than feature height + 1
|
||||
if (cascade->step > cascade->window.w) {
|
||||
@ -94,14 +94,14 @@ array_t *imlib_detect_objects(image_t *image, cascade_t *cascade)
|
||||
}
|
||||
|
||||
// Allocate integral images
|
||||
imlib_integral_mw_alloc(&sum, image->w, cascade->window.h+1);
|
||||
imlib_integral_mw_alloc(&ssq, image->w, cascade->window.h+1);
|
||||
imlib_integral_mw_alloc(&sum, roi->w, cascade->window.h+1);
|
||||
imlib_integral_mw_alloc(&ssq, roi->w, cascade->window.h+1);
|
||||
|
||||
// Iterate over the image pyramid
|
||||
for(float factor=1.0f; ; factor *= cascade->scale_factor) {
|
||||
// Set the scaled width and height
|
||||
int szw = image->w/factor;
|
||||
int szh = image->h/factor;
|
||||
int szw = roi->w/factor;
|
||||
int szh = roi->h/factor;
|
||||
|
||||
// Break if scaled image is smaller than feature size
|
||||
if (szw < cascade->window.w || szh < cascade->window.h) {
|
||||
@ -109,11 +109,11 @@ array_t *imlib_detect_objects(image_t *image, cascade_t *cascade)
|
||||
}
|
||||
|
||||
// Set the integral images scale
|
||||
imlib_integral_mw_scale(image, &sum, szw, szh);
|
||||
imlib_integral_mw_scale(image, &ssq, szw, szh);
|
||||
imlib_integral_mw_scale(roi, &sum, szw, szh);
|
||||
imlib_integral_mw_scale(roi, &ssq, szw, szh);
|
||||
|
||||
// Compute new scaled integral images
|
||||
imlib_integral_mw_ss(image, &sum, &ssq);
|
||||
imlib_integral_mw_ss(image, &sum, &ssq, roi);
|
||||
|
||||
// Scale the scanning step
|
||||
cascade->step = cascade->step/factor;
|
||||
@ -130,14 +130,15 @@ array_t *imlib_detect_objects(image_t *image, cascade_t *cascade)
|
||||
point_t p = {x, y};
|
||||
// If an object is detected, record the coordinates of the filter window
|
||||
if (run_cascade_classifier(cascade, p) > 0) {
|
||||
array_push_back(objects, rectangle_alloc(fast_roundf(x*factor), fast_roundf(y*factor),
|
||||
array_push_back(objects,
|
||||
rectangle_alloc(fast_roundf(x*factor) + roi->x, fast_roundf(y*factor) + roi->y,
|
||||
fast_roundf(cascade->window.w*factor), fast_roundf(cascade->window.h*factor)));
|
||||
}
|
||||
}
|
||||
|
||||
// If not last line, shift integral images
|
||||
if ((y+cascade->step) < y2) {
|
||||
imlib_integral_mw_shift_ss(cascade->img, cascade->sum, cascade->ssq, cascade->step);
|
||||
imlib_integral_mw_shift_ss(image, &sum, &ssq, roi, cascade->step);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -353,13 +353,13 @@ uint32_t imlib_integral_lookup(struct integral_image *src, int x, int y, int w,
|
||||
// Integral moving window
|
||||
void imlib_integral_mw_alloc(mw_image_t *sum, int w, int h);
|
||||
void imlib_integral_mw_free(mw_image_t *sum);
|
||||
void imlib_integral_mw_scale(image_t *src, mw_image_t *sum, int w, int h);
|
||||
void imlib_integral_mw_scale(rectangle_t *roi, mw_image_t *sum, int w, int h);
|
||||
void imlib_integral_mw(image_t *src, mw_image_t *sum);
|
||||
void imlib_integral_mw_sq(image_t *src, mw_image_t *sum);
|
||||
void imlib_integral_mw_shift(image_t *src, mw_image_t *sum, int n);
|
||||
void imlib_integral_mw_shift_sq(image_t *src, mw_image_t *sum, int n);
|
||||
void imlib_integral_mw_ss(image_t *src, mw_image_t *sum, mw_image_t *ssq);
|
||||
void imlib_integral_mw_shift_ss(image_t *src, mw_image_t *sum, mw_image_t *ssq, int n);
|
||||
void imlib_integral_mw_ss(image_t *src, mw_image_t *sum, mw_image_t *ssq, rectangle_t *roi);
|
||||
void imlib_integral_mw_shift_ss(image_t *src, mw_image_t *sum, mw_image_t *ssq, rectangle_t *roi, int n);
|
||||
long imlib_integral_mw_lookup(mw_image_t *sum, int x, int y, int w, int h);
|
||||
|
||||
/* Template matching */
|
||||
@ -367,7 +367,7 @@ float imlib_template_match(struct image *image, struct image *template, struct r
|
||||
|
||||
/* Haar/VJ */
|
||||
int imlib_load_cascade(struct cascade* cascade, const char *path);
|
||||
array_t *imlib_detect_objects(struct image *image, struct cascade* cascade);
|
||||
array_t *imlib_detect_objects(struct image *image, struct cascade *cascade, struct rectangle *roi);
|
||||
|
||||
/* FAST/FREAK Feature Extractor */
|
||||
kp_t *fast_detect(image_t *image, int threshold, int *ret_num_corners, rectangle_t *roi);
|
||||
|
||||
@ -83,7 +83,7 @@ void imlib_integral_mw_free(mw_image_t *sum)
|
||||
fb_free(); // Free swap
|
||||
}
|
||||
|
||||
void imlib_integral_mw_scale(image_t *src, mw_image_t *sum, int w, int h)
|
||||
void imlib_integral_mw_scale(rectangle_t *roi, mw_image_t *sum, int w, int h)
|
||||
{
|
||||
// Set new width
|
||||
// Note: height doesn't change
|
||||
@ -91,8 +91,8 @@ void imlib_integral_mw_scale(image_t *src, mw_image_t *sum, int w, int h)
|
||||
// Reset y offset
|
||||
sum->y_offs = 0;
|
||||
// Set scaling ratios
|
||||
sum->x_ratio = (int)((src->w<<16)/w)+1;
|
||||
sum->y_ratio = (int)((src->h<<16)/h)+1;
|
||||
sum->x_ratio = (int)((roi->w<<16)/w)+1;
|
||||
sum->y_ratio = (int)((roi->h<<16)/h)+1;
|
||||
}
|
||||
|
||||
void imlib_integral_mw(image_t *src, mw_image_t *sum)
|
||||
@ -231,7 +231,7 @@ void imlib_integral_mw_shift_sq(image_t *src, mw_image_t *sum, int n)
|
||||
}
|
||||
}
|
||||
|
||||
void imlib_integral_mw_ss(image_t *src, mw_image_t *sum, mw_image_t *ssq)
|
||||
void imlib_integral_mw_ss(image_t *src, mw_image_t *sum, mw_image_t *ssq, rectangle_t *roi)
|
||||
{
|
||||
// Image data pointers
|
||||
typeof(*src->data) *img_data = src->data;
|
||||
@ -241,11 +241,11 @@ void imlib_integral_mw_ss(image_t *src, mw_image_t *sum, mw_image_t *ssq)
|
||||
// Compute the first row to avoid branching
|
||||
for (int sx, s=0, sq=0, x=0; x<sum->w; x++) {
|
||||
// X offset
|
||||
sx = (x*sum->x_ratio)>>16;
|
||||
sx = roi->x+((x*sum->x_ratio)>>16);
|
||||
|
||||
// Accumulate row data
|
||||
s += img_data[sx];
|
||||
sq += img_data[sx] * img_data[sx];
|
||||
s += img_data[roi->y*src->w+sx];
|
||||
sq += img_data[roi->y*src->w+sx] * img_data[roi->y*src->w+sx];
|
||||
|
||||
sum_data[0][x] = s;
|
||||
ssq_data[0][x] = sq;
|
||||
@ -254,12 +254,12 @@ void imlib_integral_mw_ss(image_t *src, mw_image_t *sum, mw_image_t *ssq)
|
||||
// Compute the last n lines
|
||||
for (int sy, y=1; y<sum->h; y++) {
|
||||
// Y offset
|
||||
sy = (y*sum->y_ratio)>>16;
|
||||
sy = roi->y+((y*sum->y_ratio)>>16);
|
||||
|
||||
// Sum the current row
|
||||
for (int sx, s=0, sq=0, x=0; x<sum->w; x++) {
|
||||
// X offset
|
||||
sx = (x*sum->x_ratio)>>16;
|
||||
sx = roi->x+((x*sum->x_ratio)>>16);
|
||||
|
||||
// Accumulate row data
|
||||
s += img_data[sy*src->w+sx];
|
||||
@ -274,7 +274,7 @@ void imlib_integral_mw_ss(image_t *src, mw_image_t *sum, mw_image_t *ssq)
|
||||
ssq->y_offs = sum->h;
|
||||
}
|
||||
|
||||
void imlib_integral_mw_shift_ss(image_t *src, mw_image_t *sum, mw_image_t *ssq, int n)
|
||||
void imlib_integral_mw_shift_ss(image_t *src, mw_image_t *sum, mw_image_t *ssq, rectangle_t *roi, int n)
|
||||
{
|
||||
typeof(*src->data) *img_data = src->data;
|
||||
|
||||
@ -295,12 +295,12 @@ void imlib_integral_mw_shift_ss(image_t *src, mw_image_t *sum, mw_image_t *ssq,
|
||||
// Compute the last n lines
|
||||
for (int sy, y=(sum->h - n); y<sum->h; y++, sum->y_offs++, ssq->y_offs++) {
|
||||
// The y offset is set to the last line + 1
|
||||
sy = (sum->y_offs*sum->y_ratio)>>16;
|
||||
sy = roi->y+((sum->y_offs*sum->y_ratio)>>16);
|
||||
|
||||
// Sum of the current row
|
||||
for (int sx, s=0, sq=0, x=0; x<sum->w; x++) {
|
||||
// X offset
|
||||
sx = (x*sum->x_ratio)>>16;
|
||||
sx = roi->x+((x*sum->x_ratio)>>16);
|
||||
|
||||
// Accumulate row data
|
||||
s += img_data[sy*src->w+sx];
|
||||
|
||||
@ -1038,6 +1038,13 @@ static mp_obj_t py_image_find_features(uint n_args, const mp_obj_t *args, mp_map
|
||||
cascade->scale_factor = mp_obj_get_float(kw_scalef->value);
|
||||
}
|
||||
|
||||
rectangle_t roi = {
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.w = image->w,
|
||||
.h = image->h,
|
||||
};
|
||||
|
||||
mp_map_elem_t *kw_roi = mp_map_lookup(kw_args, MP_OBJ_NEW_QSTR(qstr_from_str("roi")), MP_MAP_LOOKUP);
|
||||
if (kw_roi != NULL) {
|
||||
mp_obj_t *array;
|
||||
@ -1045,10 +1052,10 @@ static mp_obj_t py_image_find_features(uint n_args, const mp_obj_t *args, mp_map
|
||||
|
||||
// If one of those is negative roi.(x) will overflow uint16_t
|
||||
// And this error will be detected when checking ROI's bounds
|
||||
uint16_t x = mp_obj_get_int(array[0]);
|
||||
uint16_t y = mp_obj_get_int(array[1]);
|
||||
uint16_t w = mp_obj_get_int(array[2]);
|
||||
uint16_t h = mp_obj_get_int(array[3]);
|
||||
uint16_t x = roi.x = mp_obj_get_int(array[0]);
|
||||
uint16_t y = roi.y = mp_obj_get_int(array[1]);
|
||||
uint16_t w = roi.w = mp_obj_get_int(array[2]);
|
||||
uint16_t h = roi.h = mp_obj_get_int(array[3]);
|
||||
|
||||
// Make sure ROI is bigger than feature size
|
||||
PY_ASSERT_TRUE_MSG((w > cascade->window.w &&
|
||||
@ -1059,20 +1066,10 @@ static mp_obj_t py_image_find_features(uint n_args, const mp_obj_t *args, mp_map
|
||||
PY_ASSERT_TRUE_MSG(((x + w) < image->w &&
|
||||
(y + h) < image->h),
|
||||
"Region of interest is bigger than frame size!");
|
||||
|
||||
image_t subimg = {
|
||||
.w = w,
|
||||
.h = h,
|
||||
.bpp = image->bpp,
|
||||
.pixels = xalloc(w*h*image->bpp)
|
||||
};
|
||||
|
||||
imlib_subimage(image, &subimg, x, y);
|
||||
image = &subimg;
|
||||
}
|
||||
|
||||
// Detect objects
|
||||
objects_array = imlib_detect_objects(image, cascade);
|
||||
objects_array = imlib_detect_objects(image, cascade, &roi);
|
||||
|
||||
/* Create empty Python list */
|
||||
objects_list = mp_obj_new_list(0, NULL);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user