public async Task UpscaleImage(Guid taskId, byte[] image, int width, int height, Action <ResultMessage> done, Action <ProgressMessage> progress) { TimeSpan timeSpanStart = TimeSpan.FromTicks(DateTime.Now.Ticks); // decompose progress(new ProgressMessage(taskId, UpscallingStatuses.Decompose, "in process")); ImageChannels channels = ImageChannel.ChannelDecompose(image, width, height); progress(new ProgressMessage(taskId, UpscallingStatuses.Decompose, "ready")); // calculate //Scaling all blocks ImageChannels upscaledChannels = await Task.Run(() => UpscaleRgbAsync(taskId, channels, ScaleModel, Scale, progress)); //Scaled all blocks // resize alpha channel ImageChannel imageA = Scale == 1 ? upscaledChannels.Alpha : upscaledChannels.Alpha.Resize(Scale); if (imageA.Buffer.Length != upscaledChannels.Red.Buffer.Length) { throw new Exception("A channel image size must be same with R channel image size"); } upscaledChannels.Alpha = imageA; // recompose progress(new ProgressMessage(taskId, UpscallingStatuses.Compose, "in process")); byte[] upscaledImage = ImageChannel.ChannelCompose(upscaledChannels); progress(new ProgressMessage(taskId, UpscallingStatuses.Compose, "ready")); TimeSpan elapsedTime = TimeSpan.FromTicks(DateTime.Now.Ticks) - timeSpanStart; done(new ResultMessage(taskId, upscaledImage, upscaledChannels.Red.Width, upscaledChannels.Red.Height, elapsedTime)); }
public static ImageChannels ChannelDecompose(byte[] image, int width, int height) { ImageChannel imageR = new ImageChannel(width, height); ImageChannel imageG = new ImageChannel(width, height); ImageChannel imageB = new ImageChannel(width, height); ImageChannel imageA = new ImageChannel(width, height); for (int w = 0; w < width; w++) { for (int h = 0; h < height; h++) { int index = w + (h * width); imageR.Buffer[index] = image[(w * 4) + (h * width * 4)]; imageG.Buffer[index] = image[(w * 4) + (h * width * 4) + 1]; imageB.Buffer[index] = image[(w * 4) + (h * width * 4) + 2]; imageA.Buffer[index] = image[(w * 4) + (h * width * 4) + 3]; } } return(new ImageChannels() { Alpha = imageA, Red = imageR, Green = imageG, Blue = imageB }); }
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); }
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 ImageChannel Resize(double scale) { int width = Width; int height = Height; int scaledWidth = (int)Math.Round(width * scale, MidpointRounding.AwayFromZero); int scaledHeight = (int)Math.Round(height * scale, MidpointRounding.AwayFromZero); ImageChannel scaledImage = new ImageChannel(scaledWidth, scaledHeight); for (int w = 0; w < scaledWidth; w++) { for (int h = 0; h < scaledHeight; h++) { int scaledIndex = w + (h * scaledWidth); int originalWidth = (int)Math.Round((w + 1) / scale, MidpointRounding.AwayFromZero) - 1; int originalHeight = (int)Math.Round((h + 1) / scale, MidpointRounding.AwayFromZero) - 1; int originalImageIndex = originalWidth + (originalHeight * width); scaledImage.Buffer[scaledIndex] = Buffer[originalImageIndex]; } } return(scaledImage); }
public ImageChannel Extrapolation(int px) { int width = Width; int height = Height; ImageChannel extrapolatedImage = new ImageChannel(width + (2 * px), height + (2 * px)); for (int h = 0; h < height + (px * 2); h++) { for (int w = 0; w < width + (px * 2); w++) { int index = w + h * (width + (px * 2)); if (w < px) { // Left outer area if (h < px) { // Left upper area extrapolatedImage.Buffer[index] = Buffer[ToIndex(0, 0, width)]; } else if (px + height <= h) { // Left lower area extrapolatedImage.Buffer[index] = Buffer[ToIndex(0, height - 1, width)]; } else { // Left outer area extrapolatedImage.Buffer[index] = Buffer[ToIndex(0, h - px, width)]; } } else if (px + width <= w) { // Right outer area if (h < px) { // Right upper area extrapolatedImage.Buffer[index] = Buffer[ToIndex(width - 1, 0, width)]; } else if (px + height <= h) { // Right lower area extrapolatedImage.Buffer[index] = Buffer[ToIndex(width - 1, height - 1, width)]; } else { // Right outer area extrapolatedImage.Buffer[index] = Buffer[ToIndex(width - 1, h - px, width)]; } } else if (h < px) { // Upper outer area extrapolatedImage.Buffer[index] = Buffer[ToIndex(w - px, 0, width)]; } else if (px + height <= h) { // Lower outer area extrapolatedImage.Buffer[index] = Buffer[ToIndex(w - px, height - 1, width)]; } else { // Inner area extrapolatedImage.Buffer[index] = Buffer[ToIndex(w - px, h - px, width)]; } } } return(extrapolatedImage); }