private ImagePlane[] Convolution(ImagePlane[] inputPlanes, double[] W, int nOutputPlane, double[] bias) { int width = inputPlanes[0].Width; int height = inputPlanes[0].Height; ImagePlane[] outputPlanes = new ImagePlane[nOutputPlane]; for (int o = 0; o < nOutputPlane; o++) { outputPlanes[o] = new ImagePlane(width - 2, height - 2); } double[] sumValues = new double[nOutputPlane]; double[] biasValues = new double[nOutputPlane]; bias.CopyTo(biasValues, 0); for (int w = 1; w < width - 1; w++) { for (int h = 1; h < height - 1; h++) { biasValues.CopyTo(sumValues, 0); // leaky ReLU bias for (int i = 0; i < inputPlanes.Length; i++) { double i00 = inputPlanes[i].GetValue(w - 1, h - 1); double i10 = inputPlanes[i].GetValue(w, h - 1); double i20 = inputPlanes[i].GetValue(w + 1, h - 1); double i01 = inputPlanes[i].GetValue(w - 1, h); double i11 = inputPlanes[i].GetValue(w, h); double i21 = inputPlanes[i].GetValue(w + 1, h); double i02 = inputPlanes[i].GetValue(w - 1, h + 1); double i12 = inputPlanes[i].GetValue(w, h + 1); double i22 = inputPlanes[i].GetValue(w + 1, h + 1); for (int o = 0; o < nOutputPlane; o++) { int weightIndex = (o * inputPlanes.Length * 9) + (i * 9); double value = sumValues[o]; value += i00 * W[weightIndex++]; value += i10 * W[weightIndex++]; value += i20 * W[weightIndex++]; value += i01 * W[weightIndex++]; value += i11 * W[weightIndex++]; value += i21 * W[weightIndex++]; value += i02 * W[weightIndex++]; value += i12 * W[weightIndex++]; value += i22 * W[weightIndex++]; sumValues[o] = value; } } for (int o = 0; o < nOutputPlane; o++) { double v = sumValues[o]; if (v < 0) { v *= 0.1; } outputPlanes[o].SetValue(w - 1, h - 1, v); } } } return(outputPlanes); }
private ImageChannel Denormalize(ImagePlane imagePlane) { ImageChannel image = new ImageChannel(imagePlane.Width, imagePlane.Height); for (int i = 0; i < imagePlane.Buffer.Length; i++) { double temp = Math.Round(imagePlane.Buffer[i] * 255, MidpointRounding.AwayFromZero); image.Buffer[i] = temp > 255? (byte)255: (byte)temp; } return(image); }
public static ImagePlane[] Deblocking(ImagePlane[][] outputBlocks, int blocksWidth, int blocksHeight) { int blockSize = outputBlocks[0][0].Width; int width = 0; for (int b = 0; b < blocksWidth; b++) { width += outputBlocks[b][0].Width; } int height = 0; for (int b = 0; b < blocksWidth * blocksHeight; b += blocksWidth) { height += outputBlocks[b][0].Height; } //console.log("result image width:" + width + " height:" + height); List <ImagePlane> outputPlanes = new List <ImagePlane>(); // [ planeR, planeG, planeB ] for (int b = 0; b < outputBlocks.Length; b++) { ImagePlane[] block = outputBlocks[b]; int blockWidthIndex = b % blocksWidth; int blockHeightIndex = (int)Math.Floor((double)b / blocksWidth); for (int n = 0; n < block.Length; n++) { if (outputPlanes.Count < n + 1) { outputPlanes.Add(new ImagePlane(width, height)); } else if (outputPlanes[n] == null) { outputPlanes[n] = new ImagePlane(width, height); } ImagePlane channelBlock = block[n]; for (int w = 0; w < channelBlock.Width; w++) { for (int h = 0; h < channelBlock.Height; h++) { int targetIndexW = blockWidthIndex * blockSize + w; int targetIndexH = blockHeightIndex * blockSize + h; int targetIndex = targetIndexH * width + targetIndexW; double channelValue = channelBlock.GetValue(w, h); outputPlanes[n].Buffer[targetIndex] = channelValue; } } } } return(outputPlanes.ToArray()); }
private ImagePlane Normalize(ImageChannel image) { int width = image.Width; int height = image.Height; ImagePlane imagePlane = new ImagePlane(width, height); if (imagePlane.Buffer.Length != image.Buffer.Length) { throw new Exception("Assertion error: length"); } for (int i = 0; i < image.Buffer.Length; i++) { double temp = image.Buffer[i] / 255.0; imagePlane.Buffer[i] = temp; } return(imagePlane); }
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); }