mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Add HoG.
This commit is contained in:
parent
60dc3f7e91
commit
ef6e6303c7
@ -168,6 +168,7 @@ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/img/,\
|
||||
hough.o \
|
||||
sincos_tab.o \
|
||||
edge.o \
|
||||
hog.o \
|
||||
)
|
||||
|
||||
FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/py/, \
|
||||
|
||||
@ -55,6 +55,7 @@ SRCS += $(addprefix img/, \
|
||||
hough.c \
|
||||
sincos_tab.c \
|
||||
edge.c \
|
||||
hog.c \
|
||||
)
|
||||
|
||||
SRCS += $(addprefix py/, \
|
||||
|
||||
127
src/omv/img/hog.c
Normal file
127
src/omv/img/hog.c
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* HoG.
|
||||
* See Histograms of Oriented Gradients (Navneet Dalal and Bill Triggs)
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include "imlib.h"
|
||||
#include "fb_alloc.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
#define N_BINS (9)
|
||||
typedef struct bin {
|
||||
int d;
|
||||
int m;
|
||||
} bin_t;
|
||||
|
||||
int bin_array_comp(const void *obj0, const void *obj1)
|
||||
{
|
||||
const bin_t *b0 = obj0;
|
||||
const bin_t *b1 = obj1;
|
||||
if (b0->m < b1->m)
|
||||
return -1;
|
||||
if (b0->m > b1->m)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void imlib_find_hog(image_t *src, rectangle_t *roi, int cell_size)
|
||||
{
|
||||
int s = src->w;
|
||||
int w = roi->x+roi->w-1;
|
||||
int h = roi->y+roi->h-1;
|
||||
|
||||
int block_size = cell_size * 2;
|
||||
int x_cells = (roi->w/cell_size);
|
||||
int y_cells = (roi->h/cell_size);
|
||||
|
||||
// TODO: Assert row->w/h >= cell_size *2;
|
||||
float *hog = fb_alloc0(x_cells * y_cells * N_BINS * sizeof*hog);
|
||||
|
||||
//2. Finding Image Gradients
|
||||
for (int y=roi->y, hog_index=0; y<h; y+=block_size) {
|
||||
for (int x=roi->x; x<w; x+=block_size) {
|
||||
float k = 0.0f;
|
||||
for (int cy=0; cy<block_size; cy++) {
|
||||
for (int cx=0; cx<block_size; cx++) {
|
||||
if ((y+cy) > 0 && (y+cy) < h && (x+cx) > 0 && (x+cx) < w) {
|
||||
// Find horizontal/vertical direction
|
||||
int vx = src->data[(y+cy+0)*s+(x+cx+1)] - src->data[(y+cy-0)*s+(x+cx-1)];
|
||||
int vy = src->data[(y+cy+1)*s+(x+cx+0)] - src->data[(y+cy-1)*s+(x+cx-0)];
|
||||
// Find magnitude
|
||||
float m = fast_sqrtf(vx*vx + vy*vy);
|
||||
if(((int) m) > 1) {
|
||||
k += m*m;
|
||||
// Find and quantize gradient degree
|
||||
// TODO atan2f is swapped for visualization
|
||||
int t = ((int) fast_fabsf((atan2f(vx, vy)*180.0f/M_PI))) / 20;
|
||||
t = (t == 9)? 0 : t;
|
||||
|
||||
// hog[((cy/cell_size) * x_cells + (cx/cell_size)) * N_BINS + t] += m;
|
||||
hog[hog_index + (((cy/8)*2+(cx/8)) * N_BINS) + t] += m;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize the last block
|
||||
k = sqrtf(k);
|
||||
for (int i=hog_index; i<(hog_index+(N_BINS*4)); i++) {
|
||||
hog[i] = hog[i]/k;
|
||||
}
|
||||
|
||||
hog_index += (N_BINS*4);
|
||||
}
|
||||
}
|
||||
|
||||
memset(src->pixels, 0, src->w*src->h);
|
||||
|
||||
array_t *gds;
|
||||
bin_t bins[9];
|
||||
array_alloc(&gds, NULL);
|
||||
|
||||
for (int i=0; i<N_BINS; i++) {
|
||||
array_push_back(gds, &bins[i]);
|
||||
}
|
||||
|
||||
int l = cell_size/2;
|
||||
// Note cells are not ordered histograms of 4 cells
|
||||
for (int by=0, hog_index=0; by<y_cells; by+=2) {
|
||||
for (int bx=0; bx<x_cells; bx+=2) {
|
||||
for (int y=0; y<2; y++) {
|
||||
for (int x=0; x<2; x++) {
|
||||
// Sort and draw bins
|
||||
for (int i=hog_index; i<hog_index+N_BINS; i++) {
|
||||
int m = (int)(hog[i]*255);
|
||||
if (m > 255) m = 255; if (m < 0) m = 0;
|
||||
bin_t *bin = array_at(gds, (i%N_BINS));
|
||||
bin->m = m;
|
||||
bin->d = ((i%N_BINS)*20);
|
||||
}
|
||||
|
||||
array_sort(gds, bin_array_comp);
|
||||
|
||||
int x1 = (x+bx) * cell_size + l;
|
||||
int y1 = (y+by) * cell_size + l;
|
||||
for (int i=0; i<N_BINS; i++) {
|
||||
bin_t *bin = array_at(gds, i);
|
||||
int x2 = l * cos_table[bin->d];
|
||||
int y2 = l * sin_table[bin->d];
|
||||
imlib_draw_line(src, (x1 - x2), (y1 + y2), (x1 + x2), (y1 - y2), bin->m);
|
||||
}
|
||||
|
||||
hog_index += N_BINS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xfree(gds);
|
||||
fb_free();
|
||||
}
|
||||
@ -543,6 +543,9 @@ array_t *imlib_find_lines(image_t *src, rectangle_t *roi, int threshold);
|
||||
void imlib_edge_simple(image_t *src, rectangle_t *roi, int low_thresh, int high_thresh);
|
||||
void imlib_edge_canny(image_t *src, rectangle_t *roi, int low_thresh, int high_thresh);
|
||||
|
||||
// HoG
|
||||
void imlib_find_hog(image_t *src, rectangle_t *roi, int cell_size);
|
||||
|
||||
// Lens correction
|
||||
void imlib_lens_corr(image_t *src, float strength);
|
||||
#endif //__IMLIB_H__
|
||||
|
||||
@ -1424,6 +1424,26 @@ static mp_obj_t py_image_find_edges(uint n_args, const mp_obj_t *args, mp_map_t
|
||||
|
||||
return mp_const_true;
|
||||
}
|
||||
|
||||
static mp_obj_t py_image_find_hog(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
||||
{
|
||||
image_t *arg_img = py_image_cobj(args[0]);
|
||||
PY_ASSERT_TRUE_MSG(IM_IS_GS(arg_img), "This function is only supported on GRAYSCALE images");
|
||||
|
||||
rectangle_t arg_r;
|
||||
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;
|
||||
}
|
||||
|
||||
int size = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_size), 8);
|
||||
imlib_find_hog(arg_img, &rect, size);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
/* 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_to_fb_obj, 1, py_image_copy_to_fb);
|
||||
@ -1490,6 +1510,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_find_lbp_obj, py_image_find_lbp);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_find_keypoints_obj, 1, py_image_find_keypoints);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_find_lines_obj, 1, py_image_find_lines);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_find_edges_obj, 2, py_image_find_edges);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_find_hog_obj, 1, py_image_find_hog);
|
||||
static const mp_map_elem_t locals_dict_table[] = {
|
||||
/* Image file functions */
|
||||
{MP_OBJ_NEW_QSTR(MP_QSTR_copy), (mp_obj_t)&py_image_copy_obj},
|
||||
@ -1557,6 +1578,7 @@ static const mp_map_elem_t locals_dict_table[] = {
|
||||
{MP_OBJ_NEW_QSTR(MP_QSTR_find_keypoints), (mp_obj_t)&py_image_find_keypoints_obj},
|
||||
{MP_OBJ_NEW_QSTR(MP_QSTR_find_lines), (mp_obj_t)&py_image_find_lines_obj},
|
||||
{MP_OBJ_NEW_QSTR(MP_QSTR_find_edges), (mp_obj_t)&py_image_find_edges_obj},
|
||||
{MP_OBJ_NEW_QSTR(MP_QSTR_find_hog), (mp_obj_t)&py_image_find_hog_obj},
|
||||
{ NULL, NULL },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(locals_dict, locals_dict_table);
|
||||
|
||||
@ -84,6 +84,7 @@ Q(find_lbp)
|
||||
Q(find_eye)
|
||||
Q(find_lines)
|
||||
Q(find_edges)
|
||||
Q(find_hog)
|
||||
Q(cmp_lbp)
|
||||
Q(quality)
|
||||
Q(color)
|
||||
|
||||
28
usr/examples/09-Feature-Detection/hog.py
Normal file
28
usr/examples/09-Feature-Detection/hog.py
Normal file
@ -0,0 +1,28 @@
|
||||
# Histogram of Oriented Gradients (HoG) Example
|
||||
#
|
||||
# This example demonstrates HoG visualization.
|
||||
#
|
||||
# Note: Due to JPEG artifacts, the HoG visualization looks blurry. To see the
|
||||
# image without JPEG artifacts, uncomment the lines that save the image to uSD.
|
||||
|
||||
import sensor, image, time
|
||||
|
||||
sensor.reset()
|
||||
# Set sensor settings
|
||||
sensor.set_contrast(1)
|
||||
sensor.set_gainceiling(8)
|
||||
sensor.set_framesize(sensor.QVGA)
|
||||
sensor.skip_frames(30)
|
||||
sensor.set_pixformat(sensor.GRAYSCALE)
|
||||
|
||||
clock = time.clock() # Tracks FPS.
|
||||
while (True):
|
||||
clock.tick()
|
||||
img = sensor.snapshot()
|
||||
img.find_hog()
|
||||
|
||||
# Uncomment to save raw FB to file and exit the loop
|
||||
#img.save("/hog.pgm")
|
||||
#break
|
||||
|
||||
print(clock.fps())
|
||||
Loading…
Reference in New Issue
Block a user