Exemple #1
0
        /// <summary>
        ///     Wraps given <see cref="BitmapData"/> as n <see cref="NDArray"/> without performing copy.
        /// </summary>
        /// <param name="bmpData">Targetted bitmap data with reading capabilities.</param>
        /// <param name="flat">
        ///     If true, returns NDArray be 1-d of pixels: R1G1B1R2G2B2 ... RnGnBn where n is the amount of pixels in the image.<br></br>
        ///     If false, returns a 4-d NDArray shaped: (1, bmpData.Height, bmpData.Width, bbp)
        /// </param>
        /// <param name="discardAlpha">If the given <see cref="Bitmap"/> has an alpha pixel (transparency pixel), return a slice without the alpha.</param>
        /// <returns>An NDArray that wraps the given bitmap, doesn't copy</returns>
        /// <remarks>If the BitmapData is unlocked via <see cref="Bitmap.UnlockBits"/> - the NDArray will point to an invalid address which will cause heap corruption. Use with caution!</remarks>
        public static unsafe NDArray AsNDArray(this BitmapData bmpData, bool flat = false, bool discardAlpha = false)
        {
            if (bmpData == null)
            {
                throw new ArgumentNullException(nameof(bmpData));
            }

            var ret = new NDArray(new ArraySlice <byte>(new UnmanagedMemoryBlock <byte>((byte *)bmpData.Scan0, bmpData.Stride * bmpData.Height)));

            if (flat)
            {
                if (ret.shape[3] == 4 && discardAlpha)
                {
                    return(ret.reshape(1, bmpData.Height, bmpData.Width, bmpData.Stride / bmpData.Width) //reshape
                           [Slice.All, Slice.All, Slice.All, new Slice(stop: 3)]                         //slice
                           .flat);                                                                       //flatten
                }

                return(ret);
            }
            else
            {
                ret = ret.reshape(1, bmpData.Height, bmpData.Width, bmpData.Stride / bmpData.Width); //reshape

                if (ret.shape[3] == 4 && discardAlpha)
                {
                    ret = ret[Slice.All, Slice.All, Slice.All, new Slice(stop: 3)]; //slice
                }
                return(ret);
            }
        }
Exemple #2
0
        /// <summary>
        /// Return coordinate matrices from coordinate vectors.
        /// Make N-D coordinate arrays for vectorized evaluations of
        /// N-D scalar/vector fields over N-D grids, given
        /// one-dimensional coordinate arrays x1, x2,..., xn.
        /// .. versionchanged:: 1.9
        /// 1-D and 0-D cases are allowed.
        /// </summary>
        /// <param name="x1"> 1-D arrays representing the coordinates of a grid</param>
        /// /// <param name="x2"> 1-D arrays representing the coordinates of a grid</param>
        /// <returns></returns>
        public static (NDArray, NDArray) meshgrid(NDArray x1, NDArray x2, Kwargs kwargs = null)
        {
            if (kwargs == null)
            {
                kwargs = new Kwargs();
            }
            int ndim   = 2;
            var s0     = (1, 1);
            var output = new NDArray[] { x1.reshape(x1.size, 1), x2.reshape(1, x2.size) };

            if (kwargs.indexing == "xy" && ndim > 1)
            {
                // Switch first and second axis
                output = new NDArray[] { x1.reshape(1, x1.size), x2.reshape(x2.size, 1) };
            }

            if (!kwargs.sparse)
            {
                // Return the full N-D matrix(not only the 1 - D vector)
                output = np.broadcast_arrays(output[0], output[1], true);
            }

            if (kwargs.copy)
            {
            }

            return(output[0], output[1]);
        }
Exemple #3
0
        public static NDArray zeros <T>(params int[] shape)
        {
            var nd = new NDArray(typeof(T));

            nd.reshape(shape);

            return(nd);
        }
