/// <summary>
        /// This will adjust the histograms in the data, ensuring that no gradient angle bin has a value greater than one. The histograms will be adjusted based upon the largest magnitude
        /// with a block of histograms - all magnitudes will be divided by the greatest magnitude of any angle within that block, such that no value anywhere will be greater than one
        /// </summary>
        public DataRectangle <HistogramOfGradient> Normalise(DataRectangle <HistogramOfGradient> hogs)
        {
            if (hogs == null)
            {
                throw new ArgumentNullException(nameof(hogs));
            }

            if ((hogs.Width < _blockSize) || (hogs.Height < _blockSize))
            {
                throw new ArgumentException($"too little data ({hogs.Width}x{hogs.Height}) for specified block size ({_blockSize})");
            }

            // For each overlapping block, we normalise and add the block contents to the normalisedHogs set. Blocks will be counted multiple times, which
            // is why the returned DataRectangle is larger than the input one. For example, given a 3x2 rectangle of histograms, there are data cells -
            //
            //  1 2 3
            //  4 5 6
            //
            // The normalised data will be four across because the first block to normalise will have histograms {{1,2},{4,5}} normalised and then the second block
            // will have {{2,3},{5,6}} normalised. This means that we have two blocks of 2x2 which combine to create a new output rectangle that is 4x2. The middle
            // elements (2 and 5) appear multiple times, which is expected.
            var numberOfOverlappingBlocksAcross = hogs.Width - (_blockSize - 1);
            var numberOfOverlappingBlocksDown   = hogs.Height - (_blockSize - 1);
            var normalisedHogs = new HistogramOfGradient[numberOfOverlappingBlocksAcross * _blockSize, numberOfOverlappingBlocksDown *_blockSize];

            for (var x = 0; x < numberOfOverlappingBlocksAcross; x++)
            {
                for (var y = 0; y < numberOfOverlappingBlocksDown; y++)
                {
                    var hogsInBlock = hogs.Slice(Rectangle.FromLTRB(
                                                     left: x,
                                                     right: x + _blockSize,
                                                     top: y,
                                                     bottom: y + _blockSize
                                                     ));
                    var maxMagnitudeWithinBlock = hogsInBlock.Enumerate().Max(pointAndHog => pointAndHog.Item2.GreatestMagnitude);
                    var normalisedHogsInBlock   = (maxMagnitudeWithinBlock == 0)                   // TODO: Need tests, particularly around this sort of thing
                                                ? hogsInBlock.Transform(hog => hog.Normalise())
                                                : hogsInBlock.Transform(hog => hog.Multiply(1 / maxMagnitudeWithinBlock));
                    for (var i = 0; i < _blockSize; i++)
                    {
                        for (var j = 0; j < _blockSize; j++)
                        {
                            normalisedHogs[(x * _blockSize) + i, (y * _blockSize) + j] = normalisedHogsInBlock[i, j];
                        }
                    }
                }
            }
            return(new DataRectangle <HistogramOfGradient>(normalisedHogs));
        }