SciSharp / NumSharp

High Performance Computation for N-D Tensors in .NET, similar API to NumPy.
https://github.com/SciSharp
Apache License 2.0
1.38k stars 192 forks source link

NumSharp.Bitmap and OpenCv #377

Closed Oceania2018 closed 4 years ago

Oceania2018 commented 4 years ago

I want to add some common methods to interoperate with OpenCv in NumSharp.Bitmap so that they can be shared. The advantage is that users can easily use NumSharp and OpenCv to process image applications.

For exampe: NdarrayToMat, MatToNdarray.

And we have to rely on this package OpenCvSharp4 which is about 1M size.

Nucs commented 4 years ago
static unsafe void Main(string[] args)
{
    Mat src = new Mat("olga.jpg", ImreadModes.AnyColor);
    NDArray nd = WrapWithNDArray(src); //shaped (1, src.Height, src.Width, Channels)
    Bitmap bmp = nd.ToBitmap(); //using NumSharp.Bitmap
    bmp.Save("./olga-reconstructed.jpg");
}

//this method copies Mat to a new NDArray
public static unsafe NDArray ToNDArray(Mat src)
{
    var nd = new NDArray(NPTypeCode.Byte, (1, src.Height, src.Width, src.Type().Channels), fillZeros: false);
    new UnmanagedMemoryBlock<byte>(src.DataPointer, nd.size)
        .CopyTo(nd.Unsafe.Address);

    return nd;
}

//this method wraps without copying Mat.
public static unsafe NDArray WrapWithNDArray(Mat src)
{
    Shape shape = (1, src.Height, src.Width, src.Type().Channels);
    var storage = new UnmanagedStorage(new ArraySlice<byte>(new UnmanagedMemoryBlock<byte>(src.DataPointer, shape.Size, () => Donothing(src))), shape); //we pass donothing as it keeps reference to src preventing its disposal by GC
    return new NDArray(storage);
}

[MethodImpl(MethodImplOptions.NoOptimization)]
private static void Donothing(Mat m)
{
    var a = m;
}

Similarly to these? (and backwards to Mat) (taken from https://github.com/SciSharp/NumSharp/issues/371)

Oceania2018 commented 4 years ago

@Nucs Correct, People use OpenCv a lot. We should make NumSharp and OpenCv work better. We have combined TF.NET and NumSharp. NumSharp with OpenCv is the last piece for Computer Vision.

AvenSun commented 4 years ago

@Nucs @Oceania2018

It would be better we can make it more generalized (data type, image layout etc. ). as far as i know, currently there're two image layouts used by mainstream deeplearning frameworks. cuDNN (Nvidia DNN library) is much more efficient when using NCHW,
but intel GPU would prefer to use NCHW.

tensorflow  ==> NHWC (numl, height, width, channe)
pytorch ==> NCHW (num, channel, height, width)
mxnet ==> NCHW (num, channel, height, width)
caffe ==> NCHW (num, channel, height, width)

during training or inference, sometimes we might decare ndarray with data type uint8 explicitly, sometimes float32 etc.

Nucs commented 4 years ago

@AvenSun Our code base is deeply tied to work with tensorflow. But a simple nd.reshape should do the trick (if not, we have np.swapaxes implemented) because the data is linear. With that being, I'll also add an enum parameter allowing to choose between the libraries you mentioned that'll decide the return shape.

AvenSun commented 4 years ago

@Nucs yes, I knew there're several ways to transfer NCHW into NHWC and vice versa. It'll cost extra time if we don't make it at the beginning. This is more noticeable when the operation lies in loops. NumSharp should be a common numerical computing library like numpy. It should not be just for tensorflow.

Oceania2018 commented 4 years ago

@Nucs I think NumSharp is not tied to TF.NET since v0.20. It's TF.NET tied to NumSharp.

Nucs commented 4 years ago

The thing is that all the common image formats provide their data in a linear way, R1G1B1R2G2B2 ... So in my opinion using NHWC is the natural way to handle images hence why I think the primary shape order should be NHWC.

Nevertheless I'll add support for NCHW