Exemple #4
0
        /// <summary>
        ///     Return a contiguous flattened array. A 1-D array, containing the elements of the input, is returned
        /// </summary>
        /// <remarks>https://docs.scipy.org/doc/numpy/reference/generated/numpy.ravel.html</remarks>
        /// <param name="a">Input array. The elements in a are read in the order specified by order, and packed as a 1-D array.</param>
        /// <remarks><br></br>If this array's <see cref="Shape"/> is a sliced or broadcasted, the a copy will be made.</remarks>
        public static NDArray ravel(NDArray a)
        {
            // ReSharper disable once ConvertIfStatementToReturnStatement
            if (!a.Shape.IsContiguous)
            {
                return(new NDArray(new UnmanagedStorage(a.Storage.CloneData(), Shape.Vector(a.size))));
            }

            return(a.reshape(Shape.Vector(a.size)));
        }
        /// <summary>
        ///     Wraps given <see cref="BitmapData"/> as n <see cref="NDArray"/> without performing copy.
        /// </summary>
        /// <param name="bmpData">Targetted bitmap data with reading capabilities.</param>
        /// <param name="flat">
        ///     If true, returns NDArray be 1-d of pixels: R1G1B1R2G2B2 ... RnGnBn where n is the amount of pixels in the image.<br></br>
        ///     If false, returns a 4-d NDArray shaped: (1, bmpData.Height, bmpData.Width, 3)
        /// </param>
        /// <returns>An NDArray that wraps the given bitmap, doesn't copy</returns>
        /// <remarks>If the BitmapData is unlocked via <see cref="Bitmap.UnlockBits"/> - the NDArray will point to an invalid address which will cause heap corruption. Use with caution!</remarks>
        public static unsafe NDArray AsNDArray(this BitmapData bmpData, bool flat = false)
        {
            if (bmpData == null)
            {
                throw new ArgumentNullException(nameof(bmpData));
            }

            var nd = new NDArray(new ArraySlice <byte>(new UnmanagedMemoryBlock <byte>((byte *)bmpData.Scan0, bmpData.Stride * bmpData.Height)));

            return(flat ? nd : nd.reshape(1, bmpData.Height, bmpData.Width, 3));
        }
Exemple #6
0
        /// <summary>
        ///     Return a contiguous flattened array. A 1-D array, containing the elements of the input, is returned
        /// </summary>
        /// <remarks>https://docs.scipy.org/doc/numpy/reference/generated/numpy.ravel.html</remarks>
        /// <param name="a">Input array. The elements in a are read in the order specified by order, and packed as a 1-D array.</param>
        /// <remarks><br></br>If this array's <see cref="Shape"/> is a slice, the a copy will be made.</remarks>
        public static NDArray ravel(NDArray a)
        {
            //TODO! when slice reshaping is done, prevent this cloning.
            // ReSharper disable once ConvertIfStatementToReturnStatement
            if (a.Shape.IsSliced)
            {
                return(new NDArray(new UnmanagedStorage(a.Storage.CloneData(), Shape.Vector(a.size))));
            }

            return(a.reshape(Shape.Vector(a.size)));
        }
        public static NDArray expand_dims(NDArray a, int axis)
        {
            //test if the ndarray is empty.
            if (a.size == 0)
            {
                return(a);
            }

            var shape = np.array(a.shape);
            var left  = shape[$":{axis}"].Array.Cast <int>();
            var right = shape[$"{axis}:"].Array.Cast <int>();

            return(a.reshape(_combineEnumerables(left, __one, right).ToArray()));
        }
Exemple #8
0
        /// <summary>
        ///     Convert inputs to arrays with at least one dimension.
        ///     Scalar inputs are converted to 1-dimensional arrays, whilst higher-dimensional inputs are preserved.
        /// </summary>
        /// <returns>An array, or list of arrays, each with a.ndim >= 1. Copies are made only if necessary.</returns>
        /// <remarks>https://docs.scipy.org/doc/numpy/reference/generated/numpy.atleast_1d.html</remarks>
        public static NDArray atleast_1d(NDArray arr)
        {
            if (arr == null)
            {
                throw new ArgumentNullException(nameof(arr));
            }

            switch (arr.ndim)
            {
            case 0:
                return(arr.reshape(1));

            default:
                return(arr);
            }
        }
Exemple #9
0
        /// <summary>
        ///     Remove single-dimensional entries from the shape of an array.
        /// </summary>
        /// <param name="a">Input data.</param>
        /// <param name="axis">Selects a subset of the single-dimensional entries in the shape. If an axis is selected with shape entry greater than one, an error is raised.</param>
        /// <returns>The input array, but with all or a subset of the dimensions of length 1 removed. This is always a itself or a view into a.</returns>
        /// <remarks>https://docs.scipy.org/doc/numpy/reference/generated/numpy.squeeze.html</remarks>
        /// <exception cref="IncorrectShapeException">If axis is not None, and an axis being squeezed is not of length 1</exception>
        public static NDArray squeeze(NDArray a, int axis)
        {
            while (axis < 0)
            {
                axis = a.ndim + axis; //handle negative axis
            }
            if (axis >= a.ndim)
            {
                throw new ArgumentOutOfRangeException(nameof(axis));
            }

            if (a.shape[axis] != 1)
            {
                throw new IncorrectShapeException($"Unable to squeeze axis {axis} because it is of length {a.shape[axis]} and not 1.");
            }

            return(a.reshape(squeeze_fast(a.Shape, axis)));
        }
