The source code for this sample is available [here](https://github.com/microsoft/onnxruntime/tree/main/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample).
To run this sample, you'll need the following things:
1. Install [.NET Core 3.1](https://dotnet.microsoft.com/download/dotnet-core/3.1) or higher for you OS (Mac, Windows or Linux).
2. Download the [ResNet50 v2](https://github.com/onnx/models/blob/master/vision/classification/resnet/model/resnet50-v2-7.onnx) ONNX model to your local system.
3. Download [this picture of a dog](/images/dog.jpeg) to test the model. You can also use any image you like.
## Getting Started
Now we have everything set up, we can start adding code to run the model on the image. We'll do this in the main method of the program for simplicity.
### Read paths
Firstly, let's read the path to the model and path to the image we want to test in through program arguments:
```cs
string modelFilePath = args[0];
string imageFilePath = args[1];
```
### Read image
Next, we will read the image in using the cross-platform image library [ImageSharp](https://www.nuget.org/packages/SixLabors.ImageSharp):
```cs
using Image<Rgb24> image = Image.Load<Rgb24>(imageFilePath, out IImageFormat format);
```
Note, we're specifically reading the `Rgb24` type so we can efficiently preprocess the image in a later step.
### Resize image
Next, we will resize the image to the appropriate size that the model is expecting; 224 pixels by 224 pixels:
```cs
using Stream imageStream = new MemoryStream();
image.Mutate(x =>
{
x.Resize(new ResizeOptions
{
Size = new Size(224, 224),
Mode = ResizeMode.Crop
});
});
image.Save(imageStream, format);
```
Note, we're doing a centered crop resize to preserve aspect ratio.
### Preprocess image
Next, we will preprocess the image according to the [requirements of the model](https://github.com/onnx/models/tree/master/vision/classification/resnet#preprocessing):
Here, we're creating a Tensor of the required size `(batch-size, channels, height, width)`, accessing the pixel values, preprocessing them and finally assigning them to the tensor at the appropriate indicies.
### Setup inputs
Next, we will create the inputs to the model:
```cs
var inputs = new List<NamedOnnxValue>
{
NamedOnnxValue.CreateFromTensor("data", input)
};
```
To check the input node names for an ONNX model, you can use [Netron](https://github.com/lutzroeder/netron) to visualise the model and see input/output names. In this case, this model has `data` as the input node name.
### Run inference
Next, we will create an inference session and run the input through it:
```cs
using var session = new InferenceSession(modelFilePath);
using IDisposableReadOnlyCollection<DisposableNamedOnnxValue> results = session.Run(inputs);
```
### Postprocess output
Next, we will need to postprocess the output to get the softmax vector, as this is not handled by the model itself: