0

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.

vuict
  • 72
  • 5
  • You need to know what the array contains. Raw 8-bit mono data? raw bgr? raw float? An actual image-file? Do you know the height/stride of the image? What is `ArrayToImage`? I'm fairly sure it is not a framework method. Without that information it it difficult to provide any assistance. – JonasH Feb 28 '23 at 09:35
  • @JonasH sorry it was a typo. Should be ```ArrayToImg```. The link is here, https://scisharp.github.io/Keras.NET/api/Keras.PreProcessing.Image.ImageUtil.html. I currently trying out a method, which I have put it in the answer below. – vuict Mar 01 '23 at 09:48

1 Answers1

0

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.

vuict
  • 72
  • 5
  • The first two steps are self-contradictory. `GetData` is a method of `NDArray`. NumSharp's `ToBitmap` is an extension method on `NDArray`. Calling `GetData` makes no sense while assigning an `int[]` to an `NDArray` variable will cause a compilation error – Panagiotis Kanavos Mar 01 '23 at 09:53
  • @PanagiotisKanavos, fairly sure it is from NDarray, link here: https://github.com/SciSharp/Numpy.NET#create-a-numpy-array-from-a-c-array-and-vice-versa – vuict Mar 01 '23 at 10:00
  • Yes it is, which is why `GetData` is meaningless and `NumSharp.NDArray numsharp_array = c_sharp_array;` will cause a compilation error. `ToBitmap()` only works on NDArray which means you can just write `numpy_array.ToBitmap()` or `numpy_array.reshape(...).ToBitmap(0` – Panagiotis Kanavos Mar 01 '23 at 10:05
  • @PanagiotisKanavos, I didn't get compilation error for the 2nd step. So far I compiled each step separately and didn't get issue. I plan to do a full test combining all the steps above in the next few days. But I believe I can get pretty much what I want. – vuict Mar 01 '23 at 10:12
  • If you convert the NDArray back to an NDArray, why not use the original? – Panagiotis Kanavos Mar 01 '23 at 10:48
  • I think NDArray and NDarray are not the same. The former is NumSharp and the latter Numpy. What I did is convert Numpy array -> C# array -> NumSharp -> Bitmap. I don't think Numpy array and NumSharp array can be used interchangeable without conversion, although I wish so to be able to skip C# array (or even the NumSharp array, directly to bitmap). Please share if you or anyone knows there is a way to skip some of the steps in this answer. – vuict Mar 01 '23 at 12:07
  • You're right, but that's actually worse. It looks like NumSharp was abandoned 2 years ago and uses the deprecated [System.Drawing.Graphics](https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/6.0/system-drawing-common-windows-only) namespace that's actively being removed and crashes on non-Windows platforms. Both NumPy.NET and NumSharp are in the same Github organisation, SciSharp, but NumSharp is abandoned – Panagiotis Kanavos Mar 01 '23 at 12:15