Make Haar detector work on ROIs.

This commit is contained in:
iabdalkader 2016-02-21 23:01:34 +02:00
parent 1d4b95353a
commit 032a6e3e4d
4 changed files with 40 additions and 42 deletions

View File

@ -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);
}
}
}

View File

@ -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);

View File

@ -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];

View File

@ -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);