mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
NN: Add test function.
* Simulates the network without actually calling any functions.
This commit is contained in:
parent
fb83fb701f
commit
85267ee276
176
src/omv/nn/nn.c
176
src/omv/nn/nn.c
@ -273,19 +273,6 @@ error:
|
||||
return res;
|
||||
}
|
||||
|
||||
#define BUFFER_2STR(buffer)\
|
||||
(buffer == buffer1) ? "buffer1":\
|
||||
(buffer == buffer2) ? "buffer2":\
|
||||
(buffer == input_data) ? "input_data":\
|
||||
(buffer == output_data) ? "output_data": "???"
|
||||
|
||||
#define CONV_FUNC_2STR(conv_func)\
|
||||
(conv_func == arm_convolve_HWC_q7_basic) ? "arm_convolve_HWC_q7_basic" :\
|
||||
(conv_func == arm_convolve_HWC_q7_fast ) ? "arm_convolve_HWC_q7_fast":"arm_convolve_HWC_q7_RGB"
|
||||
|
||||
#define POOL_FUNC_2STR(pool_func)\
|
||||
(pool_func == arm_maxpool_q7_HWC) ? "arm_maxpool_q7_HWC" : "arm_avepool_q7_HWC"
|
||||
|
||||
int nn_run_network(nn_t *net, image_t *img, int8_t *output_data)
|
||||
{
|
||||
uint32_t layer_idx = 0;
|
||||
@ -301,14 +288,14 @@ int nn_run_network(nn_t *net, image_t *img, int8_t *output_data)
|
||||
return -1;
|
||||
}
|
||||
|
||||
q7_t *buffer1 = fb_alloc0(net->max_scrbuf_size);
|
||||
q7_t *buffer2 = buffer1 + net->max_layer_size;
|
||||
q7_t *col_buffer = fb_alloc0(net->max_colbuf_size);
|
||||
|
||||
q7_t *input_data = NULL;
|
||||
q7_t *input_buffer = NULL;
|
||||
q7_t *output_buffer = NULL;
|
||||
|
||||
q7_t *buffer1 = fb_alloc0(net->max_scrbuf_size);
|
||||
q7_t *buffer2 = buffer1 + net->max_layer_size;
|
||||
q7_t *col_buffer = fb_alloc0(net->max_colbuf_size);
|
||||
|
||||
while (layer != NULL) {
|
||||
layer_t *prev_layer = layer->prev;
|
||||
|
||||
@ -347,12 +334,6 @@ int nn_run_network(nn_t *net, image_t *img, int8_t *output_data)
|
||||
} else {
|
||||
conv_func = arm_convolve_HWC_q7_fast;
|
||||
}
|
||||
debug_printf("forward: %s(%s, %lu, %lu, %s, %lu, %lu, %lu, %lu, %s, %lu, %lu, %s, %lu, %s, %p);\n",
|
||||
CONV_FUNC_2STR(conv_func), BUFFER_2STR(input_buffer),
|
||||
prev_layer->h, prev_layer->c, "conv_wt", conv_layer->c,
|
||||
conv_layer->krn_dim, conv_layer->krn_pad, conv_layer->krn_str,
|
||||
"conv_bias", conv_layer->l_shift, conv_layer->r_shift,
|
||||
BUFFER_2STR(output_buffer), conv_layer->h, "col_buffer", NULL);
|
||||
conv_func(input_buffer, prev_layer->h, prev_layer->c, conv_layer->wt, conv_layer->c,
|
||||
conv_layer->krn_dim, conv_layer->krn_pad, conv_layer->krn_str, conv_layer->bias,
|
||||
conv_layer->l_shift, conv_layer->r_shift, output_buffer, conv_layer->h, (q15_t*)col_buffer, NULL);
|
||||
@ -361,8 +342,6 @@ int nn_run_network(nn_t *net, image_t *img, int8_t *output_data)
|
||||
|
||||
case LAYER_TYPE_RELU: {
|
||||
relu_layer_t *relu_layer = (relu_layer_t *) layer;
|
||||
debug_printf("forward: arm_relu_q7(%s, %lu*%lu*%lu);\n",
|
||||
BUFFER_2STR(input_buffer), relu_layer->h, relu_layer->w, relu_layer->c);
|
||||
arm_relu_q7(input_buffer, relu_layer->h * relu_layer->w * relu_layer->c);
|
||||
break;
|
||||
}
|
||||
@ -375,10 +354,6 @@ int nn_run_network(nn_t *net, image_t *img, int8_t *output_data)
|
||||
} else {
|
||||
pool_func = arm_avepool_q7_HWC;
|
||||
}
|
||||
debug_printf("forward: %s(%s, %lu, %lu, %lu, %lu, %lu, %lu, %s, %s);\n",
|
||||
POOL_FUNC_2STR(pool_func), BUFFER_2STR(input_buffer),
|
||||
prev_layer->h, prev_layer->c, pool_layer->krn_dim,
|
||||
pool_layer->krn_pad, pool_layer->krn_str, layer->w, "col_buffer", BUFFER_2STR(output_buffer));
|
||||
pool_func(input_buffer, prev_layer->h, prev_layer->c, pool_layer->krn_dim,
|
||||
pool_layer->krn_pad, pool_layer->krn_str, layer->w, col_buffer, output_buffer);
|
||||
break;
|
||||
@ -386,15 +361,150 @@ int nn_run_network(nn_t *net, image_t *img, int8_t *output_data)
|
||||
|
||||
case LAYER_TYPE_IP: {
|
||||
ip_layer_t *ip_layer = (ip_layer_t*) layer;
|
||||
debug_printf("forward: arm_fully_connected_q7_opt(%s, %s, %lu, %lu, %lu, %lu, %s, %s, %s);\n",
|
||||
BUFFER_2STR(input_buffer), "ip_wt", prev_layer->c * prev_layer->h * prev_layer->w,
|
||||
ip_layer->c, ip_layer->l_shift, ip_layer->r_shift, "ip_bias", BUFFER_2STR(output_buffer), "col_buffer");
|
||||
arm_fully_connected_q7_opt(input_buffer, ip_layer->wt, prev_layer->c * prev_layer->h * prev_layer->w,
|
||||
ip_layer->c, ip_layer->l_shift, ip_layer->r_shift, ip_layer->bias, output_buffer, (q15_t*)col_buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (layer_idx++ > 0) {
|
||||
if (input_buffer == input_data) {
|
||||
// Image data has been processed
|
||||
input_buffer = buffer2;
|
||||
}
|
||||
|
||||
if (layer->type != LAYER_TYPE_RELU) {
|
||||
// Switch buffers
|
||||
q7_t *tmp_buffer = input_buffer;
|
||||
input_buffer = output_buffer;
|
||||
output_buffer = tmp_buffer;
|
||||
}
|
||||
|
||||
// Last layer
|
||||
if (layer->next && layer->next->next == NULL) {
|
||||
output_buffer = output_data;
|
||||
}
|
||||
}
|
||||
|
||||
layer = layer->next;
|
||||
}
|
||||
|
||||
fb_free_all();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define BUFFER_2STR(buffer)\
|
||||
(buffer == buffer1) ? "buffer1":\
|
||||
(buffer == buffer2) ? "buffer2":\
|
||||
(buffer == input_data) ? "input_data":\
|
||||
(buffer == output_data) ? "output_data": "???"
|
||||
|
||||
#define CONV_FUNC_2STR(conv_func)\
|
||||
(conv_func == arm_convolve_HWC_q7_basic) ? "arm_convolve_HWC_q7_basic" :\
|
||||
(conv_func == arm_convolve_HWC_q7_fast ) ? "arm_convolve_HWC_q7_fast":"arm_convolve_HWC_q7_RGB"
|
||||
|
||||
#define POOL_FUNC_2STR(pool_func)\
|
||||
(pool_func == arm_maxpool_q7_HWC) ? "arm_maxpool_q7_HWC" : "arm_avepool_q7_HWC"
|
||||
|
||||
int nn_dry_run_network(nn_t *net, image_t *img, int8_t *output_data)
|
||||
{
|
||||
uint32_t layer_idx = 0;
|
||||
layer_t *layer = net->layers;
|
||||
|
||||
if (layer == NULL) {
|
||||
printf("First layer is NULL!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (layer->type != LAYER_TYPE_DATA) {
|
||||
printf("First layer is not a DATA layer!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
q7_t *input_data = NULL;
|
||||
q7_t *input_buffer = NULL;
|
||||
q7_t *output_buffer = NULL;
|
||||
|
||||
q7_t *buffer1 = fb_alloc0(net->max_scrbuf_size);
|
||||
q7_t *buffer2 = buffer1 + net->max_layer_size;
|
||||
|
||||
while (layer != NULL) {
|
||||
layer_t *prev_layer = layer->prev;
|
||||
switch (layer->type) {
|
||||
case LAYER_TYPE_DATA: {
|
||||
data_layer_t *data_layer = (data_layer_t *) layer;
|
||||
input_data = fb_alloc(data_layer->c * data_layer->h * data_layer->w);
|
||||
// Scale, convert, remove mean image and load input data.
|
||||
int x_ratio = (int)((img->w<<16)/layer->w)+1;
|
||||
int y_ratio = (int)((img->h<<16)/layer->h)+1;
|
||||
for (int y=0, i=0; y<layer->h; y++) {
|
||||
int sy = (y*y_ratio)>>16;
|
||||
for (int x=0; x<layer->w; x++, i+=3) {
|
||||
int sx = (x*x_ratio)>>16;
|
||||
uint16_t p = IM_GET_RGB565_PIXEL(img, sx, sy);
|
||||
input_data[i+0] = (int8_t) (((int) COLOR_RGB565_TO_R8(p)) - (int) data_layer->r_mean);
|
||||
input_data[i+1] = (int8_t) (((int) COLOR_RGB565_TO_G8(p)) - (int) data_layer->g_mean);
|
||||
input_data[i+2] = (int8_t) (((int) COLOR_RGB565_TO_B8(p)) - (int) data_layer->b_mean);
|
||||
}
|
||||
}
|
||||
// Set image data as input buffer for the next layer.
|
||||
input_buffer = input_data;
|
||||
output_buffer = buffer1;
|
||||
break;
|
||||
}
|
||||
|
||||
case LAYER_TYPE_CONV: {
|
||||
conv_func_t conv_func = NULL;
|
||||
conv_layer_t *conv_layer = (conv_layer_t *) layer;
|
||||
if (prev_layer->c % 4 != 0 ||
|
||||
conv_layer->n % 2 != 0 || prev_layer->h % 2 != 0) {
|
||||
conv_func = arm_convolve_HWC_q7_basic;
|
||||
if (prev_layer->c == 3) {
|
||||
conv_func = arm_convolve_HWC_q7_RGB;
|
||||
}
|
||||
} else {
|
||||
conv_func = arm_convolve_HWC_q7_fast;
|
||||
}
|
||||
printf("forward: %s(%s, %lu, %lu, %s, %lu, %lu, %lu, %lu, %s, %lu, %lu, %s, %lu, %s, %p);\n",
|
||||
CONV_FUNC_2STR(conv_func), BUFFER_2STR(input_buffer),
|
||||
prev_layer->h, prev_layer->c, "conv_wt", conv_layer->c,
|
||||
conv_layer->krn_dim, conv_layer->krn_pad, conv_layer->krn_str,
|
||||
"conv_bias", conv_layer->l_shift, conv_layer->r_shift,
|
||||
BUFFER_2STR(output_buffer), conv_layer->h, "col_buffer", NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
case LAYER_TYPE_RELU: {
|
||||
relu_layer_t *relu_layer = (relu_layer_t *) layer;
|
||||
printf("forward: arm_relu_q7(%s, %lu*%lu*%lu);\n",
|
||||
BUFFER_2STR(input_buffer), relu_layer->h, relu_layer->w, relu_layer->c);
|
||||
break;
|
||||
}
|
||||
|
||||
case LAYER_TYPE_POOL: {
|
||||
pool_func_t pool_func = NULL;
|
||||
pool_layer_t *pool_layer = (pool_layer_t *) layer;
|
||||
if (pool_layer->ptype == POOL_TYPE_MAX) {
|
||||
pool_func = arm_maxpool_q7_HWC;
|
||||
} else {
|
||||
pool_func = arm_avepool_q7_HWC;
|
||||
}
|
||||
printf("forward: %s(%s, %lu, %lu, %lu, %lu, %lu, %lu, %s, %s);\n",
|
||||
POOL_FUNC_2STR(pool_func), BUFFER_2STR(input_buffer),
|
||||
prev_layer->h, prev_layer->c, pool_layer->krn_dim,
|
||||
pool_layer->krn_pad, pool_layer->krn_str, layer->w, "col_buffer", BUFFER_2STR(output_buffer));
|
||||
break;
|
||||
}
|
||||
|
||||
case LAYER_TYPE_IP: {
|
||||
ip_layer_t *ip_layer = (ip_layer_t*) layer;
|
||||
printf("forward: arm_fully_connected_q7_opt(%s, %s, %lu, %lu, %lu, %lu, %s, %s, %s);\n",
|
||||
BUFFER_2STR(input_buffer), "ip_wt", prev_layer->c * prev_layer->h * prev_layer->w,
|
||||
ip_layer->c, ip_layer->l_shift, ip_layer->r_shift, "ip_bias", BUFFER_2STR(output_buffer), "col_buffer");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (layer_idx++ > 0) {
|
||||
if (input_buffer == input_data) {
|
||||
// Image data has been processed
|
||||
@ -418,7 +528,7 @@ int nn_run_network(nn_t *net, image_t *img, int8_t *output_data)
|
||||
}
|
||||
|
||||
fb_free_all();
|
||||
debug_printf("\n");
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
#endif //IMLIB_ENABLE_CNN
|
||||
|
||||
@ -98,4 +98,5 @@ typedef void (*pool_func_t)(q7_t * Im_in, const uint16_t dim_im_in, const uint16
|
||||
int nn_dump_network(nn_t *net);
|
||||
int nn_load_network(nn_t *net, const char *path);
|
||||
int nn_run_network(nn_t *net, image_t *img, int8_t *output);
|
||||
int nn_dry_run_network(nn_t *net, image_t *img, int8_t *output);
|
||||
#endif //#define __CNN_H__
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include "py_helper.h"
|
||||
#include "py_assert.h"
|
||||
#include "omv_boardconfig.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
static const mp_obj_type_t py_net_type;
|
||||
|
||||
@ -30,16 +31,22 @@ void *py_net_cobj(mp_obj_t net)
|
||||
|
||||
STATIC mp_obj_t py_net_forward(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
||||
{
|
||||
int8_t output_data[10];
|
||||
nn_t *net = py_net_cobj(args[0]);
|
||||
image_t *img = py_helper_arg_to_image_mutable(args[1]);
|
||||
nn_run_network(net, img, output_data);
|
||||
|
||||
int8_t output_data[10]; //TODO alloc output buffer
|
||||
mp_obj_t output_list = mp_obj_new_list(0, NULL);
|
||||
bool dry_run = py_helper_keyword_int(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_dry_run), false);
|
||||
|
||||
if (dry_run == false) {
|
||||
nn_run_network(net, img, output_data);
|
||||
} else {
|
||||
nn_dry_run_network(net, img, output_data);
|
||||
}
|
||||
|
||||
for (int i=0; i<10; i++) {
|
||||
mp_obj_list_append(output_list, mp_obj_new_int(output_data[i]));
|
||||
}
|
||||
|
||||
return output_list;
|
||||
}
|
||||
|
||||
|
||||
@ -139,6 +139,7 @@ Q(load)
|
||||
// Net
|
||||
Q(Net)
|
||||
Q(forward)
|
||||
Q(dry_run)
|
||||
|
||||
// C/SIF Resolutions
|
||||
Q(QQCIF)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user