30 #include <tensorflow/c/c_api.h>
49 unsigned char *graph_data =
NULL;
51 long size, bytes_read;
64 bytes_read =
avio_read(model_file_context, graph_data, size);
66 if (bytes_read != size){
71 graph_buf = TF_NewBuffer();
72 graph_buf->data = (
void *)graph_data;
73 graph_buf->length =
size;
83 TF_SessionOptions *sess_opts;
84 const TF_Operation *init_op = TF_GraphOperationByName(tf_model->
graph,
"init");
85 TF_Tensor *output_tensor;
88 tf_model->
input.oper = TF_GraphOperationByName(tf_model->
graph,
"x");
89 if (!tf_model->
input.oper){
92 tf_model->
input.index = 0;
96 tf_model->
input_tensor = TF_AllocateTensor(TF_FLOAT, input_dims, 4,
97 input_dims[1] * input_dims[2] * input_dims[3] *
sizeof(
float));
104 tf_model->
output.oper = TF_GraphOperationByName(tf_model->
graph,
"y");
105 if (!tf_model->
output.oper){
108 tf_model->
output.index = 0;
115 sess_opts = TF_NewSessionOptions();
117 TF_DeleteSessionOptions(sess_opts);
118 if (TF_GetCode(tf_model->
status) != TF_OK)
129 if (TF_GetCode(tf_model->
status) != TF_OK)
138 &tf_model->
output, &output_tensor, 1,
140 if (TF_GetCode(tf_model->
status) != TF_OK){
144 output->
height = TF_Dim(output_tensor, 1);
145 output->
width = TF_Dim(output_tensor, 2);
146 output->
channels = TF_Dim(output_tensor, 3);
152 TF_DeleteTensor(output_tensor);
160 TF_Buffer *graph_def;
161 TF_ImportGraphDefOptions *graph_opts;
167 tf_model->
graph = TF_NewGraph();
168 tf_model->
status = TF_NewStatus();
169 graph_opts = TF_NewImportGraphDefOptions();
170 TF_GraphImportGraphDef(tf_model->
graph, graph_def, graph_opts, tf_model->
status);
171 TF_DeleteImportGraphDefOptions(graph_opts);
172 TF_DeleteBuffer(graph_def);
173 if (TF_GetCode(tf_model->
status) != TF_OK){
174 TF_DeleteGraph(tf_model->
graph);
175 TF_DeleteStatus(tf_model->
status);
182 #define NAME_BUFFER_SIZE 256
188 TF_OperationDescription *op_desc;
190 int64_t strides[] = {1, 1, 1, 1};
201 op_desc = TF_NewOperation(tf_model->
graph,
"Const", name_buffer);
202 TF_SetAttrType(op_desc,
"dtype", TF_FLOAT);
208 tensor = TF_AllocateTensor(TF_FLOAT, dims, dims_len, size *
sizeof(
float));
209 memcpy(TF_TensorData(tensor), params->
kernel, size *
sizeof(
float));
210 TF_SetAttrTensor(op_desc,
"value", tensor, tf_model->
status);
211 if (TF_GetCode(tf_model->
status) != TF_OK){
214 op = TF_FinishOperation(op_desc, tf_model->
status);
215 if (TF_GetCode(tf_model->
status) != TF_OK){
220 op_desc = TF_NewOperation(tf_model->
graph,
"Transpose", name_buffer);
222 TF_AddInput(op_desc, input);
223 input.oper = transpose_op;
224 TF_AddInput(op_desc, input);
225 TF_SetAttrType(op_desc,
"T", TF_FLOAT);
226 TF_SetAttrType(op_desc,
"Tperm", TF_INT32);
227 op = TF_FinishOperation(op_desc, tf_model->
status);
228 if (TF_GetCode(tf_model->
status) != TF_OK){
233 op_desc = TF_NewOperation(tf_model->
graph,
"Conv2D", name_buffer);
234 input.oper = *cur_op;
235 TF_AddInput(op_desc, input);
237 TF_AddInput(op_desc, input);
238 TF_SetAttrType(op_desc,
"T", TF_FLOAT);
239 TF_SetAttrIntList(op_desc,
"strides", strides, 4);
240 TF_SetAttrString(op_desc,
"padding",
"VALID", 5);
241 *cur_op = TF_FinishOperation(op_desc, tf_model->
status);
242 if (TF_GetCode(tf_model->
status) != TF_OK){
247 op_desc = TF_NewOperation(tf_model->
graph,
"Const", name_buffer);
248 TF_SetAttrType(op_desc,
"dtype", TF_FLOAT);
251 tensor = TF_AllocateTensor(TF_FLOAT, dims, dims_len, params->
output_num *
sizeof(
float));
252 memcpy(TF_TensorData(tensor), params->
biases, params->
output_num *
sizeof(
float));
253 TF_SetAttrTensor(op_desc,
"value", tensor, tf_model->
status);
254 if (TF_GetCode(tf_model->
status) != TF_OK){
257 op = TF_FinishOperation(op_desc, tf_model->
status);
258 if (TF_GetCode(tf_model->
status) != TF_OK){
263 op_desc = TF_NewOperation(tf_model->
graph,
"BiasAdd", name_buffer);
264 input.oper = *cur_op;
265 TF_AddInput(op_desc, input);
267 TF_AddInput(op_desc, input);
268 TF_SetAttrType(op_desc,
"T", TF_FLOAT);
269 *cur_op = TF_FinishOperation(op_desc, tf_model->
status);
270 if (TF_GetCode(tf_model->
status) != TF_OK){
277 op_desc = TF_NewOperation(tf_model->
graph,
"Relu", name_buffer);
280 op_desc = TF_NewOperation(tf_model->
graph,
"Tanh", name_buffer);
283 op_desc = TF_NewOperation(tf_model->
graph,
"Sigmoid", name_buffer);
288 input.oper = *cur_op;
289 TF_AddInput(op_desc, input);
290 TF_SetAttrType(op_desc,
"T", TF_FLOAT);
291 *cur_op = TF_FinishOperation(op_desc, tf_model->
status);
292 if (TF_GetCode(tf_model->
status) != TF_OK){
302 TF_OperationDescription *op_desc;
307 op_desc = TF_NewOperation(tf_model->
graph,
"DepthToSpace", name_buffer);
308 input.oper = *cur_op;
310 TF_AddInput(op_desc, input);
311 TF_SetAttrType(op_desc,
"T", TF_FLOAT);
312 TF_SetAttrInt(op_desc,
"block_size", params->
block_size);
313 *cur_op = TF_FinishOperation(op_desc, tf_model->
status);
314 if (TF_GetCode(tf_model->
status) != TF_OK){
327 for (layer = 0; layer < conv_network->
layers_num; ++layer){
341 TF_OperationDescription *op_desc;
344 int64_t pads_shape[] = {4, 2};
348 op_desc = TF_NewOperation(tf_model->
graph,
"Const",
"pads");
349 TF_SetAttrType(op_desc,
"dtype", TF_INT32);
350 tensor = TF_AllocateTensor(TF_INT32, pads_shape, 2, 4 * 2 *
sizeof(
int32_t));
351 pads = (
int32_t *)TF_TensorData(tensor);
352 pads[0] = 0; pads[1] = 0;
353 pads[2] = pad; pads[3] = pad;
354 pads[4] = pad; pads[5] = pad;
355 pads[6] = 0; pads[7] = 0;
356 TF_SetAttrTensor(op_desc,
"value", tensor, tf_model->
status);
357 if (TF_GetCode(tf_model->
status) != TF_OK){
360 op = TF_FinishOperation(op_desc, tf_model->
status);
361 if (TF_GetCode(tf_model->
status) != TF_OK){
365 op_desc = TF_NewOperation(tf_model->
graph,
"MirrorPad",
"mirror_pad");
366 input.oper = *cur_op;
367 TF_AddInput(op_desc, input);
369 TF_AddInput(op_desc, input);
370 TF_SetAttrType(op_desc,
"T", TF_FLOAT);
371 TF_SetAttrType(op_desc,
"Tpaddings", TF_INT32);
372 TF_SetAttrString(op_desc,
"mode",
"SYMMETRIC", 9);
373 *cur_op = TF_FinishOperation(op_desc, tf_model->
status);
374 if (TF_GetCode(tf_model->
status) != TF_OK){
384 TF_OperationDescription *op_desc;
386 TF_Operation *transpose_op;
390 int64_t transpose_perm_shape[] = {4};
391 int64_t input_shape[] = {1, -1, -1, -1};
404 tf_model->
graph = TF_NewGraph();
405 tf_model->
status = TF_NewStatus();
407 #define CLEANUP_ON_ERROR(tf_model) \
409 TF_DeleteGraph(tf_model->graph); \
410 TF_DeleteStatus(tf_model->status); \
414 op_desc = TF_NewOperation(tf_model->
graph,
"Placeholder",
"x");
415 TF_SetAttrType(op_desc,
"dtype", TF_FLOAT);
416 TF_SetAttrShape(op_desc,
"shape", input_shape, 4);
417 op = TF_FinishOperation(op_desc, tf_model->
status);
418 if (TF_GetCode(tf_model->
status) != TF_OK){
426 op_desc = TF_NewOperation(tf_model->
graph,
"Const",
"transpose_perm");
427 TF_SetAttrType(op_desc,
"dtype", TF_INT32);
428 tensor = TF_AllocateTensor(TF_INT32, transpose_perm_shape, 1, 4 *
sizeof(
int32_t));
429 transpose_perm = (
int32_t *)TF_TensorData(tensor);
430 transpose_perm[0] = 1;
431 transpose_perm[1] = 2;
432 transpose_perm[2] = 3;
433 transpose_perm[3] = 0;
434 TF_SetAttrTensor(op_desc,
"value", tensor, tf_model->
status);
435 if (TF_GetCode(tf_model->
status) != TF_OK){
438 transpose_op = TF_FinishOperation(op_desc, tf_model->
status);
440 for (layer = 0; layer < conv_network->
layers_num; ++layer){
461 op_desc = TF_NewOperation(tf_model->
graph,
"Identity",
"y");
463 TF_AddInput(op_desc, input);
464 TF_FinishOperation(op_desc, tf_model->
status);
465 if (TF_GetCode(tf_model->
status) != TF_OK){
502 model->
model = (
void *)tf_model;
513 TF_Tensor *output_tensor;
517 &tf_model->
output, &output_tensor, 1,
520 if (TF_GetCode(tf_model->
status) != TF_OK){
527 TF_DeleteTensor(output_tensor);
538 tf_model = (
TFModel *)(*model)->model;
540 TF_DeleteGraph(tf_model->
graph);
547 TF_DeleteStatus(tf_model->
status);
int avio_open(AVIOContext **s, const char *url, int flags)
Create and initialize a AVIOContext for accessing the resource indicated by url.
int64_t avio_size(AVIOContext *s)
Get the filesize.
ptrdiff_t const GLvoid * data
static TF_Buffer * read_graph(const char *model_filename)
DNNActivationFunc activation
DNN inference functions interface for native backend.
#define AVIO_FLAG_READ
read-only
DNNModel * ff_dnn_load_model_tf(const char *model_filename)
DNNReturnType(* set_input_output)(void *model, DNNData *input, DNNData *output)
DNN inference functions interface for TensorFlow backend.
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
static DNNReturnType load_tf_model(TFModel *tf_model, const char *model_filename)
static DNNReturnType load_native_model(TFModel *tf_model, const char *model_filename)
static int calculate_pad(const ConvolutionalNetwork *conv_network)
void ff_dnn_free_model_native(DNNModel **model)
DNNReturnType ff_dnn_execute_model_tf(const DNNModel *model)
static DNNReturnType add_conv_layer(TFModel *tf_model, TF_Operation *transpose_op, TF_Operation **cur_op, ConvolutionalParams *params, const int layer)
static void free_buffer(void *data, size_t length)
static DNNReturnType add_depth_to_space_layer(TFModel *tf_model, TF_Operation **cur_op, DepthToSpaceParams *params, const int layer)
static DNNReturnType set_input_output_tf(void *model, DNNData *input, DNNData *output)
static int op(uint8_t **dst, const uint8_t *dst_end, GetByteContext *gb, int pixel, int count, int *x, int width, int linesize)
Perform decode operation.
static DNNReturnType add_pad_op(TFModel *tf_model, TF_Operation **cur_op, const int32_t pad)
void ff_dnn_free_model_tf(DNNModel **model)
static void transpose_perm(int16_t *out, int16_t *in, int num_vect, const uint8_t line_len[2], int length_div)
Interpret the input data as in the following table:
DNNModel * ff_dnn_load_model_native(const char *model_filename)
int avio_closep(AVIOContext **s)
Close the resource accessed by the AVIOContext *s, free it and set the pointer pointing to it to NULL...
#define CLEANUP_ON_ERROR(tf_model)