在上一篇文章【Win10系统编译Tensorflow Lite 2.3为动态链接库tensorflowlite_c.dll】介绍了如何在Windows
平台下编译tflite
为动态链接库tensorflowlite_c.dll
,接下来介绍如何使用tensorflowlite_c.dll
。上一篇文章中我们编译的tflite
库为c
语言接口,即c_api
,在使用过程中,只需下面一条include语句即可:
#include "tensorflow/lite/c/c_api.h"
注意,如果不想亲自动手编译,请直接将上一篇文章拉到最后,直接下载作者已编译好的库即可。
最近看到一个巨牛的人工智能教程,分享一下给大家。教程不仅是零基础,通俗易懂,而且非常风趣幽默,像看小说一样!觉得太牛了,所以分享给大家。平时碎片时间可以当小说看,【点这里可以去膜拜一下大神的“小说”】。
0 准备tflite模型
前往【https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet/README.md】找到如下mobilenet v3
模型下载:
如果无法打开链接或者是无法下载,请到附件中下载。
1 加载模型
封装函数initModel
,传入tflite
模型路径,代码如下:
void initModel(string path ) {
TfLiteModel* model = TfLiteModelCreateFromFile(path.c_str());
TfLiteInterpreterOptions* options = TfLiteInterpreterOptionsCreate();
interpreter = TfLiteInterpreterCreate(model, options);
if (interpreter == nullptr) {
printf("Failed to create interpreter");
cout << (path) << endl;
return ;
}
// Allocate tensor buffers.
if (TfLiteInterpreterAllocateTensors(interpreter) != kTfLiteOk) {
printf("Failed to allocate tensors!");
return ;
}
input_tf = getInputTensorByName(interpreter, "input");
output_tf = getOutputTensorByName(interpreter, "MobilenetV3/Predictions/Softmax");
}
上述代码中,主要使用了如下几个接口:
TfLiteModelCreateFromFile: 创建TfLiteModel对象 TfLiteInterpreterOptionsCreate: 设置一些选项,这里暂时没有设置更多的参数。 TfLiteInterpreterCreate:创建TfLiteInterpreter对象,PS: 这个对象有点Session的感觉。 TfLiteInterpreterAllocateTensors: 为所有的Tensor分配空间,用于向系统请求分配空间。 getOutputTensorByName和getInputTensorByName这两个函数是我这边单独封装。
getOutputTensorByName
和getInputTensorByName
代码如下:
TfLiteTensor * getOutputTensorByName(TfLiteInterpreter * interpreter, const char * name)
{
int count = TfLiteInterpreterGetOutputTensorCount(interpreter);
for (int i = 0; i < count; i) {
TfLiteTensor* ts = (TfLiteTensor*)TfLiteInterpreterGetOutputTensor(interpreter, i);
if (!strcmp(ts->name, name)) {
return ts;
}
}
return nullptr;
}
TfLiteTensor * getInputTensorByName(TfLiteInterpreter * interpreter, const char * name)
{
int count = TfLiteInterpreterGetInputTensorCount(interpreter);
for (int i = 0; i < count; i) {
TfLiteTensor* ts = TfLiteInterpreterGetInputTensor(interpreter, i);
if (!strcmp(ts->name, name)) {
return ts;
}
}
return nullptr;
}
2 前向推理
前向推理主要包括3步:
向输入Tensor拷贝输入数据 执行推理 从输出Tensor将运算结果拷贝出来
示例代码如下:
代码语言:txt复制void forward(float* data, int len) {
TfLiteTensorCopyFromBuffer(input_tf, data, len*sizeof(float));
TfLiteInterpreterInvoke(interpreter);
float logits[1001];
TfLiteTensorCopyToBuffer(output_tf, logits, 1001*sizeof(float));
float maxV = -1;
int maxIdx = -1;
for (int i = 0; i < 1001; i) {
if (logits[i] > maxV) {
maxV = logits[i];
maxIdx = i;
}
//printf("%d->%fn", i, logits[i]);
}
cout << "类别:" << maxIdx << ",概率:" << maxV << endl;
}
上面代码写的比较粗糙,用起来不灵活,但是足够作为一个示例来使用了。
3 完整代码
接下来看完整代码,如下:
代码语言:txt复制#include "pch.h"
#include <map>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include "tensorflow/lite/c/c_api.h"
#pragma comment( lib, "tensorflowlite_c.dll.if.lib" )
using namespace std;
TfLiteTensor* input_tf;
TfLiteTensor* output_tf;
TfLiteInterpreter* interpreter;
TfLiteTensor * getOutputTensorByName(TfLiteInterpreter * interpreter, const char * name)
{
int count = TfLiteInterpreterGetOutputTensorCount(interpreter);
for (int i = 0; i < count; i) {
TfLiteTensor* ts = (TfLiteTensor*)TfLiteInterpreterGetOutputTensor(interpreter, i);
if (!strcmp(ts->name, name)) {
return ts;
}
}
return nullptr;
}
TfLiteTensor * getInputTensorByName(TfLiteInterpreter * interpreter, const char * name)
{
int count = TfLiteInterpreterGetInputTensorCount(interpreter);
for (int i = 0; i < count; i) {
TfLiteTensor* ts = TfLiteInterpreterGetInputTensor(interpreter, i);
if (!strcmp(ts->name, name)) {
return ts;
}
}
return nullptr;
}
void initModel(string path ) {
TfLiteModel* model = TfLiteModelCreateFromFile(path.c_str());
TfLiteInterpreterOptions* options = TfLiteInterpreterOptionsCreate();
interpreter = TfLiteInterpreterCreate(model, options);
if (interpreter == nullptr) {
printf("Failed to create interpreter");
cout << (path) << endl;
return ;
}
// Allocate tensor buffers.
if (TfLiteInterpreterAllocateTensors(interpreter) != kTfLiteOk) {
printf("Failed to allocate tensors!");
return ;
}
input_tf = getInputTensorByName(interpreter, "input");
output_tf = getOutputTensorByName(interpreter, "MobilenetV3/Predictions/Softmax");
}
void forward(float* data, int len) {
TfLiteTensorCopyFromBuffer(input_tf, data, len*sizeof(float));
TfLiteInterpreterInvoke(interpreter);
float logits[1001];
TfLiteTensorCopyToBuffer(output_tf, logits, 1001*sizeof(float));
float maxV = -1;
int maxIdx = -1;
for (int i = 0; i < 1001; i) {
if (logits[i] > maxV) {
maxV = logits[i];
maxIdx = i;
}
//printf("%d->%fn", i, logits[i]);
}
cout << "类别:" << maxIdx << ",概率:" << maxV << endl;
}
long getSize(string path) {
ifstream file(path, ios::in | ios::binary);
long l, m;
l = file.tellg();
file.seekg(0, ios::end);
m = file.tellg();
file.close();
return m - l;
}
float* readBmp(string path, int& len) {
len = getSize(path);
unsigned char* buff = (unsigned char*)calloc(len, sizeof(unsigned char*));
ifstream fin(path, std::ifstream::binary);
fin.read(reinterpret_cast<char*>(buff), len *sizeof(unsigned char*));
fin.close();
float* data = (float*)calloc(len, sizeof(float));
for (int i = 0; i < len; i) {
data[i] = (buff[i]/255.0-0.5)*2;
}
free(buff);
return data;
}
int main()
{
initModel("v3-small_224_0.75_float.tflite" );
int size=0;
float* bmp = readBmp("input.bin", size);
forward(bmp, size );
}
4 运行结果
将下面图片作为输入:
运行上面代码,控制台输出如下:
代码语言:txt复制类别:896,概率:0.92355
这里没有对具体类别转为中文查看,因为作为demo不想再添加其他不太相关的代码(主要是懒)。label文件可以在附件中下载,打开label文件可以看到第896类:
5 附件
mobilenet v3 tflite
模型下载地址:http://askonline.tech/download/4.html- 完整打包下载:http://askonline.tech/download/5.html