Exemple #10
0
        public static NDArray load(Stream stream)
        {
            using (var reader = new BinaryReader(stream, System.Text.Encoding.ASCII
#if !NET35 && !NET40
                                                 , leaveOpen: true
#endif
                                                 ))
            {
                int   bytes;
                Type  type;
                int[] shape;
                if (!parseReader(reader, out bytes, out type, out shape))
                {
                    throw new FormatException();
                }

                Array array = Arrays.Create(type, shape.Aggregate((dims, dim) => dims * dim));

                var result = new NDArray(readValueMatrix(reader, array, bytes, type, shape));
                return(result.reshape(shape));
            }
        }
Exemple #11
0
        /// <summary>
        ///     View inputs as arrays with at least three dimensions.
        /// </summary>
        /// <returns>An array, or list of arrays, each with a.ndim >= 3. Copies are avoided where possible, and views with three or more dimensions are returned. For example, a 1-D array of shape (N,) becomes a view of shape (1, N, 1), and a 2-D array of shape (M, N) becomes a view of shape (M, N, 1).</returns>
        /// <remarks>https://docs.scipy.org/doc/numpy/reference/generated/numpy.atleast_3d.html</remarks>
        public static NDArray atleast_3d(NDArray arr)
        {
            if (arr == null)
            {
                throw new ArgumentNullException(nameof(arr));
            }

            switch (arr.ndim)
            {
            case 0:
                return(arr.reshape(1, 1, 1));

            case 1:
                return(np.expand_dims(np.expand_dims(arr, 1), 0));

            case 2:
                return(np.expand_dims(arr, 2));

            default:
                return(arr);
            }
        }
        /// <summary>
        ///     Creates <see cref="NDArray"/> from given <see cref="Bitmap"/>.
        /// </summary>
        /// <param name="image">The image to load data from.</param>
        /// <param name="flat">
        ///     If true, returns NDArray be 1-d of pixels: `R1G1B1R2G2B2 ... RnGnBn` where n is the amount of pixels in the image.<br></br>
        ///     If false, returns a 4-d NDArray shaped: (1, bmpData.Height, bmpData.Width, 3)
        /// </param>
        /// <param name="copy">
        ///     If true, performs <see cref="Bitmap.LockBits(System.Drawing.Rectangle,System.Drawing.Imaging.ImageLockMode,System.Drawing.Imaging.PixelFormat)"/>
        ///     and then copies the data to a new <see cref="NDArray"/> then finally releasing the locked bits.<br></br>
        ///     If false, It'll call <see cref="Bitmap.LockBits(System.Drawing.Rectangle,System.Drawing.Imaging.ImageLockMode,System.Drawing.Imaging.PixelFormat)"/>
        ///     , wraps the <see cref="BitmapData.Scan0"/> with an NDArray and call <see cref="Bitmap.UnlockBits"/> only when the NDArray will be collected by the <see cref="GC"/>.
        /// </param>
        /// <returns>An NDArray that holds the pixel data of the given bitmap</returns>
        public static unsafe NDArray ToNDArray(this System.Drawing.Bitmap image, bool flat = false, bool copy = true)
        {
            if (image == null)
            {
                throw new ArgumentNullException(nameof(image));
            }

            BitmapData bmpData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadOnly, image.PixelFormat);

            if (copy)
            {
                try
                {
                    unsafe
                    {
                        //Create a 1d vector without filling it's values to zero (similar to np.empty)
                        var nd = new NDArray(NPTypeCode.Byte, Shape.Vector(bmpData.Stride * image.Height), fillZeros: false);

                        // Get the respective addresses
                        byte *src = (byte *)bmpData.Scan0;
                        byte *dst = (byte *)nd.Unsafe.Address; //we can use unsafe because we just allocated that array and we know for sure it is contagious.

                        // Copy the RGB values into the array.
                        Buffer.MemoryCopy(src, dst, nd.size, nd.size); //faster than Marshal.Copy
                        return(nd.reshape(1, image.Height, image.Width, 3));
                    }
                }
                finally
                {
                    image.UnlockBits(bmpData);
                }
            }
            else
            {
                var nd = new NDArray(new ArraySlice <byte>(new UnmanagedMemoryBlock <byte>((byte *)bmpData.Scan0, bmpData.Stride * bmpData.Height, () => image.UnlockBits(bmpData))));
                return(flat ? nd : nd.reshape(1, bmpData.Height, bmpData.Width, 3));
            }
        }
