private ImageChannels UpscaleRgbAsync(Guid taskId, ImageChannels channels, SRCNNModelLayer[] model, int scale, Action <ProgressMessage> progressCallback) { ImagePlane[] inputPlanes = channels.ToArray().Select((image) => { ImageChannel imgResized = scale == 1 ? image : image.Resize(scale); // extrapolation for layer count (each convolution removes outer 1 pixel border) ImageChannel imgExtra = imgResized.Extrapolation(model.Length); return(Normalize(imgExtra)); }).ToArray(); // blocking ImageBlocks imageBlocks = ImagePlane.Blocking(inputPlanes); inputPlanes = null; // init W double[][] weights = GetWeights(model); var outputBlocks = imageBlocks.Blocks.AsParallel() .SelectMany((block, index) => UpscaleBlocks(taskId, model, weights, progressCallback, index + 1, imageBlocks.Blocks.Count, block)) .ToList(); // de-blocking ImagePlane[] outputPlanes = ImagePlane.Deblocking(outputBlocks.ToArray(), imageBlocks.BlocksWidth, imageBlocks.BlocksHeight); if (outputPlanes.Length != 3) { throw new Exception("Output planes must be 3: color channel R, G, B."); } ImageChannels outputChannels = new ImageChannels() { Red = Denormalize(outputPlanes[0]), Green = Denormalize(outputPlanes[1]), Blue = Denormalize(outputPlanes[2]), Alpha = channels.Alpha }; return(outputChannels); }
public static ImageBlocks Blocking(ImagePlane[] initialPlanes) { int widthInput = initialPlanes[0].Width; int heightInput = initialPlanes[0].Height; int blocksWidth = (int)Math.Ceiling((double)(widthInput - Overlap) / (BlockSize - Overlap)); int blocksHeight = (int)Math.Ceiling((double)(heightInput - Overlap) / (BlockSize - Overlap)); int blocks = blocksWidth * blocksHeight; ImageBlocks inputBlocks = new ImageBlocks() // [ [ block0_R, block0_G, block0_B ], [ block1_R, ...] ... ] { BlocksWidth = blocksWidth, BlocksHeight = blocksHeight }; for (int b = 0; b < blocks; b++) { int blockWidthIndex = b % blocksWidth; int blockHeightIndex = (int)Math.Floor((double)(b / blocksWidth)); int blockWidth; int blockHeight; if (blockWidthIndex == blocksWidth - 1) { blockWidth = widthInput - ((BlockSize - Overlap) * blockWidthIndex); // right end block } else { blockWidth = BlockSize; } if (blockHeightIndex == blocksHeight - 1) { blockHeight = heightInput - ((BlockSize - Overlap) * blockHeightIndex); // bottom end block } else { blockHeight = BlockSize; } ImagePlane[] channels = new ImagePlane[initialPlanes.Length]; for (int i = 0; i < channels.Length; i++) { channels[i] = new ImagePlane(blockWidth, blockHeight); } for (int w = 0; w < blockWidth; w++) { for (int h = 0; h < blockHeight; h++) { for (int n = 0; n < initialPlanes.Length; n++) { int targetIndexW = blockWidthIndex * (BlockSize - Overlap) + w; int targetIndexH = blockHeightIndex * (BlockSize - Overlap) + h; ImagePlane channel = initialPlanes[n]; double channelValue = channel.GetValue(targetIndexW, targetIndexH); channels[n].SetValue(w, h, channelValue); } } } inputBlocks.Blocks.Add(channels); } return(inputBlocks); }