[ESP32]:TFLite Micro推理CIFAR10模型

server/2024/9/24 8:05:33/

[ESP32]:TFLite Micro推理CIFAR10模型

模型训练

数据集处理

from keras.datasets import cifar10
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential, load_model, Model
from keras.layers import Input, Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D, GlobalAveragePooling2D
import pandas as pd
import matplotlib.pyplot as plt
import time, pickle
from keras.utils import to_categorical
from keras import layers
import tensorflow as tf
from tensorflow.keras.callbacks import EarlyStopping(x_train, y_train), (x_test, y_test) = cifar10.load_data()y_train = y_train.reshape(y_train.shape[0])
y_test = y_test.reshape(y_test.shape[0])print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'training samples')
print(x_test.shape[0], 'validation samples')x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255y_train = to_categorical(y_train, 10)
y_test = to_categorical(y_test, 10)

模型搭建

def build_model():model = tf.keras.Sequential()model.add(layers.Conv2D(32, kernel_size=(4,4), strides=1,activation='relu', input_shape=(32, 32, 3)))model.add(layers.MaxPooling2D((2, 2)))model.add(layers.Conv2D(32, kernel_size=(4,4), strides=1,activation='relu'))model.add(layers.MaxPooling2D((2, 2)))model.add(layers.Flatten())model.add(layers.Dense(256, activation='relu'))model.add(layers.Dense(10, activation='softmax'))print(model.summary())return modelmodel=build_model()

tflite模型转换


converter = tf.lite.TFLiteConverter.from_keras_model(model)
tflite_model = converter.convert()
open("cifar10.tflite", "wb").write(tflite_model)

ESP32推理

本文采用的是2DCNN,添加所需的op算子即可

static tflite::MicroMutableOpResolver<5> resolver;
// 这里需要添加我们模型使用的层
if (resolver.AddReshape() != kTfLiteOk)
{ESP_LOGI(TAG, "Add reshape failed");return;
}if (resolver.AddConv2D() != kTfLiteOk)
{ESP_LOGI(TAG, "Add reshape failed");return;
}if (resolver.AddMaxPool2D() != kTfLiteOk)
{ESP_LOGI(TAG, "Add reshape failed");return;
}if (resolver.AddFullyConnected() != kTfLiteOk)
{ESP_LOGI(TAG, "Add reshape failed");return;
}if (resolver.AddSoftmax() != kTfLiteOk)
{ESP_LOGI(TAG, "Add reshape failed");return;
}

推理方案1:PC端JPG图片转换为数组

每一个像素点都有RGB三个数值,依次排开即可,以下为python的一段实例

from PIL import Image
import numpy as npdef image_to_c_array(image_path):# 读取图片image = Image.open(image_path)print(image.size)# 转换为numpy数组image_array = np.array(image)# 归一化# normalized_image_array = image_array / 255.0print(image_array.size)x_array_flatten = image_array.flatten()print(len(x_array_flatten))c_array_string = "{" + ", ".join(str(pixel) for pixel in x_array_flatten) + "}"with open("image_array.h", "w") as f:f.write("#ifndef IMAGE_ARRAY_H\n")f.write("#define IMAGE_ARRAY_H\n\n")f.write("const float image_array[] = %s;\n" % c_array_string)f.write("#endif\n")# 调用函数生成.h文件
image_to_c_array("0042.jpg")

在这里插入图片描述

这样,我们可以直接将这个数组作为模型的输入去推理,记得归一化,除以255。

推理方案2:esp_jpeg解码jpg

size_t pic_buf_size = 32 * 32 * sizeof(uint32_t);uint8_t *pic_buf = (uint8_t *)heap_caps_malloc(pic_buf_size + 1, MALLOC_CAP_SPIRAM); // create out image bufferesp_jpeg_image_cfg_t jpeg_cfg = {.indata = (uint8_t *)file_buf,.indata_size = filesize,.outbuf = (uint8_t *)pic_buf,.outbuf_size = pic_buf_size,.out_format = JPEG_IMAGE_FORMAT_RGB888,.out_scale = JPEG_IMAGE_SCALE_0,};// // decode jpgesp_jpeg_image_output_t outimage;esp_jpeg_decode(&jpeg_cfg, &outimage);ESP_LOGI(TAG, "%s size: %d x %d", filename, outimage.width, outimage.height);

和上面python版本的一样,解码出来的pic_buf存放的也是每一个的像素,类似于这样