Exemple #13
0
        public static unsafe NDArray ToNDArray(this System.Drawing.Bitmap image, bool flat = false, bool copy = true, bool discardAlpha = false)
        {
            if (image == null)
            {
                throw new ArgumentNullException(nameof(image));
            }

            BitmapData bmpData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadOnly, image.PixelFormat);

            if (copy)
            {
                try
                {
                    unsafe
                    {
                        //Create a 1d vector without filling it's values to zero (similar to np.empty)
                        var nd = new NDArray(NPTypeCode.Byte, Shape.Vector(bmpData.Stride * image.Height), fillZeros: false);

                        // Get the respective addresses
                        byte *src = (byte *)bmpData.Scan0;
                        byte *dst = (byte *)nd.Unsafe.Address; //we can use unsafe because we just allocated that array and we know for sure it is contagious.

                        // Copy the RGB values into the array.
                        Buffer.MemoryCopy(src, dst, bmpData.Stride * image.Height, nd.size); //faster than Marshal.Copy
                        var ret = nd.reshape(1, image.Height, image.Width, bmpData.Stride / bmpData.Width);
                        if (discardAlpha && ret.shape[3] == 4)
                        {
                            ret = ret[Slice.All, Slice.All, Slice.All, new Slice(stop: 3)];
                        }

                        return(flat && ret.ndim != 1 ? ret.flat : ret);
                    }
                }
                finally
                {
                    image.UnlockBits(bmpData);
                }
            }
            else
            {
                var ret = new NDArray(new ArraySlice <byte>(new UnmanagedMemoryBlock <byte>((byte *)bmpData.Scan0, bmpData.Stride * bmpData.Height, () => image.UnlockBits(bmpData))));

                if (flat)
                {
                    if (discardAlpha)
                    {
                        if (bmpData.Stride / bmpData.Width == 4)                                                 //1byte-per-color
                        {
                            return(ret.reshape(1, bmpData.Height, bmpData.Width, bmpData.Stride / bmpData.Width) //reshape
                                   [Slice.All, Slice.All, Slice.All, new Slice(stop: 3)]                         //slice
                                   .flat);                                                                       //flatten
                        }

                        if (bmpData.Stride / bmpData.Width == 8)                                                 //2bytes-per-color
                        {
                            return(ret.reshape(1, bmpData.Height, bmpData.Width, bmpData.Stride / bmpData.Width) //reshape
                                   [Slice.All, Slice.All, Slice.All, new Slice(stop: 6)]                         //slice
                                   .flat);                                                                       //flatten
                        }

                        throw new NotSupportedException($"Given bbp ({bmpData.Stride / bmpData.Width}) is not supported.");
                    }

                    return(ret.flat);
                }
                else
                {
                    ret = ret.reshape(1, bmpData.Height, bmpData.Width, bmpData.Stride / bmpData.Width); //reshape
                    if (discardAlpha)
                    {
                        if (ret.shape[3] == 4)                                              //1byte-per-color
                        {
                            ret = ret[Slice.All, Slice.All, Slice.All, new Slice(stop: 3)]; //slice
                        }
                        else if (ret.shape[3] == 8)                                         //2bytes-per-color
                        {
                            ret = ret[Slice.All, Slice.All, Slice.All, new Slice(stop: 6)]; //slice
                        }
                        else
                        {
                            throw new NotSupportedException($"Given bbp ({bmpData.Stride / bmpData.Width}) is not supported.");
                        }
                    }

                    return(ret);
                }
            }
        }
Exemple #14
0
 /// <summary>
 /// Remove single-dimensional entries from the shape of an array.
 /// </summary>
 /// <param name="nd"></param>
 /// <param name="axis"></param>
 /// <returns></returns>
 public static NDArray squeeze(NDArray nd, int axis = -1)
 {
     return(nd.reshape(nd.shape.Where(x => x > 1).ToArray()));
 }
