97 lines
3.5 KiB
C
97 lines
3.5 KiB
C
#include "onnx.h"
|
|
|
|
void maxpool(const int *input,
|
|
const uint16_t dim_im_in_x, // input image dimension x or W
|
|
const uint16_t dim_im_in_y, // input image dimension y or H
|
|
const uint16_t ch_im_in, // number of input image channels
|
|
const uint16_t dim_kernel_x, // window kernel size
|
|
const uint16_t dim_kernel_y, // window kernel size
|
|
const uint16_t padding_x, // padding sizes
|
|
const uint16_t padding_y, // padding sizes
|
|
const uint16_t stride_x, // stride
|
|
const uint16_t stride_y, // stride
|
|
const uint16_t dim_im_out_x, // output image dimension x or W
|
|
const uint16_t dim_im_out_y, // output image dimension y or H
|
|
int *output)
|
|
{
|
|
int16_t i_ch_in, i_x, i_y;
|
|
int16_t k_x, k_y;
|
|
|
|
for (i_ch_in = 0; i_ch_in < ch_im_in; i_ch_in++)
|
|
{
|
|
for (i_y = 0; i_y < dim_im_out_y; i_y++)
|
|
{
|
|
for (i_x = 0; i_x < dim_im_out_x; i_x++)
|
|
{
|
|
//int max = FLT_MIN;
|
|
int max = 0;
|
|
for (k_y = i_y * stride_y - padding_y; k_y < i_y * stride_y - padding_y + dim_kernel_y; k_y++)
|
|
{
|
|
for (k_x = i_x * stride_x - padding_x; k_x < i_x * stride_x - padding_x + dim_kernel_x; k_x++)
|
|
{
|
|
if (k_y >= 0 && k_x >= 0 && k_y < dim_im_in_y && k_x < dim_im_in_x)
|
|
{
|
|
if (input[i_ch_in + ch_im_in * (k_x + k_y * dim_im_in_x)] > max)
|
|
{
|
|
max = input[i_ch_in + ch_im_in * (k_x + k_y * dim_im_in_x)];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
output[i_ch_in + ch_im_in * (i_x + i_y * dim_im_out_x)] = max;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int* maxpool_layer(Onnx__GraphProto* graph, int* input, int64_t* shapeInput, int64_t* shapeOutput, const char* layer_name)
|
|
{
|
|
//assert(graph != NULL && input != NULL && layer_name != "" );
|
|
|
|
Onnx__NodeProto* node = onnx_graph_get_node_by_name(graph, layer_name);
|
|
if(node == NULL)
|
|
{
|
|
// layer not found
|
|
return NULL;
|
|
}
|
|
|
|
uint16_t kernel_x = 1;
|
|
uint16_t kernel_y = 1;
|
|
uint16_t padding_x = 0;
|
|
uint16_t padding_y = 0;
|
|
uint16_t stride_x = 1;
|
|
uint16_t stride_y = 1;
|
|
|
|
for(int i = 0; i < node->n_attribute; i++)
|
|
{
|
|
if( strcmp(node->attribute[i]->name, "kernel_shape") == 0 )
|
|
{
|
|
kernel_x = node->attribute[i]->ints[0];
|
|
kernel_y = node->attribute[i]->ints[1];
|
|
}
|
|
if( strcmp(node->attribute[i]->name, "strides") == 0 )
|
|
{
|
|
stride_x = node->attribute[i]->ints[0];
|
|
stride_y = node->attribute[i]->ints[1];
|
|
}
|
|
}
|
|
|
|
uint16_t out_x = (shapeInput[W_INDEX] - kernel_x + 2 * padding_x) / stride_x + 1;
|
|
uint16_t out_y = (shapeInput[H_INDEX] - kernel_y + 2 * padding_y) / stride_y + 1;
|
|
|
|
int* output = (int*) malloc(sizeof(int)*out_x*out_y*shapeInput[C_INDEX]);
|
|
if(output == NULL)
|
|
{
|
|
// No memory
|
|
return NULL;
|
|
}
|
|
memset(output, 0, sizeof(sizeof(int)*out_x*out_y*shapeInput[C_INDEX]));
|
|
maxpool(input, shapeInput[W_INDEX], shapeInput[H_INDEX], shapeInput[C_INDEX], kernel_x, kernel_y, padding_x, padding_y, stride_x, stride_y, out_x, out_y, output);
|
|
|
|
shapeOutput[W_INDEX] = out_x;
|
|
shapeOutput[H_INDEX] = out_y;
|
|
shapeOutput[C_INDEX] = shapeInput[C_INDEX];
|
|
|
|
return output;
|
|
}
|