Search code examples
c#pytorchartificial-intelligenceonnx

Image classification with Pytorch and C# ML


I m trying to load an image classification model made with pytorch into a c# aplication. In order to acomplish this task i use an async task, but when i run the program it throws me a null reference exception because it seams it doesn't load the model.

using System;
using System.Threading.Tasks;
using Windows.AI.MachineLearning;
using Windows.Graphics.Imaging;
using Windows.Media;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.Storage.Streams;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Imaging;

// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409

namespace AI_Test1
{
    /// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
    // All the required fields declaration 
    private Model modelGen;
    private Input image = new Input();
    private Output results;
    private StorageFile selectedStorageFile;
    private string label = "";
    private float probability = 0;
    private Helper helper = new Helper();

    public enum Labels
    {
        Has_Lighter,
        Has_No_Lighter,
    }


    public MainPage()
    {
        
        this.InitializeComponent();
        _ = loadModel();

    }

    private async Task loadModel()
    {
        // Get an access the ONNX model and save it in memory.
        StorageFile modelFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri($"ms-appx:///Assets/LTM-Classic_Model.onnx"));
        // Instantiate the model. 
        modelGen = await Model.CreateFromStreamAsync(modelFile);

    }

    private async void OpenFileButton_Click(object sender, RoutedEventArgs e)
    {
        if (!await getImage())
        {
            return;
        }
        // After the click event happened and an input selected, begin the model execution. 
        // Bind the model input
        await imageBind();
        // Model evaluation
        await evaluate();
        // Extract the results
        ExtractResult();
        // Display the results  
        displayResult();
    }

    private async Task<bool> getImage()
    {
        try
        {
            // Trigger file picker to select an image file
            FileOpenPicker fileOpenPicker = new FileOpenPicker();
            fileOpenPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
            fileOpenPicker.FileTypeFilter.Add(".jpg");
            fileOpenPicker.FileTypeFilter.Add(".png");
            fileOpenPicker.ViewMode = PickerViewMode.Thumbnail;
            selectedStorageFile = await fileOpenPicker.PickSingleFileAsync();
            if (selectedStorageFile == null)
            {
                return false;
            }
        }
        catch (Exception)
        {
            return false;
        }
        return true;
    }
    private async Task imageBind()
    {
        UIPreviewImage.Source = null;
        try
        {
            SoftwareBitmap softwareBitmap;
            using (IRandomAccessStream stream = await selectedStorageFile.OpenAsync(FileAccessMode.Read))
            {
                // Create the decoder from the stream
                BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
                // Get the SoftwareBitmap representation of the file in BGRA8 format
                softwareBitmap = await decoder.GetSoftwareBitmapAsync();
                softwareBitmap = SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
            }
            // Display the image 
            SoftwareBitmapSource imageSource = new SoftwareBitmapSource();
            await imageSource.SetBitmapAsync(softwareBitmap);
            UIPreviewImage.Source = imageSource;

            // Encapsulate the image within a VideoFrame to be bound and evaluated
            VideoFrame inputImage = VideoFrame.CreateWithSoftwareBitmap(softwareBitmap);
            // Resize the image size to 32x32  
            inputImage = await helper.CropAndDisplayInputImageAsync(inputImage);
            // Bind the model input with image 
            ImageFeatureValue imageTensor = ImageFeatureValue.CreateFromVideoFrame(inputImage);
            image.input = imageTensor;

            // Encapsulate the image within a VideoFrame to be bound and evaluated
            //VideoFrame inputImage = VideoFrame.CreateWithSoftwareBitmap(softwareBitmap);
            // bind the input image 
            //ImageFeatureValue imageTensor = ImageFeatureValue.CreateFromVideoFrame(inputImage);
            //image.modelInput = imageTensor;
        }
        catch (Exception )
        {
        }
    }
    private void ExtractResult()
    {
        // Retrieve the results of evaluation
        var mResult = results.output as TensorFloat;
        // convert the result to vector format
        var resultVector = mResult.GetAsVectorView();

        probability = 0;
        int index = 0;
        // find the maximum probability
        for (int i = 0; i < resultVector.Count; i++)
        {
            var elementProbability = resultVector[i];
            if (elementProbability > probability)
            {
                index = i;
            }
        }
        label = ((Labels)index).ToString();
    }
    private void displayResult()
    {
        displayOutput.Text = label;
    }
    private async Task evaluate()
    {
        results = await modelGen.EvaluateAsync(image);
    }
}

}

enter image description here


Solution

  • According to what I could understand from your code, the modelGen is not initialized before you have called the evaluate() method. Apparantly, you have created a method loadModel() for this purpose, so I am guessing that you need to call the loadmodel() before you call evaluate().

    So edit this portion of the code

        private async void OpenFileButton_Click(object sender, RoutedEventArgs e)
        {
            if (!await getImage())
            {
                return;
            }
            // After the click event happened and an input selected, begin the model execution. 
            // Bind the model input
            await imageBind();
    
            await loadModel(); // EDITED: Load Model here
    
            // Model evaluation
            await evaluate();
            // Extract the results
            ExtractResult();
            // Display the results  
            displayResult();
        }