pic_buf[]= {像素0的R,像素0的G,像素0的B,像素1的R....}

所以在输入网络的时候,pic_buf的长度一定是图像宽图像高3,其中3为RGB,包括解码的时候选择RGB888

推理端的代码,记得归一化。

void cifar10_model_predict(const uint8_t *pic, int size)
{for (int i = 0; i < size; i++){input->data.f[i] = pic[i] / 255.0f;}TfLiteStatus invoke_status = interpreter->Invoke();if (invoke_status != kTfLiteOk){MicroPrintf("Invoke failed on");return;}for (int i = 0; i < 10; i++){printf("%.2f ", output->data.f[i]);}printf("\n");
}
LiteOk){MicroPrintf("Invoke failed on");return;}for (int i = 0; i < 10; i++){printf("%.2f ", output->data.f[i]);}printf("\n");
}

可以看到推理结果还是挺不错的。
在这里插入图片描述


http://www.ppmy.cn/server/20344.html

相关文章

C语言——数据在内存中的存储

大家好&#xff0c;今天和大家来聊一聊数据是如何在内存中存储的&#xff0c;大家记得三连支持一下哦&#xff01; 一、整数在内存中的存储 整数在内存中的存储&#xff0c;其实在操作符一期文章中我们就已经说过了.即&#xff1a; 1.整数的2进制表⽰⽅法有三种&#xff0c;即…

无人机+功能吊舱:SAR(合成孔径雷达)技术详解

SAR&#xff08;Synthetic Aperture Radar&#xff0c;合成孔径雷达&#xff09;是一种主动式的对地观测系统&#xff0c;它利用合成孔径原理、脉冲压缩技术和信号处理技术&#xff0c;获得方位向的高分辨率。SAR的工作波长较长&#xff0c;因此不易受云雾和光照条件的影响&…

学习OpenCV——CV_16S的常用场合(二)

学习OpenCV——CV_16S的常用场合&#xff08;二&#xff09; 说明主要使用场合总结 说明 在OpenCV中&#xff0c;CV_16S 是一种数据类型定义&#xff0c;它表示一个16位有符号整数型&#xff08;16-bit signed integer&#xff09;。 主要使用场合 OpenCV使用这种数据类型来…

xLua详解

目录 环境准备xLua导入 C#调用LuaLua解析器Lua文件加载重定向Lua解析管理器全局变量的获取全局函数的获取List和Dictionary映射table类映射table接口映射tableLuaTable映射table Lua调用C#准备工作Lua使用C#类Lua调用C#枚举Lua使用C# 数组 List 字典数组List字典 Lua使用C#扩展…

邮票,快递柜和硬件卸载

昨天跑步时捡到一套邮票&#xff0c;很久不再用到的古老玩意儿&#xff0c;记得上大学那会儿每周都要去学校的邮局买很多邮票… 为什么会有邮票&#xff0c;为了证明已经为这次邮寄服务支付过邮资&#xff0c;那为什么不能邮局现场支付货币呢&#xff0c;非要搞这么麻烦个邮票。…

PeLK: 大卷积核强势回归,高达101 × 101,提出了外围卷积

paper&#xff1a;https://arxiv.org/pdf/2403.07589 code&#xff1a;暂无 目录 0. 摘要 1. 引言 2. 相关工作 2.1. Large Kernel Convolutional Networks 2.2. Peripheral Vision for Machine Learning 3. 密集卷积优于条纹卷积 4. 参数高效的大核卷积神经网络 4.1. …

PotatoPie 4.0 实验教程(29) —— FPGA实现摄像头图像均值滤波处理

图像的均值滤波简介 图像均值滤波处理是一种常见的图像处理技术&#xff0c;用于降低图像中噪声的影响并平滑图像。该方法通过在图像中滑动一个固定大小的窗口&#xff08;通常是一个正方形或矩形&#xff09;&#xff0c;将窗口中所有像素的值取平均来计算窗口中心像素的新值…

MySQL商城数据表(30-39)

30商品规格表 CREATE TABLE xuge_goods_specs (id int(11) NOT NULL AUTO_INCREMENT COMMENT 自增id,shopId int(11) NOT NULL DEFAULT 0 COMMENT 店铺id,goodsId int(11) NOT NULL DEFAULT 0 COMMENT 商品id,productNo varchar(20) NOT NULL COMMENT 商品货号,speclds varcha…