private static ICanvasImage CreateConvolveMatrixEffect(ICanvasImage canvasImage) { var ef = new ConvolveMatrixEffect { Source = canvasImage, KernelWidth = 3, KernelHeight = 3, KernelMatrix = new float[] { -0.0821647644f, 0.917835236f, 0, 0.917835236f, -3.794588f, 1, 0, 1, 0.0821647644f } }; return(ef); }
private ICanvasImage CreateConvolveMatrix() { var convolveEffect = new ConvolveMatrixEffect { Source = bitmapTiger, KernelWidth = 3, KernelHeight = 3, }; float[][] filters = { new float[] { 0, 1, 0, 1, -4, 1, 0, 1, 0 }, new float[] { -2, -1, 0, -1, 1, 1, 0, 1, 2 }, new float[] { -1, -2, -1, -2, 13, -2, -1, -2, -1 }, new float[] { 1f / 9, 1f / 9, 1f / 9, 1f / 9, 1f / 9, 1f / 9, 1f / 9, 1f / 9, 1f / 9 }, }; string[] filterNames = { "Edge detect", "Emboss", "Sharpen", "Box blur", }; // Animation interpolates between different convolve filter matrices. animationFunction = elapsedTime => { int prevFilter = (int)(elapsedTime % filters.Length); int nextFilter = (prevFilter + 1) % filters.Length; float mu = elapsedTime % 1; var convolve = new float[9]; for (int i = 0; i < 9; i++) { convolve[i] = filters[prevFilter][i] * (1 - mu) + filters[nextFilter][i] * mu; } convolveEffect.KernelMatrix = convolve; textLabel = string.Format("{0}\n{{\n {1:0.0}, {2:0.0}, {3:0.0},\n {4:0.0}, {5:0.0}, {6:0.0},\n {7:0.0}, {8:0.0}, {9:0.0}\n}}", filterNames[mu < 0.5 ? prevFilter : nextFilter], convolve[0], convolve[1], convolve[2], convolve[3], convolve[4], convolve[5], convolve[6], convolve[7], convolve[8]); }; return(convolveEffect); }
private ICanvasImage CreateConvolveMatrix() { var convolveEffect = new ConvolveMatrixEffect { Source = bitmapTiger, KernelWidth = 3, KernelHeight = 3, }; float[][] filters = { new float[] { 0, 1, 0, 1, -4, 1, 0, 1, 0 }, new float[] { -2, -1, 0, -1, 1, 1, 0, 1, 2 }, new float[] { -1, -2, -1, -2, 13, -2, -1, -2, -1 }, new float[] { 1f / 9, 1f / 9, 1f / 9, 1f / 9, 1f / 9, 1f / 9, 1f / 9, 1f / 9, 1f / 9 }, }; string[] filterNames = { "Edge detect", "Emboss", "Sharpen", "Box blur", }; // Animation interpolates between different convolve filter matrices. animationFunction = elapsedTime => { int prevFilter = (int)(elapsedTime % filters.Length); int nextFilter = (prevFilter + 1) % filters.Length; float mu = elapsedTime % 1; var convolve = new float[9]; for (int i = 0; i < 9; i++) { convolve[i] = filters[prevFilter][i] * (1 - mu) + filters[nextFilter][i] * mu; } convolveEffect.KernelMatrix = convolve; textLabel = string.Format("{0}\n{{\n {1:0.0}, {2:0.0}, {3:0.0},\n {4:0.0}, {5:0.0}, {6:0.0},\n {7:0.0}, {8:0.0}, {9:0.0}\n}}", filterNames[mu < 0.5 ? prevFilter : nextFilter], convolve[0], convolve[1], convolve[2], convolve[3], convolve[4], convolve[5], convolve[6], convolve[7], convolve[8]); }; return convolveEffect; }
void CreateEffects() { // The Game of Life is a cellular automaton with very simple rules. // Each cell (pixel) can be either alive (white) or dead (black). // The state is updated by: // // - for each cell, count how many of its 8 neighbors are alive // - if less than two, the cell dies from loneliness // - if exactly two, the cell keeps its current state // - if exactly three, the cell become alive // - if more than three, the cell dies from overcrowding // Step 1: use a convolve matrix to count how many neighbors are alive. This filter // also includes the state of the current cell, but with a lower weighting. The result // is an arithmetic encoding where (value / 2) indicates how many neighbors are alive, // and (value % 2) is the state of the cell itself. This is divided by 18 to make it // fit within 0-1 color range. countNeighborsEffect = new ConvolveMatrixEffect { KernelMatrix = new float[] { 2, 2, 2, 2, 1, 2, 2, 2, 2 }, Divisor = 18, BorderMode = EffectBorderMode.Hard, }; // Step 2: use a color transfer table to map the different states produced by the // convolve matrix to whether the cell should live or die. Each pair of entries in // this table corresponds to a certain number of live neighbors. The first of the // pair is the result if the current cell is dead, or the second if it is alive. float[] transferTable = { 0, 0, // 0 live neighbors -> dead cell 0, 0, // 1 live neighbors -> dead cell 0, 1, // 2 live neighbors -> cell keeps its current state 1, 1, // 3 live neighbors -> live cell 0, 0, // 4 live neighbors -> dead cell 0, 0, // 5 live neighbors -> dead cell 0, 0, // 6 live neighbors -> dead cell 0, 0, // 7 live neighbors -> dead cell 0, 0, // 8 live neighbors -> dead cell }; liveOrDieEffect = new DiscreteTransferEffect { Source = countNeighborsEffect, RedTable = transferTable, GreenTable = transferTable, BlueTable = transferTable, }; // Step 3: the algorithm is implemented in terms of white = live, // black = dead, but we invert these colors before displaying the // result, just 'cause I think it looks better that way. invertEffect = new LinearTransferEffect { RedSlope = -1, RedOffset = 1, GreenSlope = -1, GreenOffset = 1, BlueSlope = -1, BlueOffset = 1, }; // Step 4: insert our own DPI compensation effect to stop the system trying to // automatically convert DPI for us. The Game of Life simulation always works // in pixels (96 DPI) regardless of display DPI. Normally, the system would // handle this mismatch automatically and scale the image up as needed to fit // higher DPI displays. We don't want that behavior here, because it would use // a linear filter while we want nearest neighbor. So we insert a no-op DPI // converter of our own. This overrides the default adjustment by telling the // system the source image is already the same DPI as the destination canvas // (even though it really isn't). We'll handle any necessary scaling later // ourselves, using Transform2DEffect to control the interpolation mode. var dpiCompensationEffect = new DpiCompensationEffect { Source = invertEffect, SourceDpi = new Vector2(canvas.Dpi), }; // Step 5: a transform matrix scales up the simulation rendertarget and moves // it to the right part of the screen. This uses nearest neighbor filtering // to avoid unwanted blurring of the cell shapes. transformEffect = new Transform2DEffect { Source = dpiCompensationEffect, InterpolationMode = CanvasImageInterpolation.NearestNeighbor, }; }
public void ProcessFrame(ProcessVideoFrameContext context) { CanvasRenderTarget rt = new CanvasRenderTarget(canvasDevice, context.OutputFrame.Direct3DSurface.Description.Width, context.OutputFrame.Direct3DSurface.Description.Height, 96.0f); using (CanvasBitmap input = CanvasBitmap.CreateFromDirect3D11Surface(canvasDevice, context.InputFrame.Direct3DSurface)) using (CanvasDrawingSession ds = rt.CreateDrawingSession()) { TimeSpan time = context.InputFrame.RelativeTime.HasValue ? context.InputFrame.RelativeTime.Value : new TimeSpan(); float dispX = (float)Math.Cos(time.TotalSeconds) * 75f; float dispY = (float)Math.Sin(time.TotalSeconds) * 75f; ds.Clear(Colors.Black); //var posterizeEffect = new PosterizeEffect() //{ // Source = input, // BlueValueCount = 2, // RedValueCount = 2, // GreenValueCount = 2, //}; var transformEffect = new Transform2DEffect() { Source = input, TransformMatrix = new System.Numerics.Matrix3x2(-1, 0, 0, 1, rt.SizeInPixels.Width, 0), }; var discreteTransferEffect = new DiscreteTransferEffect() { Source = transformEffect, RedTable = new float[] { 0.0f, 1.0f, 1.0f, 1.0f }, GreenTable = new float[] { 0.0f, 1.0f, 1.0f, 1.0f }, BlueTable = new float[] { 0.0f, 1.0f, 1.0f, 1.0f }, AlphaDisable = true, }; var dispMap = new ConvolveMatrixEffect() { KernelMatrix = new float[] { 0, +1, 0, +1, -4, +1, 0, +1, 0, }, Source = discreteTransferEffect, Divisor = 0.2f, }; var modEffect = new ArithmeticCompositeEffect() { Source1 = dispMap, Source2 = dispMap, MultiplyAmount = 1, }; //var finalPosterizeEffect = new PosterizeEffect() //{ // Source = modEffect, // BlueValueCount = 2, // RedValueCount = 2, // GreenValueCount = 2, //}; //var dispMap = new EdgeDetectionEffect() //{ // Source = greyScaleEffect, // Mode = EdgeDetectionEffectMode.Sobel, //}; Rect src = new Rect(rt.SizeInPixels.Width / 3, rt.SizeInPixels.Height / 3, rt.SizeInPixels.Width / 3, rt.SizeInPixels.Height / 3); //ds.DrawImage(input, bottomLeft); //ds.DrawImage(discreteTransferEffect, bottomRight, src); //ds.DrawImage(dispMap, topLeft, src); ds.DrawImage(modEffect, src, src); } int centerX = 0; int centerY = 0; int cubletWidth = 0; int cubletHeight = 0; int analysisAreaX = (int)rt.SizeInPixels.Width * 3 / 10; int analysisWidth = (int)rt.SizeInPixels.Width * 4 / 10; byte[] analysisHorzBytes = rt.GetPixelBytes(analysisAreaX, (int)rt.SizeInPixels.Height / 2, analysisWidth, 1); int analysisAreaY = (int)rt.SizeInPixels.Height * 3 / 10; int analysisHeight = (int)rt.SizeInPixels.Height * 4 / 10; byte[] analysisVertBytes = rt.GetPixelBytes((int)rt.SizeInPixels.Width / 2, analysisAreaY, 1, analysisHeight); int foundLeft = 0; for (int i = 0; i < analysisWidth / 2; i++) { byte b = analysisHorzBytes[4 * (analysisWidth / 2 - i) + 0]; byte g = analysisHorzBytes[4 * (analysisWidth / 2 - i) + 1]; byte r = analysisHorzBytes[4 * (analysisWidth / 2 - i) + 2]; if ((r > 100 || g > 100 || b > 50) && foundLeft == 0) { foundLeft = i; } } int foundRight = 0; for (int i = 0; i < analysisWidth / 2; i++) { byte r = analysisHorzBytes[4 * (analysisWidth / 2 + i) + 0]; byte g = analysisHorzBytes[4 * (analysisWidth / 2 + i) + 1]; byte b = analysisHorzBytes[4 * (analysisWidth / 2 + i) + 2]; if ((r > 100 || g > 100 || b > 50) && foundRight == 0) { foundRight = i; } } int foundTop = 0; for (int i = 0; i < analysisHeight / 2; i++) { byte r = analysisVertBytes[4 * (analysisHeight / 2 - i) + 0]; byte g = analysisVertBytes[4 * (analysisHeight / 2 - i) + 1]; byte b = analysisVertBytes[4 * (analysisHeight / 2 - i) + 2]; if ((r > 100 || g > 100 || b > 50) && foundTop == 0) { foundTop = i; } } int foundBottom = 0; for (int i = 0; i < analysisHeight / 2; i++) { byte r = analysisVertBytes[4 * (analysisHeight / 2 + i) + 0]; byte g = analysisVertBytes[4 * (analysisHeight / 2 + i) + 1]; byte b = analysisVertBytes[4 * (analysisHeight / 2 + i) + 2]; if ((r > 100 || g > 100 || b > 50) && foundBottom == 0) { foundBottom = i; } } centerX = (-foundLeft + foundRight) / 2 + (int)rt.SizeInPixels.Width / 2; centerY = (-foundTop + foundBottom) / 2 + (int)rt.SizeInPixels.Height / 2; cubletWidth = (int)((foundLeft + foundRight) * 1.2f); cubletHeight = (int)((foundTop + foundBottom) * 1.2f); // No 2d arrays in WinRT components? Boo. // "Error C1113 #using failed on 'rubikscuberecognitionwinrt.winmd' RubiksCubeRecognitionLib Vector2[] cubletCenters = new Vector2[3 * 3]; cubletCenters[1 * 3 + 1] = new Vector2(centerX, centerY); cubletCenters[1 * 3 + 0] = new Vector2(centerX, centerY - cubletHeight); cubletCenters[1 * 3 + 2] = new Vector2(centerX, centerY + cubletHeight); cubletCenters[0 * 3 + 1] = new Vector2(centerX - cubletWidth, centerY); cubletCenters[0 * 3 + 0] = new Vector2(centerX - cubletWidth, centerY - cubletHeight); cubletCenters[0 * 3 + 2] = new Vector2(centerX - cubletWidth, centerY + cubletHeight); cubletCenters[2 * 3 + 1] = new Vector2(centerX + cubletWidth, centerY); cubletCenters[2 * 3 + 0] = new Vector2(centerX + cubletWidth, centerY - cubletHeight); cubletCenters[2 * 3 + 2] = new Vector2(centerX + cubletWidth, centerY + cubletHeight); cubeletColorsMutex.WaitOne(); using (CanvasBitmap input = CanvasBitmap.CreateFromDirect3D11Surface(canvasDevice, context.InputFrame.Direct3DSurface)) using (CanvasRenderTarget output = CanvasRenderTarget.CreateFromDirect3D11Surface(canvasDevice, context.OutputFrame.Direct3DSurface)) using (CanvasDrawingSession ds = output.CreateDrawingSession()) { var transformEffect = new Transform2DEffect() { Source = input, TransformMatrix = new System.Numerics.Matrix3x2(-1, 0, 0, 1, output.SizeInPixels.Width, 0), }; Rect src = new Rect(0, 0, output.SizeInPixels.Width, output.SizeInPixels.Height); ds.DrawImage(transformEffect, src, src); // Draw a crosshair on the screen ds.FillRectangle(new Rect(output.SizeInPixels.Width / 2 - 3, output.SizeInPixels.Height / 4, 6, output.SizeInPixels.Height / 2), Colors.Gray); ds.FillRectangle(new Rect(output.SizeInPixels.Width / 4, output.SizeInPixels.Height / 2 - 3, output.SizeInPixels.Width / 2, 6), Colors.Gray); if (true) { for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { int sampleWidth = 2; byte[] cubletBytes = input.GetPixelBytes((int)cubletCenters[(2 - x) * 3 + y].X - sampleWidth / 2, (int)cubletCenters[(2 - x) * 3 + y].Y - sampleWidth / 2, sampleWidth, sampleWidth); int totalR = 0; int totalG = 0; int totalB = 0; for (int i = 0; i < sampleWidth * sampleWidth; i++) { totalB += cubletBytes[4 * i + 0]; totalG += cubletBytes[4 * i + 1]; totalR += cubletBytes[4 * i + 2]; } cubletColors[x * 3 + y] = Color.FromArgb(255, (byte)(totalR / (sampleWidth * sampleWidth)), (byte)(totalG / (sampleWidth * sampleWidth)), (byte)(totalB / (sampleWidth * sampleWidth))); } } for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { ds.FillRectangle((float)cubletCenters[x * 3 + y].X - 12, (float)cubletCenters[x * 3 + y].Y - 12, 24, 24, Colors.Black); ds.FillRectangle((float)cubletCenters[x * 3 + y].X - 10, (float)cubletCenters[x * 3 + y].Y - 10, 20, 20, cubletColors[x * 3 + y]); } } } } cubeletColorsMutex.ReleaseMutex(); }
private void DrawElevation(CanvasDrawingSession drawingSession, Size size, Rect destinationRelative) { if (trackpoints == null) { return; } var foreground = new CanvasSolidColorBrush(drawingSession, Colors.Green); var absoluteDestination = GetAbsoluteDestinationRect(size, destinationRelative); var renderTarget = new CanvasRenderTarget(drawingSession, (float)absoluteDestination.Width, (float)absoluteDestination.Height); _elevationTransform = GetTransformationMatrix(size, destinationRelative); _elevationPoints = GetPolyLinePointsRelative(tp => tp.Coordinate.Elevation, true); using (var ds = renderTarget.CreateDrawingSession()) { var elevationRenderTargetTransform = _elevationTransform * Matrix3x2.CreateTranslation((float)(-destinationRelative.Left * size.Width), (float)(-destinationRelative.Top * size.Height)); var gradientStops = new List <CanvasGradientStop>(); var minInclination = _elevationPoints.Keys.Min(tp => tp.Inclination); var maxInclination = _elevationPoints.Keys.Max(tp => tp.Inclination); var positions = new List <Vector2>(); var pathBuilder = new CanvasPathBuilder(drawingSession); bool first = true; foreach (var point in _elevationPoints) { var position = point.Value; if (first) { pathBuilder.BeginFigure(position); first = false; } else { pathBuilder.AddLine(position); } var mu = (point.Key.Inclination - minInclination) / (maxInclination - minInclination); var color = GenerateColor(1, 1, 1, 4, 2, 1, 128, 127, mu * 2); gradientStops.Add(new CanvasGradientStop { Color = color, Position = position.X }); } pathBuilder.AddLine(new Vector2(1, 1)); pathBuilder.AddLine(new Vector2(0, 1)); pathBuilder.EndFigure(CanvasFigureLoop.Closed); var geometry = CanvasGeometry.CreatePath(pathBuilder); var brush = new CanvasLinearGradientBrush(ds, gradientStops.ToArray(), CanvasEdgeBehavior.Clamp, CanvasAlphaMode.Straight) { StartPoint = new Vector2((float)0, 0), EndPoint = new Vector2((float)1, 0), }; ds.Transform = elevationRenderTargetTransform; ds.FillGeometry(geometry, brush); ds.Transform = Matrix3x2.Identity; } var sharpen = new ConvolveMatrixEffect() { Source = renderTarget, KernelMatrix = new float[] { -1, -1, -1, -1, 9, -1, -1, -1, -1 }, }; //drawingSession.DrawImage(sharpen, (float)absoluteDestination.X, (float)absoluteDestination.Y); drawingSession.DrawImage(renderTarget, (float)absoluteDestination.X, (float)absoluteDestination.Y); }