Update imlib

* Use image for imlib functions
* Rename some types
This commit is contained in:
iabdalkader 2014-02-13 03:12:11 +02:00
parent f0431b9b10
commit ca39013097
2 changed files with 163 additions and 156 deletions

View File

@ -17,6 +17,8 @@
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; })
#define MAX_GRAY_LEVEL (255)
float imlib_distance(struct color *c0, struct color *c1)
{
float sum=0.0f;
@ -28,7 +30,7 @@ float imlib_distance(struct color *c0, struct color *c1)
void imlib_rgb_to_hsv(struct color *rgb, struct color *hsv)
{
int min;
int min;
int max;
int r,g,b;
int delta;
@ -38,8 +40,8 @@ void imlib_rgb_to_hsv(struct color *rgb, struct color *hsv)
g = rgb->g*100/255;
b = rgb->b*100/255;
min = MIN(r, MIN(g, b));
max = MAX(r, MAX(g, b));
min = MIN(r, MIN(g, b));
max = MAX(r, MAX(g, b));
if (min == max) {
/* Black/gray/white */
@ -66,12 +68,12 @@ void imlib_rgb_to_hsv(struct color *rgb, struct color *hsv)
}
/* converts a grayscale buffer to RGB565 to display on LCDs */
void imlib_grayscale_to_rgb565(struct frame_buffer *fb)
void imlib_grayscale_to_rgb565(struct image *image)
{
#if 0
int i;
for (i=0; i<(fb->width * fb->height * fb->bpp); i++) {
uint8_t y = fb->pixels[i];
for (i=0; i<(image->w * image->h * image->bpp); i++) {
uint8_t y = image->pixels[i];
uint8_t r = y*31/255;
uint8_t g = y*63/255;
uint8_t b = y*31/255;
@ -80,7 +82,7 @@ void imlib_grayscale_to_rgb565(struct frame_buffer *fb)
#endif
}
void imlib_color_track(struct frame_buffer *fb, struct color *color, struct point *point, int threshold)
void imlib_detect_color(struct image *image, struct color *color, struct rectangle *rectangle, int threshold)
{
int x,y;
uint8_t p0,p1;
@ -88,17 +90,19 @@ void imlib_color_track(struct frame_buffer *fb, struct color *color, struct poin
struct color hsv;
int pixels = 1;
point->x = 0;
point->y = 0;
rectangle->w = 0;
rectangle->h = 0;
rectangle->x = image->w;
rectangle->y = image->h;
//to avoid sqrt we use squared values
threshold *= threshold;
for (y=0; y<fb->height; y++) {
for (x=0; x<fb->width; x++) {
int i=y*fb->width*fb->bpp+x*fb->bpp;
p0 = fb->pixels[i];
p1 = fb->pixels[i+1];
for (y=0; y<image->h; y++) {
for (x=0; x<image->w; x++) {
int i=y*image->w*image->bpp+x*image->bpp;
p0 = image->pixels[i];
p1 = image->pixels[i+1];
/* map RGB565 to RGB888 */
rgb.r = (uint8_t) (p0>>3) * 255/31;
@ -114,75 +118,83 @@ void imlib_color_track(struct frame_buffer *fb, struct color *color, struct poin
/* add pixel if within threshold */
if (hsv.h < threshold && hsv.s > color->s && hsv.v > color->v) { //s==pale
pixels++;
point->x += x;
point->y += y;
if (x < rectangle->x) {
rectangle->x = x;
}
if (y < rectangle->y) {
rectangle->y = y;
}
if (x > rectangle->w) {
rectangle->w = x;
}
if (y > rectangle->h) {
rectangle->h = y;
}
}
}
}
if (pixels < 10) {
point->x = 0;
point->y = 0;
} else {
point->x /= pixels;
point->y /= pixels;
}
rectangle->w = rectangle->w-rectangle->x;
rectangle->h = rectangle->h-rectangle->y;
}
void imlib_erosion_filter(struct frame_buffer *fb, uint8_t *kernel, int k_size)
void imlib_erosion_filter(struct image *src, uint8_t *kernel, int k_size)
{
int x, y, j, k;
int w = fb->width;
int h = fb->height;
int w = src->w;
int h = src->h;
/* TODO */
uint8_t *dst = calloc(w*h, 1);
for (y=0; y<h-k_size; y++) {
for (x=0; x<w-k_size; x++) {
dst[w*(y+1)+x+1] = 255;
for (j=0; j<k_size; j++) {
for (k=0; k<k_size; k++) {
/* (y*w+x)+(j*w+k) */
if (fb->pixels[w*(y+j)+x+k] != (kernel[j*k_size+k]*255)) {
if (src->pixels[w*(y+j)+x+k] != (kernel[j*k_size+k]*255)) {
dst[w*(y+1)+x+1] = 0;
j=k_size;
break;
}
}
}
}
}
}
memcpy(fb->pixels, dst, w*h);
memcpy(src->pixels, dst, w*h);
free(dst);
}
void imlib_integral_image(struct frame_buffer *src, struct integral_image *sum)
void imlib_integral_image(struct image *src, struct integral_image *sum)
{
int x, y, s,t;
unsigned char *data = src->data;
typeof(*sum->data) *sumData = sum->data;
for (y=0; y<src->height; y++) {
s = 0;
/* loop over the number of columns */
for (x=0; x<src->width; x++) {
/* sum of the current row (integer)*/
s += data[y*src->width+x];
t = s;
if (y != 0) {
t += sumData[(y-1)*src->width+x];
}
sumData[y*src->width+x]=t;
}
}
int x, y, s,t;
unsigned char *data = src->pixels;
typeof(*sum->data) *sumData = sum->data;
for (y=0; y<src->h; y++) {
s = 0;
/* loop over the number of columns */
for (x=0; x<src->w; x++) {
/* sum of the current row (integer)*/
s += data[y*src->w+x];
t = s;
if (y != 0) {
t += sumData[(y-1)*src->w+x];
}
sumData[y*src->w+x]=t;
}
}
}
void imlib_scale_image(struct frame_buffer *src, struct frame_buffer *dst)
void imlib_scale_image(struct image *src, struct image *dst)
{
int x, y, i, j;
uint8_t *t, *p;
int w1 = src->width;
int h1 = src->height;
int w2 = dst->width;
int h2 = dst->height;
int w1 = src->w;
int h1 = src->h;
int w2 = dst->w;
int h2 = dst->h;
int rat = 0;
@ -205,53 +217,57 @@ void imlib_scale_image(struct frame_buffer *src, struct frame_buffer *dst)
}
}
void imlib_draw_rectangle(struct frame_buffer* image, struct rectangle *r)
void imlib_draw_rectangle(struct image *image, struct rectangle *r)
{
int i;
int bpp = image->bpp;
int col = image->width*image->bpp;
uint8_t c=0xff;
for (i = 0; i < r->width*bpp; i++) {
image->data[r->y*col + r->x*bpp + i] = c;
}
int i;
uint8_t c=0xFF;
int x = MIN(MAX(r->x, 0), image->w);
int y = MIN(MAX(r->y, 0), image->h);
int w = (x+r->w) > image->w ? (image->w-x):r->w;
int h = (y+r->h) > image->h ? (image->h-y):r->h;
for (i = 0; i < r->height; i++) {
image->data[col*(r->y+i) + r->x*bpp + r->width*bpp] = c;
}
x *= image->bpp;
w *= image->bpp;
int col = image->w*image->bpp;
for (i = 0; i < r->width*bpp; i++) {
image->data[col*(r->y + r->height) + r->x*bpp + r->width*bpp - i] = c;
}
for (i=0; i<w; i++) {
image->pixels[y*col + x + i] = c;
image->pixels[(y+h)*col + x + i] = c;
}
for (i = 0; i < r->height; i++) {
image->data[col*(r->y + r->height - i) + r->x*bpp] =c;
}
for (i=0; i<h; i++) {
image->pixels[(y+i)*col + x] = c;
image->pixels[(y+i)*col + x + w-2] = c;
if (image->bpp>1) {
image->pixels[(y+i)*col + x+1] = c;
image->pixels[(y+i)*col + x + w-1] = c;
}
}
}
#define MAX_GRAY_LEVEL (255)
void imlib_histeq(struct frame_buffer *fb)
void imlib_histeq(struct image *src)
{
int i, sum;
int a = fb->width*fb->height;
uint32_t hist[MAX_GRAY_LEVEL+1]={0};
int a = src->w*src->h;
uint32_t hist[MAX_GRAY_LEVEL+1]={0};
/* compute image histogram */
for (i=0; i<a; i++) {
hist[fb->pixels[i]]+=1;
hist[src->pixels[i]]+=1;
}
/* compute the CDF */
/* compute the CDF */
for (i=0, sum=0; i<MAX_GRAY_LEVEL+1; i++) {
sum += hist[i];
hist[i] = sum;
}
for (i=0; i<a; i++) {
fb->pixels[i] = (uint8_t) ((MAX_GRAY_LEVEL/(float)a) * hist[fb->pixels[i]]);
src->pixels[i] = (uint8_t) ((MAX_GRAY_LEVEL/(float)a) * hist[src->pixels[i]]);
}
}
/* Viola-Jones face detector implementation
/* Viola-Jones face detector implementation
* 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 )
@ -270,7 +286,7 @@ static int evalWeakClassifier(struct integral_image *sum, int std, int p_offset,
int i,k, sumw=0;
if ((tr.x)&& (tr.y) &&(tr.width) &&(tr.height)) {
if ((tr.x)&& (tr.y) &&(tr.w) &&(tr.h)) {
k = 3;
} else {
k = 2;
@ -283,13 +299,13 @@ static int evalWeakClassifier(struct integral_image *sum, int std, int p_offset,
tr.h = rectangles_array[r_index + i*4 + 3];
sumw += (
*((sum->data + sum->width*(tr.y ) + (tr.x )) + p_offset)
- *((sum->data + sum->width*(tr.y ) + (tr.x + tr.width)) + p_offset)
- *((sum->data + sum->width*(tr.y + tr.height) + (tr.x )) + p_offset)
+ *((sum->data + sum->width*(tr.y + tr.height) + (tr.x + tr.width)) + 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.h) + (tr.x )) + p_offset)
+ *((sum->data + sum->w*(tr.y + tr.h) + (tr.x + tr.w)) + p_offset))
* weights_array[w_index + i];
}
if (sumw >= t) {
return alpha2_array[tree_index];
}
@ -308,42 +324,42 @@ static int runCascadeClassifier(struct cascade* cascade, struct point pt, int st
int r_index = 0;
int stage_sum;
int tree_index = 0;
int x,y,offset;
uint32_t sumsq=0;
vec_t v0, v1;
for (y=pt.y; y<24; y++) {
for (x=pt.x; x<24; x+=2) {
offset = y*cascade->img->width+x;
v0.s0 = cascade->img->data[offset+0];
v0.s1 = cascade->img->data[offset+1];
offset = y*cascade->img->w+x;
v0.s0 = cascade->img->pixels[offset+0];
v0.s1 = cascade->img->pixels[offset+1];
v1.s0 = cascade->img->data[offset+0];
v1.s1 = cascade->img->data[offset+1];
v1.s0 = cascade->img->pixels[offset+0];
v1.s1 = cascade->img->pixels[offset+1];
sumsq = __SMLAD(v0.i, v1.i, sumsq);
}
}
/* Image normalization */
int win_w = cascade->window.width - 1;
int win_h = cascade->window.height - 1;
int win_w = cascade->window.w - 1;
int win_h = cascade->window.h - 1;
p_offset = pt.y * (cascade->sum.width) + pt.x;
p_offset = pt.y * (cascade->sum.w) + pt.x;
mean = cascade->sum.data[p_offset]
- cascade->sum.data[win_w + p_offset]
- cascade->sum.data[cascade->sum.width * win_h + p_offset]
+ cascade->sum.data[cascade->sum.width * win_h + win_w + p_offset];
- cascade->sum.data[cascade->sum.w * win_h + p_offset]
+ cascade->sum.data[cascade->sum.w * win_h + win_w + p_offset];
std = sqrtf(sumsq * cascade->window.width * cascade->window.height - mean * mean);
std = sqrtf(sumsq * cascade->window.w * cascade->window.h - mean * mean);
for (i=start_stage; i<cascade->n_stages; i++) {
stage_sum = 0;
for (j=0; j<stages_array[i]; j++, tree_index++, w_index+=3, r_index+=12) {
/* send the shifted window to a haar filter */
stage_sum += evalWeakClassifier(&cascade->sum, std, p_offset, tree_index, w_index, r_index);
}
}
/* If the sum is below the stage threshold, no faces are detected */
if (stage_sum < 0.4*stages_thresh_array[i]) {
@ -362,12 +378,12 @@ static void ScaleImageInvoker(struct cascade *cascade, float factor, int sum_row
struct point p;
struct size win_size;
win_size.width = roundf(cascade->window.width*factor);
win_size.height = roundf(cascade->window.height*factor);
win_size.w = roundf(cascade->window.w*factor);
win_size.h = roundf(cascade->window.h*factor);
/* When filter window shifts to image boarder, some margin need to be kept */
y2 = sum_row - win_size.height;
x2 = sum_col - win_size.width;
y2 = sum_row - win_size.h;
x2 = sum_col - win_size.w;
/* Shift the filter window over the image. */
for (x=0; x<=x2; x+=cascade->step) {
@ -382,8 +398,8 @@ static void ScaleImageInvoker(struct cascade *cascade, float factor, int sum_row
struct rectangle *r = malloc(sizeof(struct rectangle));
r->x = roundf(x*factor);
r->y = roundf(y*factor);
r->w = win_size.width;
r->h = win_size.height;
r->w = win_size.w;
r->h = win_size.h;
array_push_back(vec, r);
}
}
@ -447,7 +463,7 @@ struct array *imlib_merge_detections(struct array *rectangles)
rect1 = (struct rectangle *) array_at(rectangles, 0);
for (j=1; j<array_length(rectangles); j++) {
rect2 = (struct rectangle *) array_at(rectangles, j);
if (rectangle_intersects(rect1, rect2)) {
if (rectangle_intersects(rect1, rect2)) {
array_push_back(overlap, rectangle_clone(rect2));
array_erase(rectangles, j--);
}
@ -460,7 +476,7 @@ struct array *imlib_merge_detections(struct array *rectangles)
rectangle_add(rect1, rect2);
array_erase(overlap, 0);
}
/* average the overlaping detections */
rectangle_div(rect1, count);
array_push_back(objects, rectangle_clone(rect1));
@ -469,30 +485,31 @@ struct array *imlib_merge_detections(struct array *rectangles)
array_free(overlap);
array_free(rectangles);
return objects;
return objects;
}
struct array *imlib_detect_objects(struct cascade *cascade, struct frame_buffer *fb)
struct array *imlib_detect_objects(struct image *image, struct cascade *cascade)
{
/* scaling factor */
float factor;
struct array *objects;
struct frame_buffer img;
struct image img;
struct integral_image sum;
/* allocate buffer for scaled image */
img.width = fb->width;
img.height = fb->height;
/* use the second half of the frame_buffer */
img.pixels = fb->pixels+(fb->width * fb->height);
img.w = image->w;
img.h = image->h;
img.bpp = image->bpp;
/* use the second half of the framebuffer */
img.pixels = image->pixels+(image->w * image->h);
/* allocate buffer for integral image */
sum.width = fb->width;
sum.height = fb->height;
//sum.data = malloc(fb->width *fb->height*sizeof(*sum.data));
sum.data = (uint32_t*) fb->pixels+(fb->width * fb->height * 2);
sum.w = image->w;
sum.h = image->h;
//sum.data = malloc(image->w *image->h*sizeof(*sum.data));
sum.data = (uint32_t*) (image->pixels+(image->w * image->h * 2));
/* allocate the detections array */
array_alloc(&objects, free);
@ -503,26 +520,26 @@ struct array *imlib_detect_objects(struct cascade *cascade, struct frame_buffer
/* iterate over the image pyramid */
for(factor=1.0f; ; factor*=cascade->scale_factor) {
/* size of the scaled image */
struct size sz = {
(fb->width/factor),
(fb->height/factor)
struct size sz = {
(image->w/factor),
(image->h/factor)
};
/* if scaled image is smaller than the original detection window, break */
if ((sz.width - cascade->window.width) <= 0 ||
(sz.height - cascade->window.height) <= 0) {
if ((sz.w - cascade->window.w) <= 0 ||
(sz.h - cascade->window.h) <= 0) {
break;
}
/* Set the width and height of the images */
img.width = sz.width;
img.height = sz.height;
/* Set the width and height of the images */
img.w = sz.w;
img.h = sz.h;
sum.width = sz.width;
sum.height = sz.height;
sum.w = sz.w;
sum.h = sz.h;
/* downsample using nearest neighbor */
imlib_scale_image(fb, &img);
imlib_scale_image(image, &img);
/* compute a new integral image */
imlib_integral_image(&img, &sum);
@ -531,7 +548,7 @@ struct array *imlib_detect_objects(struct cascade *cascade, struct frame_buffer
cascade->sum = sum;
/* process the current scale with the cascaded fitler. */
ScaleImageInvoker(cascade, factor, sum.height, sum.width, objects);
ScaleImageInvoker(cascade, factor, sum.h, sum.w, objects);
}
//free(sum.data);
@ -539,5 +556,3 @@ struct array *imlib_detect_objects(struct cascade *cascade, struct frame_buffer
objects = imlib_merge_detections(objects);
return objects;
}

View File

@ -7,21 +7,15 @@ struct point {
};
struct size {
int width;
int height;
int w;
int h;
};
struct rectangle {
int x;
int y;
union {
int width;
int w;
};
union {
int h;
int height;
};
int w;
int h;
};
struct color {
@ -39,19 +33,16 @@ struct color {
};
};
struct frame_buffer {
int width;
int height;
struct image {
int w;
int h;
int bpp;
union {
uint8_t *data;
uint8_t *pixels;
};
uint8_t *pixels;
};
struct integral_image {
int width;
int height;
int w;
int h;
uint32_t *data;
};
@ -86,16 +77,17 @@ struct cascade {
/* pointer to current integral image */
struct integral_image sum;
/* pointer to current scaled image in the pyramid */
struct frame_buffer *img;
struct image *img;
};
float imlib_distance(struct color *c0, struct color *c1);
void imlib_rgb_to_hsv(struct color *rgb, struct color *hsv);
void imlib_grayscale_to_rgb565(struct frame_buffer *fb);
void imlib_color_track(struct frame_buffer *fb, struct color *color, struct point *point, int threshold);
void imlib_erosion_filter(struct frame_buffer *fb, uint8_t *kernel, int k_size);
void imlib_scale_image(struct frame_buffer *src, struct frame_buffer *dst);
void imlib_integral_image(struct frame_buffer *src, struct integral_image *sum);
void imlib_draw_rectangle(struct frame_buffer* image, struct rectangle *r);
struct array *imlib_detect_objects(struct cascade* cascade, struct frame_buffer* fb);
void imlib_grayscale_to_rgb565(struct image *image);
void imlib_detect_color(struct image *image, struct color *color, struct rectangle *rectangle, int threshold);
void imlib_erosion_filter(struct image *src, uint8_t *kernel, int k_size);
void imlib_scale_image(struct image *src, struct image *dst);
void imlib_integral_image(struct image *src, struct integral_image *sum);
void imlib_draw_rectangle(struct image *image, struct rectangle *r);
void imlib_histeq(struct image *src);
struct array *imlib_detect_objects(struct image *image, struct cascade* cascade);
#endif //__IMLIB_H__