Browse Source

windows version

master
Yuya Hanai 3 years ago
parent
commit
3ebd08c73d
  1. 18
      README.md
  2. 113
      example-onnx_mnist/src/ofApp.cpp

18
README.md

@ -7,9 +7,23 @@
## Installation
- macOS
- copy `libonnxruntime.1.10.0.dylib` to `/usr/local/lib`
- Generate a project using ProjectGenerator.
- Windows
- There are two ways to install ONNX Runtime on your project.
1. Install using NuGet
- I recommend this way in general.
- Generate a project using ProjectGenerator.
- Open `sln` file.
- Right click your project on `Solution Explorer` pane, and then select `Manage NuGet Packages...`.
- From `Browse` tab, search `Microsoft.ML.OnnxRuntime` (CPU) or `Microsoft.ML.OnnxRuntime.Gpu` (GPU) and install it.
2. DLL direct download
- You can download prebuilt DLLs from (here)[https://github.com/microsoft/onnxruntime/releases].
- Unzip downloaded `onnxruntime-win-x64-(gpu-)1.10.0.zip` and locate files on `libs\onnxruntime\lib\vs\x64\` .
- Generate a project using ProjectGenerator, then all libs are linked correctly and all dlls are copied to `bin`.
## Tested environment
- MacBookPro 2018 Intel + macOS Catalina
- oF 0.11.2 + MacBookPro 2018 Intel + macOS Catalina
- oF 0.11.2 + VS2017 + Windows 10 + RTX2080Ti + CUDA 11.4
## ToDo
- check M1 Mac (should work), Windows CPU&GPU, Linux CPU&GPU
- check M1 Mac (should work), Linux CPU&GPU

113
example-onnx_mnist/src/ofApp.cpp

@ -3,9 +3,8 @@
#include "ofxOnnxRuntime.h"
// code from
//https://github.com/microsoft/onnxruntime-inference-examples/blob/main/c_cxx/MNIST/MNIST.cpp
template <typename T>
static void softmax(T& input) {
// https://github.com/microsoft/onnxruntime-inference-examples/blob/main/c_cxx/MNIST/MNIST.cpp
template <typename T> static void softmax(T &input) {
float rowmax = *std::max_element(input.begin(), input.end());
std::vector<float> y(input.size());
float sum = 0.0f;
@ -18,23 +17,55 @@ static void softmax(T& input) {
}
// This is the structure to interface with the MNIST model
// After instantiation, set the input_image_ data to be the 28x28 pixel image of the number to recognize
// Then call Run() to fill in the results_ data with the probabilities of each
// result_ holds the index with highest probability (aka the number the model thinks is in the image)
// After instantiation, set the input_image_ data to be the 28x28 pixel image of
// the number to recognize Then call Run() to fill in the results_ data with the
// probabilities of each result_ holds the index with highest probability (aka
// the number the model thinks is in the image)
struct MNIST {
MNIST() {
auto memory_info = Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU);
input_tensor_ = Ort::Value::CreateTensor<float>(memory_info, input_image_.data(), input_image_.size(), input_shape_.data(), input_shape_.size());
output_tensor_ = Ort::Value::CreateTensor<float>(memory_info, results_.data(), results_.size(), output_shape_.data(), output_shape_.size());
#ifdef _MSC_VER
Ort::SessionOptions sf;
#define USE_CUDA
#define USE_TENSORRT
#ifdef USE_CUDA
#ifdef USE_TENSORRT
sf.AppendExecutionProvider_TensorRT(OrtTensorRTProviderOptions{ 0 });
#endif
sf.AppendExecutionProvider_CUDA(OrtCUDAProviderOptions());
#endif
string path = ofToDataPath("mnist-8.onnx", true);
std::wstring widestr = std::wstring(path.begin(), path.end());
session_ = make_shared<Ort::Session>(env, widestr.c_str(), sf);
#else
// OSX
session_ = make_shared<Ort::Session>(
env, ofToDataPath("mnist-8.onnx", true).c_str(),
Ort::SessionOptions{ nullptr });
#endif
auto memory_info =
Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU);
input_tensor_ = Ort::Value::CreateTensor<float>(
memory_info, input_image_.data(), input_image_.size(),
input_shape_.data(), input_shape_.size());
output_tensor_ = Ort::Value::CreateTensor<float>(
memory_info, results_.data(), results_.size(), output_shape_.data(),
output_shape_.size());
}
std::ptrdiff_t Run() {
const char* input_names[] = {"Input3"};
const char* output_names[] = {"Plus214_Output_0"};
const char *input_names[] = { "Input3" };
const char *output_names[] = { "Plus214_Output_0" };
session_.Run(Ort::RunOptions{nullptr}, input_names, &input_tensor_, 1, output_names, &output_tensor_, 1);
session_->Run(Ort::RunOptions{ nullptr }, input_names, &input_tensor_, 1,
output_names, &output_tensor_, 1);
softmax(results_);
result_ = std::distance(results_.begin(), std::max_element(results_.begin(), results_.end()));
result_ = std::distance(results_.begin(),
std::max_element(results_.begin(), results_.end()));
return result_;
}
@ -43,29 +74,31 @@ struct MNIST {
std::array<float, width_ * height_> input_image_{};
std::array<float, 10> results_{};
int64_t result_{0};
int64_t result_{ 0 };
private:
private:
Ort::Env env;
Ort::Session session_{env, ofToDataPath("mnist-8.onnx", true).c_str(), Ort::SessionOptions{nullptr}};
shared_ptr<Ort::Session>
session_; // {env, (const wchar_t*)ofToDataPath("mnist-8.onnx",
// true).c_str(), Ort::SessionOptions{ nullptr }};
Ort::Value input_tensor_{nullptr};
std::array<int64_t, 4> input_shape_{1, 1, width_, height_};
Ort::Value input_tensor_{ nullptr };
std::array<int64_t, 4> input_shape_{ 1, 1, width_, height_ };
Ort::Value output_tensor_{nullptr};
std::array<int64_t, 2> output_shape_{1, 10};
Ort::Value output_tensor_{ nullptr };
std::array<int64_t, 2> output_shape_{ 1, 10 };
};
class ofApp : public ofBaseApp{
class ofApp : public ofBaseApp {
shared_ptr<MNIST> mnist;
ofFbo fbo_render;
ofFbo fbo_classification;
ofFloatPixels pix;
bool prev_pressed = false;
glm::vec2 prev_pt;
public:
void setup()
{
void setup() {
ofSetVerticalSync(true);
ofSetFrameRate(60);
@ -79,10 +112,11 @@ public:
fbo_classification.allocate(28, 28, GL_R32F, 0);
pix.setFromExternalPixels(&mnist->input_image_.front(), 28, 28, 1);
mnist->Run();
}
void update()
{
void update() {
if (ofGetMousePressed()) {
auto pt = glm::vec2(ofGetMouseX(), ofGetMouseY() - 60);
fbo_render.begin();
@ -98,28 +132,30 @@ public:
fbo_classification.begin();
ofClear(0);
fbo_render.draw(0, 0, fbo_classification.getWidth(), fbo_classification.getHeight());
fbo_render.draw(0, 0, fbo_classification.getWidth(),
fbo_classification.getHeight());
fbo_classification.end();
fbo_classification.readToPixels(pix);
mnist->Run();
prev_pt = pt;
prev_pressed = true;
} else {
}
else {
prev_pressed = false;
}
}
void draw()
{
void draw() {
ofClear(128);
fbo_render.draw(0, 60);
fbo_classification.draw(0, 340);
// render result
for (int i=0; i<10; ++i) {
for (int i = 0; i < 10; ++i) {
stringstream ss;
ss << i << ":" << std::fixed << std::setprecision(3) << mnist->results_[i];
ss << i << ":" << std::fixed << std::setprecision(3)
<< mnist->results_[i];
ofDrawBitmapString(ss.str(), 300, 70 + i * 30);
ofPushStyle();
ofSetColor(0, 255, 0);
@ -134,8 +170,7 @@ public:
ofDrawBitmapStringHighlight(ss.str(), 10, 20);
}
void keyPressed(int key)
{
void keyPressed(int key) {
if (key == 'c') {
fbo_render.begin();
ofClear(0);
@ -144,27 +179,23 @@ public:
}
void keyReleased(int key) {}
void mouseMoved(int x, int y ) {}
void mouseMoved(int x, int y) {}
void mouseDragged(int x, int y, int button) {}
void mousePressed(int x, int y, int button) {
}
void mousePressed(int x, int y, int button) {}
void mouseReleased(int x, int y, int button) {}
void windowResized(int w, int h) {}
void dragEvent(ofDragInfo dragInfo) {}
void gotMessage(ofMessage msg) {}
};
//========================================================================
int main( ){
ofSetupOpenGL(640,400,OF_WINDOW); // <-------- setup the GL context
int main() {
ofSetupOpenGL(640, 400, OF_WINDOW); // <-------- setup the GL context
// this kicks off the running of my app
// can be OF_WINDOW or OF_FULLSCREEN
// pass in width and height too:
ofRunApp(new ofApp());
}

Loading…
Cancel
Save