update knowing framework and application from Tian_Chunyu

it is perfect
This commit is contained in:
xuedongliang
2021-07-30 09:53:21 +08:00
355 changed files with 99743 additions and 476 deletions
@@ -1,14 +1,3 @@
menu "connection app"
menuconfig APPLICATION_CONNECTION
bool "Using connection apps"
default n
menuconfig CONNECTION_COMMUNICATION_ZIGBEE
bool "enable zigbee demo"
default n
select CONFIG_CONNECTION_COMMUNICATION_ZIGBEE
if CONNECTION_COMMUNICATION_ZIGBEE
source "$KERNEL_DIR/framework/connection/Adapter/zigbee/Kconfig"
endif
endmenu
@@ -1,7 +1,4 @@
menu "knowing app"
menuconfig APPLICATION_KNOWING
bool "Using knowing apps"
default n
source "$APP_DIR/Applications/knowing_app/mnist/Kconfig"
source "$APP_DIR/Applications/knowing_app/face_detect/Kconfig"
endmenu
@@ -0,0 +1,14 @@
import os
Import('RTT_ROOT')
from building import *
cwd = GetCurrentDir()
objs = []
list = os.listdir(cwd)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
objs = objs + SConscript(os.path.join(path, 'SConscript'))
Return('objs')
@@ -0,0 +1,7 @@
config FACE_DETECT
bool "enable apps/face detect"
depends on BOARD_K210_EVB
depends on DRV_USING_OV2640
depends on USING_KPU_POSTPROCESSING
depends on USING_YOLOV2
default n
@@ -0,0 +1,9 @@
from building import *
cwd = GetCurrentDir()
src = Glob('*.c') + Glob('*.cpp')
CPPPATH = [cwd]
group = DefineGroup('Applications', src, depend = ['FACE_DETECT'], LOCAL_CPPPATH = CPPPATH)
Return('group')
@@ -0,0 +1,253 @@
#include <transform.h>
#include"region_layer.h"
#define SHOW_RGB_BUF_SIZE (320*240*2)
#define AI_KPU_RGB_BUF_SIZE (320*240*3)
#define KMODEL_SIZE (388776) //face model size
#define ANCHOR_NUM 5
#define KPUIMAGEWIDTH (320)
#define KPUIMAGEHEIGHT (240)
static float anchor[ANCHOR_NUM * 2] = {1.889,2.5245, 2.9465,3.94056, 3.99987,5.3658, 5.155437,6.92275, 6.718375,9.01025};
#define THREAD_PRIORITY_FACE_D (11)
static pthread_t facetid = 0;
static void* thread_face_detcet_entry(void *parameter);
static int g_fd = 0;
static int kmodel_fd = 0;
static int if_exit = 0;
static unsigned char * showbuffer = NULL ;
static unsigned char * kpurgbbuffer = NULL ;
static _ioctl_shoot_para shoot_para_t = {0};
unsigned char * model_data = NULL; //kpu data load memory
unsigned char *model_data_align = NULL;
kpu_model_context_t face_detect_task;
static region_layer_t face_detect_rl;
static obj_info_t face_detect_info;
volatile uint32_t g_ai_done_flag;
static void ai_done(void *ctx)
{
g_ai_done_flag = 1;
}
void face_detect()
{
int ret = 0;
int result = 0;
int size = 0;
g_fd = open("/dev/ov2640",O_RDONLY);
if(g_fd < 0)
{
printf("open ov2640 fail !!");
return;
}
showbuffer = (unsigned char*)malloc(SHOW_RGB_BUF_SIZE);
if(NULL ==showbuffer)
{
close(g_fd);
printf("showbuffer apply memory fail !!");
return ;
}
kpurgbbuffer = (unsigned char*)malloc(AI_KPU_RGB_BUF_SIZE);
if(NULL ==kpurgbbuffer)
{
close(g_fd);
free(showbuffer);
printf("kpurgbbuffer apply memory fail !!");
return ;
}
model_data = (unsigned char *)malloc(KMODEL_SIZE + 255);
if(NULL ==model_data)
{
free(showbuffer);
free(kpurgbbuffer);
close(g_fd);
printf("model_data apply memory fail !!");
return ;
}
memset(model_data,0,KMODEL_SIZE + 255);
memset(showbuffer,0,SHOW_RGB_BUF_SIZE);
memset(kpurgbbuffer,0,AI_KPU_RGB_BUF_SIZE);
shoot_para_t.pdata = (unsigned int *)(showbuffer);
shoot_para_t.length = SHOW_RGB_BUF_SIZE;
/*
load memory
*/
kmodel_fd = open("/kmodel/detect.kmodel",O_RDONLY);
if(kmodel_fd <0)
{
printf("open kmodel fail");
close(g_fd);
free(showbuffer);
free(kpurgbbuffer);
free(model_data);
return;
}
else
{
size = read(kmodel_fd, model_data, KMODEL_SIZE);
if(size != KMODEL_SIZE)
{
printf("read kmodel error size %d\n",size);
close(g_fd);
close(kmodel_fd);
free(showbuffer);
free(kpurgbbuffer);
free(model_data);
return;
}
else
{
printf("read kmodel success \n");
}
}
unsigned char *model_data_align = (unsigned char *)(((unsigned int)model_data+255)&(~255));
dvp_set_ai_addr((uint32_t)kpurgbbuffer, (uint32_t)(kpurgbbuffer + 320 * 240), (uint32_t)(kpurgbbuffer + 320 * 240 * 2));
if (kpu_load_kmodel(&face_detect_task, model_data_align) != 0)
{
printf("\nmodel init error\n");
close(g_fd);
close(kmodel_fd);
free(showbuffer);
free(kpurgbbuffer);
free(model_data);
return;
}
face_detect_rl.anchor_number = ANCHOR_NUM;
face_detect_rl.anchor = anchor;
face_detect_rl.threshold = 0.7;
face_detect_rl.nms_value = 0.3;
result = region_layer_init(&face_detect_rl, 20, 15, 30, KPUIMAGEWIDTH, KPUIMAGEHEIGHT);
printf("region_layer_init result %d \n\r",result);
size_t stack_size = 32*1024;
pthread_attr_t attr; /* 线程属性 */
struct sched_param prio; /* 线程优先级 */
prio.sched_priority = 8; /* 优先级设置为 8 */
pthread_attr_init(&attr); /* 先使用默认值初始化属性 */
pthread_attr_setschedparam(&attr,&prio); /* 修改属性对应的优先级 */
pthread_attr_setstacksize(&attr, stack_size);
/* 创建线程 1, 属性为 attr,入口函数是 thread_entry,入口函数参数是 1 */
result = pthread_create(&facetid,&attr,thread_face_detcet_entry,NULL);
if (0 == result)
{
printf("thread_face_detcet_entry successfully!\n");
}
else
{
printf("thread_face_detcet_entry failed! error code is %d\n",result);
close(g_fd);
}
}
#ifdef __RT_THREAD_H__
MSH_CMD_EXPORT(face_detect,face detect task);
#endif
static void* thread_face_detcet_entry(void *parameter)
{
extern void lcd_draw_picture(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, uint32_t *ptr);
printf("thread_face_detcet_entry start!\n");
int ret = 0;
//sysctl_enable_irq();
while(1)
{
//memset(showbuffer,0,320*240*2);
g_ai_done_flag = 0;
ret = ioctl(g_fd,IOCTRL_CAMERA_START_SHOT,&shoot_para_t);
if(RT_ERROR == ret)
{
printf("ov2640 can't wait event flag");
rt_free(showbuffer);
close(g_fd);
pthread_exit(NULL);
return NULL;
}
kpu_run_kmodel(&face_detect_task, kpurgbbuffer, DMAC_CHANNEL5, ai_done, NULL);
while(!g_ai_done_flag);
float *output;
size_t output_size;
kpu_get_output(&face_detect_task, 0, (uint8_t **)&output, &output_size);
face_detect_rl.input = output;
region_layer_run(&face_detect_rl, &face_detect_info);
/* display result */
#ifdef BSP_USING_LCD
for (int face_cnt = 0; face_cnt < face_detect_info.obj_number; face_cnt++)
{
draw_edge((uint32_t *)showbuffer, &face_detect_info, face_cnt, 0xF800);
}
lcd_draw_picture(0, 0, 320, 240, (unsigned int*)showbuffer);
#endif
usleep(1);
if(1 == if_exit)
{
if_exit = 0;
printf("thread_face_detcet_entry exit");
pthread_exit(NULL);
}
}
}
void face_detect_delete()
{
if(showbuffer != NULL)
{
int ret = 0;
close(g_fd);
close(kmodel_fd);
free(showbuffer);
free(kpurgbbuffer);
free(model_data);
printf("face detect task cancel!!! ret %d ",ret);
if_exit = 1;
}
}
#ifdef __RT_THREAD_H__
MSH_CMD_EXPORT(face_detect_delete,face detect task delete);
#endif
void kmodel_load(unsigned char * model_data)
{
int kmodel_fd = 0;
int size = 0;
kmodel_fd = open("/kmodel/detect.kmodel",O_RDONLY);
model_data = (unsigned char *)malloc(KMODEL_SIZE + 255);
if(NULL ==model_data)
{
printf("model_data apply memory fail !!");
return ;
}
memset(model_data,0,KMODEL_SIZE + 255);
if (kmodel_fd>= 0)
{
size = read(kmodel_fd, model_data, KMODEL_SIZE);
if(size != KMODEL_SIZE)
{
printf("read kmodel error size %d\n",size);
}
else
{
printf("read kmodel success");
}
}
else
{
free(model_data);
printf("open kmodel fail");
}
}
#ifdef __RT_THREAD_H__
MSH_CMD_EXPORT(kmodel_load,kmodel load memory);
#endif
@@ -0,0 +1,2 @@
*.h5
*.tflite
Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

