extern alias CoreDrawing; using System; using System.Collections.Generic; using System.Linq; namespace ZeroLevel.ML.Services { internal sealed class ImageScanner : IDisposable { private readonly CoreDrawing.System.Drawing.Bitmap _image; private readonly CoreDrawing.System.Drawing.Imaging.BitmapData _bitmapData; private readonly int _stride; private readonly int _bytesPerPixel; private readonly int _cropSizeX; private readonly int _cropSizeY; private readonly int _total; private readonly int[] _x_points; private readonly int[] _y_points; public int CropSizeX => _cropSizeX; public int CropSizeY => _cropSizeY; public int TotalRegions => _total; public ImageScanner(CoreDrawing.System.Drawing.Bitmap image, int cropSize) { _image = image; _bitmapData = _image.LockBits(new System.Drawing.Rectangle(0, 0, image.Width, image.Height), CoreDrawing.System.Drawing.Imaging.ImageLockMode.ReadOnly, CoreDrawing.System.Drawing.Imaging.PixelFormat.Format24bppRgb); _stride = Math.Abs(_bitmapData.Stride); _bytesPerPixel = _stride / image.Width; _cropSizeX = cropSize > 0 ? cropSize : _image.Width; _cropSizeY = cropSize > 0 ? cropSize : _image.Height; _x_points = SplitRange(_image.Width, _cropSizeX, 0).ToArray(); _y_points = SplitRange(_image.Height, _cropSizeY, 0).ToArray(); _total = _x_points.Length * _y_points.Length; } public IEnumerable ScanByRegions() { var tensorIndex = 0; foreach (var x in _x_points) { foreach (var y in _y_points) { var region = new RegionInfo { Index = tensorIndex, X = x, Y = y, CropSizeX = _cropSizeX, CropSizeY = _cropSizeY, Stride = _stride, BytesPerPixel = _bytesPerPixel }; yield return new ImageRegionReader(_bitmapData, region); tensorIndex++; } } } private IEnumerable SplitRange(int size, int cropSize, float overlapProportion) { var stride = (int)(cropSize * (1f - overlapProportion)); var counter = 0; while (true) { var pt = stride * counter; if (pt + cropSize > size) { if (cropSize == size || pt == size) { break; } yield return size - cropSize; break; } else { yield return pt; } counter++; } } public void Dispose() { _image.UnlockBits(_bitmapData); _image.Dispose(); } } }