public void TestWeightedAveragedMerge() { YuvKA.VideoModel.Size testSize = new YuvKA.VideoModel.Size(5, 5); Frame[] inputs = { new Frame(testSize), new Frame(testSize), new Frame(testSize) }; for (int x = 0; x < testSize.Width; x++) { for (int y = 0; y < testSize.Height; y++) { inputs[0][x, y] = new Rgb((byte)(x + y), (byte)(x + y), (byte)(x + y)); inputs[1][x, y] = new Rgb((byte)(x * y), (byte)(x * y), (byte)(x * y)); inputs[2][x, y] = new Rgb((byte)(x ^ y), (byte)(x ^ y), (byte)(x ^ y)); } } WeightedAveragedMergeNode node = new WeightedAveragedMergeNode(); Node.Input testInput = new Node.Input(); node.Inputs.Add(testInput); ObservableCollection <double> testGetWeights = node.Weights; // node.Weights is null -> create weights with default value 1.0 Assert.Contains(1.0, testGetWeights); node.Inputs.Add(testInput); node.Weights[0] = 0; node.Weights[1] = 0.25; node.Inputs.Add(testInput); testGetWeights = node.Weights; // node.Weights has not enough values -> fill up missing weights with 1.0 Assert.Contains(1.0, testGetWeights); Frame[] result = node.Process(inputs, 0); for (int x = 0; x < testSize.Width; x++) { for (int y = 0; y < testSize.Height; y++) { Assert.Equal((byte)((0.25 * inputs[1][x, y].R + inputs[2][x, y].R) / 1.25), result[0][x, y].R); Assert.Equal((byte)((0.25 * inputs[1][x, y].G + inputs[2][x, y].G) / 1.25), result[0][x, y].G); Assert.Equal((byte)((0.25 * inputs[1][x, y].B + inputs[2][x, y].B) / 1.25), result[0][x, y].B); } } WeightedAveragedMergeNode secondNode = new WeightedAveragedMergeNode { Weights = { 0.75, 0.75, 0.75 } }; node.Weights[0] = node.Weights[1] = node.Weights[2] = 0.5; result = node.Process(inputs, 0); Frame[] secondResult = secondNode.Process(inputs, 0); for (int x = 0; x < testSize.Width; x++) { for (int y = 0; y < testSize.Height; y++) { Assert.Equal(result[0][x, y].R, secondResult[0][x, y].R); Assert.Equal(result[0][x, y].G, secondResult[0][x, y].G); Assert.Equal(result[0][x, y].B, secondResult[0][x, y].B); } } }
/// <summary> /// Generates an AnnotatedFrame with randomly filled Data and the given Macroblock decisions. /// </summary> /// <returns> An annotated Frame with random Data and the given Macroblock decisions.</returns> public static AnnotatedFrame GenerateAnnFrame(MacroblockDecision[,] decisions) { var testSize = new YuvKA.VideoModel.Size(8, 8); var output = new AnnotatedFrame(testSize, decisions); for (int x = 0; x < testSize.Width; x++) { for (int y = 0; y < testSize.Height; y++) { output[x, y] = new Rgb((byte)(x + y), (byte)(x + y), (byte)(x + y)); } } return output; }
public void TestBrightnessContrastSaturation() { System.Drawing.Bitmap image = new System.Drawing.Bitmap("..\\..\\..\\..\\resources\\papagei.png"); YuvKA.VideoModel.Size size = new YuvKA.VideoModel.Size(image.Width, image.Height); Frame[] inputFrames = { new Frame(size) }; BrightnessContrastSaturationNode bcsNode = new BrightnessContrastSaturationNode(); // Copy RGB content to the input frame for (int y = 0; y < size.Height; y++) { for (int x = 0; x < size.Width; ++x) { inputFrames[0][x, y] = new Rgb(image.GetPixel(x, y).R, image.GetPixel(x, y).G, image.GetPixel(x, y).B); } } bcsNode.Contrast = 0.8; // Process the input frame. Reuse the frames object by writing back to it Frame[] outputFrames = bcsNode.Process(inputFrames, 0); // Copy RGB content of the processed frame to the output image for (int y = 0; y < size.Height; y++) { for (int x = 0; x < size.Width; ++x) { // Reuse the created image object image.SetPixel(x, y, System.Drawing.Color.FromArgb(outputFrames[0][x, y].R, outputFrames[0][x, y].G, outputFrames[0][x, y].B)); } } image.Save("..\\..\\..\\..\\output\\papagei-bcs-" + (int)(bcsNode.Contrast * 10) + ".png"); // Set contrast to a negative value and brightness to the maximum bcsNode.Contrast = -0.6; bcsNode.Brightness = 1; outputFrames = bcsNode.Process(inputFrames, 0); for (int y = 0; y < size.Height; y++) { for (int x = 0; x < size.Width; ++x) { // Reuse the created image object image.SetPixel(x, y, System.Drawing.Color.FromArgb(outputFrames[0][x, y].R, outputFrames[0][x, y].G, outputFrames[0][x, y].B)); } } bcsNode.Brightness = -1; bcsNode.Process(inputFrames, 0); image.Save("..\\..\\..\\..\\output\\papagei-bcs-" + (int)(bcsNode.Contrast * 10) + ".png"); }
public void TestHistogramNodeRGB() { // Generates an array of 1 Frame with randomly filled Data YuvKA.VideoModel.Size testSize = new YuvKA.VideoModel.Size(5, 5); Frame[] inputs = { new Frame(testSize) }; for (int x = 0; x < testSize.Width; x++) { for (int y = 0; y < testSize.Height; y++) { inputs[0][x, y] = new Rgb((byte)(x + y), (byte)(x + y), (byte)(x + y)); } } // Generate all RGB HistogramNode once HistogramNode histNodeR = new HistogramNode(); histNodeR.Type = HistogramType.R; HistogramNode histNodeG = new HistogramNode(); histNodeG.Type = HistogramType.G; HistogramNode histNodeB = new HistogramNode(); histNodeB.Type = HistogramType.B; histNodeR.Process(inputs, 0); histNodeG.Process(inputs, 0); histNodeB.Process(inputs, 0); // Calculate expected results independently from Histogram methods. int[] value = new int[3]; int[,] intData = new int[256, 3]; for (int x = 0; x < inputs[0].Size.Width; x++) { for (int y = 0; y < inputs[0].Size.Height; y++) { value[0] = inputs[0][x, y].R; value[1] = inputs[0][x, y].G; value[2] = inputs[0][x, y].B; intData[value[0], 0]++; intData[value[1], 1]++; intData[value[2], 2]++; } } int numberOfPixels = inputs[0].Size.Height * inputs[0].Size.Width; for (int i = 0; i < 256; i++) { Assert.Equal(histNodeR.Data[i], (double)intData[i, 0] / numberOfPixels); Assert.Equal(histNodeG.Data[i], (double)intData[i, 1] / numberOfPixels); Assert.Equal(histNodeB.Data[i], (double)intData[i, 2] / numberOfPixels); } }
/// <summary> /// Generates an AnnotatedFrame with randomly filled Data and the given Macroblock decisions. /// </summary> /// <returns> An annotated Frame with random Data and the given Macroblock decisions.</returns> public static AnnotatedFrame GenerateAnnFrame(MacroblockDecision[,] decisions) { var testSize = new YuvKA.VideoModel.Size(8, 8); var output = new AnnotatedFrame(testSize, decisions); for (int x = 0; x < testSize.Width; x++) { for (int y = 0; y < testSize.Height; y++) { output[x, y] = new Rgb((byte)(x + y), (byte)(x + y), (byte)(x + y)); } } return(output); }
/// <summary> /// A Process method to be used by AnonymousNodes. /// Generates an array of 1 Frame and 2 AnnotatedFrame with randomly filled Data. /// </summary> /// <param name="inputs">The inputs used for processing. This parameter is not used here.</param> /// <param name="tick"> The current index of the frame. This parameter is not used here.</param> /// <returns> An array of generated Frames.</returns> public static Frame[] SourceNode(Frame[] inputs, int tick) { var testSize = new YuvKA.VideoModel.Size(8, 8); Frame[] outputs = { GenerateAnnFrame(new MacroblockDecision[,] { { new MacroblockDecision { Movement = new Vector(0.0, 0.0), PartitioningDecision = MacroblockPartitioning.Inter4x4 }, new MacroblockDecision { Movement = new Vector(0.0, 0.0), PartitioningDecision = MacroblockPartitioning.Inter4x4 }, new MacroblockDecision { Movement = new Vector(0.0, 0.0), PartitioningDecision = MacroblockPartitioning.Inter8x4 } } }), new Frame(testSize), GenerateAnnFrame(new MacroblockDecision[,] { { new MacroblockDecision { Movement = new Vector(0.0, 0.0), PartitioningDecision = MacroblockPartitioning.Intra4x4 }, new MacroblockDecision { Movement = new Vector(0.0, 0.0), PartitioningDecision = MacroblockPartitioning.Intra4x4 }, new MacroblockDecision { Movement = new Vector(0.0, 0.0), PartitioningDecision = MacroblockPartitioning.Inter8x4 } } }), }; for (int x = 0; x < testSize.Width; x++) { for (int y = 0; y < testSize.Height; y++) { outputs[1][x, y] = new Rgb((byte)(x * y), (byte)(x * y), (byte)(x * y)); } } return outputs; }
public void TestHistogramNodeValue() { // Generates an array of 1 Frame with randomly filled Data YuvKA.VideoModel.Size testSize = new YuvKA.VideoModel.Size(5, 5); Frame[] inputs = { new Frame(testSize) }; for (int x = 0; x < testSize.Width; x++) { for (int y = 0; y < testSize.Height; y++) { inputs[0][x, y] = new Rgb((byte)(x + y), (byte)(x + y), (byte)(x + y)); } } // Generate Value HistogramNode once HistogramNode histNodeValue = new HistogramNode(); histNodeValue.Type = HistogramType.Value; histNodeValue.Process(inputs, 0); // Calculate expected results independently from Histogram method. Color rgbValue; int value; int[] intData = new int[256]; for (int x = 0; x < inputs[0].Size.Width; x++) { for (int y = 0; y < inputs[0].Size.Height; y++) { rgbValue = Color.FromArgb(inputs[0][x, y].R, inputs[0][x, y].G, inputs[0][x, y].B); value = (int)(rgbValue.GetBrightness() * 255); intData[value]++; } } int numberOfPixels = inputs[0].Size.Height * inputs[0].Size.Width; for (int i = 0; i < 256; i++) { Assert.Equal(histNodeValue.Data[i], (double)intData[i] / numberOfPixels); } }
/// <summary> /// A Process method to be used by AnonymousNodes. /// Generates an array of 1 Frame and 2 AnnotatedFrame with randomly filled Data. /// </summary> /// <param name="inputs">The inputs used for processing. This parameter is not used here.</param> /// <param name="tick"> The current index of the frame. This parameter is not used here.</param> /// <returns> An array of generated Frames.</returns> public static Frame[] SourceNode(Frame[] inputs, int tick) { var testSize = new YuvKA.VideoModel.Size(8, 8); Frame[] outputs = { GenerateAnnFrame(new MacroblockDecision[, ] { { new MacroblockDecision { Movement = new Vector(0.0, 0.0), PartitioningDecision = MacroblockPartitioning.Inter4x4 }, new MacroblockDecision { Movement = new Vector(0.0, 0.0), PartitioningDecision = MacroblockPartitioning.Inter4x4 }, new MacroblockDecision { Movement = new Vector(0.0, 0.0), PartitioningDecision = MacroblockPartitioning.Inter8x4 } } }), new Frame(testSize), GenerateAnnFrame(new MacroblockDecision[, ] { { new MacroblockDecision { Movement = new Vector(0.0, 0.0), PartitioningDecision = MacroblockPartitioning.Intra4x4 }, new MacroblockDecision { Movement = new Vector(0.0, 0.0), PartitioningDecision = MacroblockPartitioning.Intra4x4 }, new MacroblockDecision { Movement = new Vector(0.0, 0.0), PartitioningDecision = MacroblockPartitioning.Inter8x4 } } }), }; for (int x = 0; x < testSize.Width; x++) { for (int y = 0; y < testSize.Height; y++) { outputs[1][x, y] = new Rgb((byte)(x * y), (byte)(x * y), (byte)(x * y)); } } return(outputs); }
public void TestInverter() { YuvKA.VideoModel.Size testSize = new YuvKA.VideoModel.Size(5, 5); Frame[] inputs = { new Frame(testSize) }; for (int x = 0; x < testSize.Width; x++) { for (int y = 0; y < testSize.Height; y++) { inputs[0][x, y] = new Rgb((byte)(x + y), (byte)(x + y), (byte)(x + y)); } } InverterNode inverter = new InverterNode(); Frame[] result = inverter.Process(inputs, 0); for (int x = 0; x < testSize.Width; x++) { for (int y = 0; y < testSize.Height; y++) { Assert.Equal(255 - inputs[0][x, y].R, result[0][x, y].R); Assert.Equal(255 - inputs[0][x, y].G, result[0][x, y].G); Assert.Equal(255 - inputs[0][x, y].B, result[0][x, y].B); } } }
public void TestRgbSplit() { YuvKA.VideoModel.Size testSize = new YuvKA.VideoModel.Size(5, 5); Frame[] inputs = { new Frame(testSize) }; for (int x = 0; x < testSize.Width; x++) { for (int y = 0; y < testSize.Height; y++) { inputs[0][x, y] = new Rgb((byte)(x + y), (byte)(x * y), (byte)(x ^ y)); } } RgbSplitNode rgbSplit = new RgbSplitNode(); Frame[] result = rgbSplit.Process(inputs, 0); for (int x = 0; x < testSize.Width; x++) { for (int y = 0; y < testSize.Height; y++) { Assert.Equal(new Rgb((byte)(x + y), 0, 0), result[0][x, y]); Assert.Equal(new Rgb(0, (byte)(x * y), 0), result[1][x, y]); Assert.Equal(new Rgb(0, 0, (byte)(x ^ y)), result[2][x, y]); } } }