Search code examples
c#kerasnumpy-ndarrayimage-segmentation

Convert Numpy Array to Bitmap in C#, Keras.Net


I am working on image semantic segmentation, and trying to figure out how to convert the prediction (after argmax) to bitmap.

If I use ArrayToImg from ImageUtil, it returns a system object. How do I convert it to bitmap from here?

I trained the model using python, and trying to do the prediction in C#.

I tried searching online but so far haven't found any useful information about it.


Solution

  • Updated answer:

    Method 1 (NumSharp Method) - Convert Numpy array -> C# array -> NumSharp array -> Bitmap.

    //Convert Numpy array to C# array. The Numpy array has shape of (height, width). I use (500,600) for this example:
    var array_csharp = array_numpy.GetData<long>();
    
    /Convert C# array to NumSharp, and reshape it to back to image size
    NumSharp.NDArray gray_numsharp = array_csharp;
    gray_numsharp = gray_numsharp.reshape(500, 600, 1);
    
    //create an empty RGB array with white color background
    NumSharp.NDArray rgb_numsharp = NumSharp.np.ones((500, 600, 3)) * 255;
    
    //Convert class index to color. Note the color value is in BGR order instead of RGB
    for (int row = 0; row < 500; row++)
        for (int col = 0; col < 600; col++)
            if (gray_numsharp[row, col, 0] == 1)
            {
                rgb_numsharp[row, col] = new int[] { 0, 0, 255 };
            }
            else if (gray_numsharp[row, col, 0] == 2)
            {
                rgb_numsharp[row, col] = new int[] { 255, 0, 0 };
            }
    
    //Reshape into 4 dimensions, required for bitmap conversion
    rgb_numsharp = rgb_numsharp.reshape(1, 500, 600, 3);
    
    //Change datatype to byte
    NumSharp.NDArray numsharp_byte_array = array_rgb_numsharp.astype(NumSharp.np.@byte);
    
    //Convert to bitmap and save it
    Bitmap mask = numsharp_byte_array.ToBitmap();
    mask.Save(@"C:\prediction.png", ImageFormat.Png);
    

    Method 2 (without using NumSharp)

    • Convert Numpy array -> C# array -> Bitmap. I took reference from here. I am also using the function MySaveBMP from the link.
    //Convert Numpy array to C# array. The Numpy array has shape of (height, width). I use (500,600) for this example:
    var array_csharp = array_numpy.GetData<long>();
    
    int width = 600;
    int height = 500;
    int bytesPerPixel = 3;
    int pixel_length = width*height;
    byte[] bgr_array = new byte[pixel_length*3];
    
    for (int i=0; i < pixel_length; i++)
    {
        if (array_csharp[i] == 1)
        {
            bgr_array[3 * i] = 0;
            bgr_array[3 * i + 1] = 0;
            bgr_array[3 * i + 2] = 255;
        }
        else if (array_csharp[i] == 2)
        {
            bgr_array[3 * i] = 255;
            bgr_array[3 * i + 1] = 0;
            bgr_array[3 * i + 2] = 0;
        }
        else
        {
            bgr_array[3 * i] = 255;
            bgr_array[3 * i + 1] = 255;
            bgr_array[3 * i + 2] = 255;
        }
    }
    
    MySaveBMP(bgr_array, width, height);
    
    

    Both the methods were tested and work as expected. I would choose to use method 2 due to the speed. Method 1 takes like 2 sec (from Numpy array to bitmap conversion), while method 2 is almost instantly I can get the result.


    Below is earlier answer and can be ignored

    After researching here and there, I think this might work, though I have not done a complete test yet. Put it might help someones who have the same question:

    1. First convert the numpy array to C# array using GetData:
    var c_sharp_array = numpy_array.GetData<int>();
    
    1. Then convert it to NumSharp and reshape it to desired shape:
    NumSharp.NDArray numsharp_array = c_sharp_array;
    numsharp_array = numsharp_array.reshape(x,y,z);
    
    1. Convert to Bitmap using NumSharp library:
    Bitmap bmp = numsharp_array.ToBitmap();
    

    Will mark this as accepted answer once it is fully tested.