Exemple #15
0
 /// <summary>
 ///     Gives a new shape to an array without changing its data.
 /// </summary>
 /// <param name="nd">Array to be reshaped.</param>
 /// <param name="shape">The new shape should be compatible with the original shape. </param>
 /// <returns>original <paramref name="nd"/> reshaped without copying.</returns>
 /// <remarks>https://docs.scipy.org/doc/numpy-1.16.0/reference/generated/numpy.reshape.html</remarks>
 public static NDArray reshape(NDArray nd, params int[] shape)
 {
     return(nd.reshape(shape));
 }
Exemple #16
0
 internal static NDArray squeeze_fast(NDArray a, int axis)
 {
     return(a.reshape(squeeze_fast(a.Shape, axis)));
 }
Exemple #17
0
        /// <summary>
        ///     Converts <see cref="NDArray"/> to a <see cref="Bitmap"/>.
        /// </summary>
        /// <param name="nd">The <see cref="NDArray"/> to copy pixels from, <see cref="Shape"/> is ignored completely. If nd.Unsafe.Shape.IsContiguous == false then a copy is made.</param>
        /// <param name="width">The height of the <see cref="Bitmap"/></param>
        /// <param name="height">The width of the <see cref="Bitmap"/></param>
        /// <param name="format">The format of the expected bitmap, Must be matching to given NDArray otherwise unexpected results might occur.</param>
        /// <returns>A <see cref="Bitmap"/></returns>
        /// <exception cref="ArgumentException">When nd.size != width*height, which means the ndarray be turned into the given bitmap size.</exception>
        public static unsafe Bitmap ToBitmap(this NDArray nd, int width, int height, PixelFormat format = PixelFormat.DontCare)
        {
            if (nd == null)
            {
                throw new ArgumentNullException(nameof(nd));
            }

            //if flat then initialize based on given format
            if (nd.ndim == 1 && format != PixelFormat.DontCare)
            {
                nd = nd.reshape(1, height, width, format.ToBytesPerPixel()); //theres a check internally for size mismatch.
            }
            if (nd.ndim != 4)
            {
                throw new ArgumentException("ndarray was expected to be of 4-dimensions, (1, bmpData.Height, bmpData.Width, bytesPerPixel)");
            }

            if (nd.shape[0] != 1)
            {
                throw new ArgumentException($"ndarray has more than one picture in it ({nd.shape[0]}) based on the first dimension.");
            }


            var bbp = nd.shape[3]; //bytes per pixel.

            if (bbp != extractFormatNumber())
            {
                throw new ArgumentException($"Given PixelFormat: {format} does not match the number of bytes per pixel in the 4th dimension of given ndarray.");
            }

            if (bbp * width * height != nd.size)
            {
                throw new ArgumentException($"The expected size does not match the size of given ndarray. (expected: {bbp * width * height}, actual: {nd.size})");
            }


            var ret     = new Bitmap(width, height, format);
            var bitdata = ret.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, format);

            try
            {
                var dst = new ArraySlice <byte>(new UnmanagedMemoryBlock <byte>((byte *)bitdata.Scan0, bitdata.Stride * bitdata.Height));
                if (nd.Shape.IsContiguous)
                {
                    nd.CopyTo(dst);
                }
                else
                {
                    MultiIterator.Assign(new UnmanagedStorage(dst, Shape.Vector(bitdata.Stride * bitdata.Height)), nd.Unsafe.Storage);
                }
            }
            finally
            {
                ret.UnlockBits(bitdata);
            }

            return(ret);

            int extractFormatNumber()
            {
                if (format == PixelFormat.DontCare)
                {
                    switch (bbp)
                    {
                    case 3:
                        format = PixelFormat.Format24bppRgb;
                        break;

                    case 4:
                        format = PixelFormat.Format32bppArgb;
                        break;

                    case 6:
                        format = PixelFormat.Format48bppRgb;
                        break;

                    case 8:
                        format = PixelFormat.Format64bppArgb;
                        break;
                    }

                    return(bbp);
                }

                return(format.ToBytesPerPixel());
            }
        }
Exemple #18
0
 /// <summary>
 ///     Remove single-dimensional entries from the shape of an array.
 /// </summary>
 /// <param name="a">Input data.</param>
 /// <returns>The input array, but with all or a subset of the dimensions of length 1 removed. This is always a itself or a view into a.</returns>
 /// <remarks>https://docs.scipy.org/doc/numpy/reference/generated/numpy.squeeze.html</remarks>
 public static NDArray squeeze(NDArray a)
 {
     return(a.reshape(a.shape.Where(x => x != 1).ToArray()));
 }