@@ -0,0 +1,4 @@
config APP_MNIST
bool "enable apps/mnist"
depends on USING_TENSORFLOWLITEMICRO
default n
@@ -0,0 +1,23 @@
# MNIST 说明
要使用本例程,MCU RAM必须至少500K左右,所以本例程目前在K210上面验证过,stm32f407 目前在rtt上原则上只能采取dlmodule加载的方式。
![K210 mnist ](E:\XIUOS_FRAMEWORK\xiuos\APP_Framework\Applications\knowing_app\mnist\K210 mnist .png)
## 使用
tools/mnist-train.py 训练生成 mnist 模型。
tools/mnist-inference.py 使用 mnist 模型进行推理。
tools/mnist-c-model.py 将 mnist 模型转换成 C 的数组保存在 model.h 中。
tools/mnist-c-digit.py 将 mnist 数据集中的某个数字转成数组保存在 digit.h 中。
## 参考资料
https://tensorflow.google.cn/lite/performance/post_training_quantization
https://tensorflow.google.cn/lite/performance/post_training_integer_quant
https://colab.research.google.com/github/tensorflow/tensorflow/blob/master/tensorflow/lite/micro/examples/hello_world/train/train_hello_world_model.ipynb
@@ -0,0 +1,9 @@
from building import *
cwd = GetCurrentDir()
src = Glob('*.c') + Glob('*.cpp')
CPPPATH = [cwd]
group = DefineGroup('Applications', src, depend = ['APP_MNIST'], LOCAL_CPPPATH = CPPPATH)
Return('group')
@@ -0,0 +1,31 @@
const float mnist_digit[] = {
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.33, 0.73, 0.62, 0.59, 0.24, 0.14, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.87, 1.00, 1.00, 1.00, 1.00, 0.95, 0.78, 0.78, 0.78, 0.78, 0.78, 0.78, 0.78, 0.78, 0.67, 0.20, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.26, 0.45, 0.28, 0.45, 0.64, 0.89, 1.00, 0.88, 1.00, 1.00, 1.00, 0.98, 0.90, 1.00, 1.00, 0.55, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.07, 0.26, 0.05, 0.26, 0.26, 0.26, 0.23, 0.08, 0.93, 1.00, 0.42, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.33, 0.99, 0.82, 0.07, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.09, 0.91, 1.00, 0.33, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.51, 1.00, 0.93, 0.17, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.23, 0.98, 1.00, 0.24, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.52, 1.00, 0.73, 0.02, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.04, 0.80, 0.97, 0.23, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.49, 1.00, 0.71, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.29, 0.98, 0.94, 0.22, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.07, 0.87, 1.00, 0.65, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.01, 0.80, 1.00, 0.86, 0.14, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.15, 1.00, 1.00, 0.30, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.12, 0.88, 1.00, 0.45, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.52, 1.00, 1.00, 0.20, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.24, 0.95, 1.00, 1.00, 0.20, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.47, 1.00, 1.00, 0.86, 0.16, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.47, 1.00, 0.81, 0.07, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00
};
const int mnist_label = 7;
@@ -0,0 +1,96 @@
#include <transform.h>
#include <stdio.h>
#include "tensorflow/lite/micro/all_ops_resolver.h"
#include "tensorflow/lite/micro/micro_error_reporter.h"
#include "tensorflow/lite/micro/micro_interpreter.h"
#include "tensorflow/lite/schema/schema_generated.h"
#include "tensorflow/lite/version.h"
#include "digit.h"
#include "model.h"
namespace {
tflite::ErrorReporter* error_reporter = nullptr;
const tflite::Model* model = nullptr;
tflite::MicroInterpreter* interpreter = nullptr;
TfLiteTensor* input = nullptr;
TfLiteTensor* output = nullptr;
constexpr int kTensorArenaSize = 110 * 1024;
uint8_t *tensor_arena = nullptr;
//uint8_t tensor_arena[kTensorArenaSize];
}
extern "C" void mnist_app() {
tflite::MicroErrorReporter micro_error_reporter;
error_reporter = &micro_error_reporter;
model = tflite::GetModel(mnist_model);
if (model->version() != TFLITE_SCHEMA_VERSION) {
TF_LITE_REPORT_ERROR(error_reporter,
"Model provided is schema version %d not equal "
"to supported version %d.",
model->version(), TFLITE_SCHEMA_VERSION);
return;
}
tensor_arena = (uint8_t *)malloc(kTensorArenaSize);
if (tensor_arena == nullptr) {
TF_LITE_REPORT_ERROR(error_reporter, "malloc for tensor_arena failed");
return;
}
tflite::AllOpsResolver resolver;
tflite::MicroInterpreter static_interpreter(
model, resolver, tensor_arena, kTensorArenaSize, error_reporter);
interpreter = &static_interpreter;
// Allocate memory from the tensor_arena for the model's tensors.
TfLiteStatus allocate_status = interpreter->AllocateTensors();
if (allocate_status != kTfLiteOk) {
TF_LITE_REPORT_ERROR(error_reporter, "AllocateTensors() failed");
return;
}
input = interpreter->input(0);
output = interpreter->output(0);
printf("------- Input Digit -------\n");
for (int i = 0; i < 28; i++) {
for (int j = 0; j < 28; j++) {
if (mnist_digit[i*28+j] > 0.3)
printf("#");
else
printf(".");
}
printf("\n");
}
for (int i = 0; i < 28*28; i++) {
input->data.f[i] = mnist_digit[i];
}
TfLiteStatus invoke_status = interpreter->Invoke();
if (invoke_status != kTfLiteOk) {
TF_LITE_REPORT_ERROR(error_reporter, "Invoke failed on x_val\n");
return;
}
// Read the predicted y value from the model's output tensor
float max = 0.0;
int index;
for (int i = 0; i < 10; i++) {
if(output->data.f[i]>max){
max = output->data.f[i];
index = i;
}
}
printf("------- Output Result -------\n");
printf("result is %d\n", index);
}
extern "C" {
#ifdef __RT_THREAD_H__
MSH_CMD_EXPORT(mnist_app, run mnist app);
#endif
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,36 @@
#!/usr/bin/env python3
import tensorflow as tf
print("TensorFlow version %s" % (tf.__version__))
def show(image):
for i in range(28):
for j in range(28):
if image[i][j] > 0.3:
print('#', end = '')
else:
print('.', end = '')
print()
digit_file_path = 'digit.h'
digit_content = '''const float mnist_digit[] = {
%s
};
const int mnist_label = %d;
'''
if __name__ == '__main__':
mnist = tf.keras.datasets.mnist
(_, _), (test_images, test_labels) = mnist.load_data()
index = 0
shape = 28
image = test_images[index].astype('float32')/255
label = test_labels[index]
print('label: %d' % label)
#show(image)
digit_data = (',\n ').join([ (', ').join([ '%.2f' % image[row][col] for col in range(shape)]) for row in range(shape)])
digit_file = open(digit_file_path, 'w')
digit_file.write(digit_content % (digit_data, label))
digit_file.close()
@@ -0,0 +1,23 @@
#!/usr/bin/env python3
#tflite_file_path = 'mnist-default-quan.tflite'
tflite_file_path = 'mnist.tflite'
model_file_path = 'model.h'
tflite_file = open(tflite_file_path, 'rb')
tflite_data = tflite_file.read()
tflite_file.close()
tflite_array = [ '0x%02x' % byte for byte in tflite_data ]
model_content = '''unsigned char mnist_model[] = {
%s
};
unsigned int mnist_model_len = %d;
'''
# 12 bytes in a line, the same with xxd
bytes_of_line = 12
model_data = (',\n ').join([ (', ').join(tflite_array[i:i+bytes_of_line]) for i in range(0, len(tflite_array), bytes_of_line) ])
model_file = open(model_file_path, 'w')
model_file.write(model_content % (model_data, len(tflite_array)))
model_file.close()
@@ -0,0 +1,40 @@
#!/usr/bin/env python3
import tensorflow as tf
print("TensorFlow version %s" % (tf.__version__))
MODEL_NAME_H5 = 'mnist.h5'
MODEL_NAME_TFLITE = 'mnist.tflite'
DEFAULT_QUAN_MODEL_NAME_TFLITE = 'mnist-default-quan.tflite'
FULL_QUAN_MODEL_NAME_TFLITE = 'mnist-full-quan.tflite'
def show(image):
for i in range(28):
for j in range(28):
if image[i][j][0] > 0.3:
print('#', end = '')
else:
print(' ', end = '')
print()
if __name__ == '__main__':
mnist = tf.keras.datasets.mnist
(_, _), (test_images, test_labels) = mnist.load_data()
test_images = test_images.reshape(10000, 28, 28, 1)
index = 0
input_image = test_images[index].astype('float32')/255
target_label = test_labels[index]
interpreter = tf.lite.Interpreter(model_path = DEFAULT_QUAN_MODEL_NAME_TFLITE)
interpreter.allocate_tensors()
input_details = interpreter.get_input_details()[0]
output_details = interpreter.get_output_details()[0]
interpreter.set_tensor(input_details['index'], [input_image])
interpreter.invoke()
output = interpreter.get_tensor(output_details['index'])[0]
show(input_image)
print('target label: %d, predict label: %d' % (target_label, output.argmax()))
@@ -0,0 +1,109 @@
#!/usr/bin/env python3
import os
import tensorflow as tf
print("TensorFlow version %s" % (tf.__version__))
MODEL_NAME_H5 = 'mnist.h5'
MODEL_NAME_TFLITE = 'mnist.tflite'
DEFAULT_QUAN_MODEL_NAME_TFLITE = 'mnist-default-quan.tflite'
FULL_QUAN_MODEL_NAME_TFLITE = 'mnist-full-quan.tflite'
def build_model(model_name):
print('\n>>> load mnist dataset')
mnist = tf.keras.datasets.mnist
(train_images, train_labels),(test_images, test_labels) = mnist.load_data()
print("train images shape: ", train_images.shape)
print("train labels shape: ", train_labels.shape)
print("test images shape: ", test_images.shape)
print("test labels shape: ", test_labels.shape)
# transform label to categorical, like: 2 -> [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
print('\n>>> transform label to categorical')
train_labels = tf.keras.utils.to_categorical(train_labels)
test_labels = tf.keras.utils.to_categorical(test_labels)
print("train labels shape: ", train_labels.shape)
print("test labels shape: ", test_labels.shape)
# transform color like: [0, 255] -> 0.xxx
print('\n>>> transform image color into float32')
train_images = train_images.astype('float32') / 255
test_images = test_images.astype('float32') / 255
# reshape image like: (60000, 28, 28) -> (60000, 28, 28, 1)
print('\n>>> reshape image with color channel')
train_images = train_images.reshape((60000, 28, 28, 1))
test_images = test_images.reshape((10000, 28, 28, 1))
print("train images shape: ", train_images.shape)
print("test images shape: ", test_images.shape)
print('\n>>> build model')
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(32, (3, 3), activation=tf.nn.relu, input_shape=(28, 28, 1)),
tf.keras.layers.MaxPooling2D((2, 2)),
tf.keras.layers.Conv2D(64, (3, 3), activation=tf.nn.relu),
tf.keras.layers.MaxPooling2D((2, 2)),
tf.keras.layers.Conv2D(64, (3, 3), activation=tf.nn.relu),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(64, activation=tf.nn.relu),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
model.summary()
print('\n>>> train the model')
early_stopping = tf.keras.callbacks.EarlyStopping(
monitor='loss', min_delta=0.0005, patience=3, verbose=1, mode='auto',
baseline=None, restore_best_weights=True
)
model.fit(train_images, train_labels, epochs=100, batch_size=64, callbacks=[early_stopping])
print('\n>>> evaluate the model')
test_loss, test_acc = model.evaluate(test_images, test_labels)
print("lost: %f, accuracy: %f" % (test_loss, test_acc))
print('\n>>> save the keras model as %s' % model_name)
model.save(model_name)
if __name__ == '__main__':
if not os.path.exists(MODEL_NAME_H5):
build_model(MODEL_NAME_H5)
if not os.path.exists(MODEL_NAME_TFLITE):
print('\n>>> save the tflite model as %s' % MODEL_NAME_TFLITE)
converter = tf.lite.TFLiteConverter.from_keras_model(tf.keras.models.load_model(MODEL_NAME_H5))
tflite_model = converter.convert()
with open(MODEL_NAME_TFLITE, "wb") as f:
f.write(tflite_model)
if not os.path.exists(DEFAULT_QUAN_MODEL_NAME_TFLITE):
print('\n>>> save the default quantized model as %s' % DEFAULT_QUAN_MODEL_NAME_TFLITE)
converter = tf.lite.TFLiteConverter.from_keras_model(tf.keras.models.load_model(MODEL_NAME_H5))
converter.optimizations = [tf.lite.Optimize.DEFAULT]
tflite_model = converter.convert()
with open(DEFAULT_QUAN_MODEL_NAME_TFLITE, "wb") as f:
f.write(tflite_model)
if not os.path.exists(FULL_QUAN_MODEL_NAME_TFLITE):
mnist = tf.keras.datasets.mnist
(train_images, _), (_, _) = mnist.load_data()
train_images = train_images.astype('float32') / 255
train_images = train_images.reshape((60000, 28, 28, 1))
def representative_data_gen():
for input_value in tf.data.Dataset.from_tensor_slices(train_images).batch(1).take(100):
yield [input_value]
print('\n>>> save the full quantized model as %s' % DEFAULT_QUAN_MODEL_NAME_TFLITE)
converter = tf.lite.TFLiteConverter.from_keras_model(tf.keras.models.load_model(MODEL_NAME_H5))
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.representative_dataset = representative_data_gen
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.uint8
converter.inference_output_type = tf.uint8
tflite_model = converter.convert()
with open(FULL_QUAN_MODEL_NAME_TFLITE, "wb") as f:
f.write(tflite_model)