// One byte images only private byte[] PerformConvolution(byte[] inImage, Box size, ConvolutionKernel kernel) { byte[] outImage = new byte[inImage.Length]; int kernelHeight = kernel.Kernel.GetLength(0); int kernelWidth = kernel.Kernel.GetLength(1); int kernelCenterRow = kernelWidth / 2; int kernelCenterCol = kernelHeight / 2; int accumulator; for (int imageRow = 0; imageRow < size.Height; ++imageRow) { for (int imageCol = 200; imageCol < size.Width - 200; ++imageCol) { byte outValue = 0; accumulator = 0; for (int kernelRow = 0; kernelRow < kernelHeight; ++kernelRow) { for (int kernelCol = 0; kernelCol < kernelWidth; ++kernelCol) { accumulator += kernel.Kernel[kernelRow, kernelCol] * GetPixelAt(inImage, size, imageRow + (kernelRow - kernelCenterRow), imageCol + (kernelCol - kernelCenterCol), 0); } } outValue = (byte)((float)accumulator * kernel.Multiplier); outImage[imageRow * size.Width + imageCol] = outValue; } } return(outImage); }
public MNISTConvolutionNN(Variable features, DeviceDescriptor device, int outputDesmintations = 10, string classifierName = "classifierOutput") { // Set local private variables this.device = device; this.features = features; // Create and connect a convolution neutral network for MNIST // 1. Convolution layer I // Kernel size = 3 x 3, Input size = 28 x 28 x 1, Output size = 12 x 12 x 30 ConvolutionKernel kernel1 = new ConvolutionKernel() { width = 3, height = 3, input_channel = 1, output_map_channel = 30, vStride = 2, hStride = 2, poolingWindowWidth = 3, poolingWindowHeight = 3, }; Function convolutionPooling1 = ConvolutionWithMaxPooling(inputLayer: features, kernel: kernel1); // 2. Convolution layer II // Kernel size = 3 x 3, Input size = 12 x 12 x 30, Output size = 8 x 8 x 10 ConvolutionKernel kernel2 = new ConvolutionKernel() { width = 3, height = 3, input_channel = kernel1.output_map_channel, output_map_channel = 10, vStride = 1, hStride = 1, poolingWindowWidth = 3, poolingWindowHeight = 3, }; Function convolutionPooling2 = ConvolutionWithMaxPooling(inputLayer: convolutionPooling1, kernel: kernel2); // 3. Reshape layer Function reshaped = Flatten(convolutionPooling2); // int planeDimension = ((Variable)convolutionPooling2).Shape.Dimensions.Aggregate((d1, d2) => d1 * d2); // Function reshaped = Reshape(convolutionPooling2, new int[] { planeDimension }); // 4. Fully connected layer I Function fullyConnectedI = Sigmoid(FullyConnectedLinearLayer(reshaped, 240, "outputl1"), "SigmoidI"); // 5. Fully connected layer II Function fullyConnectedII = Sigmoid(FullyConnectedLinearLayer(fullyConnectedI, 100, "outputl2"), "SigmoidII"); // 6. Fully connected layer III Function fullyConnectedIII = FullyConnectedLinearLayer(fullyConnectedII, outputDesmintations, "outputl3"); // 7. Softmax layer Function softmaxLayer = Softmax(fullyConnectedIII, classifierName); cnn_function = softmaxLayer; }
public void HorizontalEdgeBi(Bitmap image) { int[,] matrix = { { -1, 0, 1 } }; Bitmap destination = DuplicateBitmap(image); var convolveOp = new ConvolveOp(); var kernel = new ConvolutionKernel { Size = 3, Matrix = matrix }; destination = convolveOp.Convolve(image, kernel); }
public new void VerticalEdgeDetector(Bitmap source) { int[,] matrix = { { -1, 0, 1 } }; Bitmap destination = DuplicateBitmap(source); var convolveOp = new ConvolveOp(); var kernel = new ConvolutionKernel { Size = 3, Matrix = matrix }; destination = convolveOp.Convolve(source, kernel); }
public void FullEdgeDetector(Bitmap source) { int[,] verticalMatrix = { { -1, 0, 1 }, { -2, 0, 2 }, { -1, 0, 1 } }; int[,] horizontalMatrix = { { -1, -2, -1 }, { 0, 0, 0 }, { 1, 2, 1 } }; Bitmap i1 = CreateBlankBitmap(source); Bitmap i2 = CreateBlankBitmap(source); var convolveOp = new ConvolveOp(); var kernel = new ConvolutionKernel { Size = 3, Matrix = verticalMatrix }; i1 = convolveOp.Convolve(source, kernel); kernel = new ConvolutionKernel(); kernel.Size = 3; kernel.Matrix = horizontalMatrix; i2 = convolveOp.Convolve(source, kernel); int w = source.Width; int h = source.Height; for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { float sum = 0.0f; sum += GetBrightness(i1, x, y); sum += GetBrightness(i2, x, y); SetBrightness(source, x, y, Math.Min(1.0f, sum)); } } }
private Function ConvolutionWithMaxPooling(Variable inputLayer, ConvolutionKernel kernel) { double convWScale = 0.26; // Configure a convolution layer Parameter conv_para = new Parameter( shape: new int[] { kernel.width, kernel.height, kernel.input_channel, kernel.output_map_channel }, dataType: DataType.Float, initializer: GlorotUniformInitializer(convWScale, -1, 2), device: device); Function convolution = LeakyReLU(operand: Convolution(convolutionMap: conv_para, operand: inputLayer, strides: new int[] { 1, 1, kernel.input_channel }), alpha: 0.3f); Function pooling = Pooling(operand: convolution, poolingType: PoolingType.Max, poolingWindowShape: new int[] { kernel.poolingWindowWidth, kernel.poolingWindowHeight }, strides: new int[] { kernel.hStride, kernel.vStride }, autoPadding: new bool[] { true }); return(pooling); }
public void VerticalEdgeBitmap(Bitmap image) { Bitmap imageCopy = DuplicateBitmap(image); int[,] data = { { -1, 0, 1 }, { -1, 0, 1 }, { -1, 0, 1 }, { -1, 0, 1 } }; ConvolveOp convolveOp = new ConvolveOp(); var kernel = new ConvolutionKernel(); kernel.Size = 3; kernel.Matrix = data; imageCopy = convolveOp.Convolve(image, kernel); }
public void HorizontalEdgeDetector(Bitmap source) { Bitmap destination = DuplicateBitmap(source); int[,] matrix = { { -1, -2, -1 }, { 0, 0, 0 }, { 1, 2, 1 } }; var convolveOp = new ConvolveOp(); var kernel = new ConvolutionKernel { Size = 3, Matrix = matrix }; destination = convolveOp.Convolve(source, kernel); }
public void VerticalEdgeDetector(Bitmap source) { Bitmap destination = DuplicateBitmap(source); int[,] datset1 = { { -1, 0, 1 }, { -2, 0, 2 }, { -1, 0, 1 } }; var convolveOp = new ConvolveOp(); var kernel = new ConvolutionKernel { Size = 3, Matrix = datset1 }; destination = convolveOp.Convolve(source, kernel); }
public GestureOverlay() { InitializeComponent(); SetStyle(ControlStyles.AllPaintingInWmPaint, true); SetStyle(ControlStyles.UserPaint, true); var outlineDivisor = 5700; var outlineBias = -1000; BlurFilter = new ConvolutionKernel( outlineDivisor, outlineBias, 0, 0, 0, 1000, 0, 0, 0, 0, 0, 1000, 2000, 1000, 0, 0, 0, 1000, 2000, 4000, 2000, 1000, 0, 1000, 2000, 4000, -44000, 4000, 2000, 1000, 0, 1000, 2000, 4000, 2000, 1000, 0, 0, 0, 1000, 2000, 1000, 0, 0, 0, 0, 0, 1000, 0, 0, 0 ); }
public void ApplyConvolution(ConvolutionKernel k) { ApplyConvolution(this, k); }
/// <summary> /// /// </summary> /// <param name="x"></param> /// <param name="bw"></param> /// <param name="bwSel"></param> /// <param name="adjust"></param> /// <param name="kernel"></param> /// <param name="weights"></param> /// <param name="width"></param> /// <param name="widthSel"></param> /// <param name="n"></param> /// <param name="from"></param> /// <param name="to"></param> /// <param name="cut"></param> /// <remarks>Adapted from the R-project (www.r-project.org), Version 2.72, file density.R</remarks> public static ProbabilityDensityResult ProbabilityDensity( this IReadOnlyList <double> x, double bw, string bwSel, double adjust, ConvolutionKernel kernel, IReadOnlyList <double> weights, double width, string widthSel, int n, double from, double to, double cut // default: 3 ) { double wsum; if (null == weights) { weights = VectorMath.GetConstantVector(1.0 / x.Count, x.Count); wsum = 1; } else { wsum = weights.Sum(); } double totMass = 1; int n_user = n; n = Math.Max(n, 512); if (n > 512) { n = BinaryMath.NextPowerOfTwoGreaterOrEqualThan(n); } if (bw.IsNaN() && !(width.IsNaN() && null == widthSel)) { if (!width.IsNaN()) { // S has width equal to the length of the support of the kernel // except for the gaussian where it is 4 * sd. // R has bw a multiple of the sd. double fac = 1; switch (kernel) { case ConvolutionKernel.Gaussian: fac = 4; break; case ConvolutionKernel.Rectangular: fac = 2 * Math.Sqrt(3); break; case ConvolutionKernel.Triangular: fac = 2 * Math.Sqrt(6); break; case ConvolutionKernel.Epanechnikov: fac = 2 * Math.Sqrt(5); break; case ConvolutionKernel.Biweight: fac = 2 * Math.Sqrt(7); break; case ConvolutionKernel.Cosine: fac = 2 / Math.Sqrt(1 / 3 - 2 / (Math.PI * Math.PI)); break; case ConvolutionKernel.Optcosine: fac = 2 / Math.Sqrt(1 - 8 / (Math.PI * Math.PI)); break; default: throw new ArgumentException("Unknown convolution kernel"); } bw = width / fac; } else { bwSel = widthSel; } } if (null != bwSel) { if (x.Count < 2) { throw new ArgumentException("need at least 2 points to select a bandwidth automatically"); } switch (bwSel.ToLowerInvariant()) { case "nrd0": //nrd0 = bw.nrd0(x), break; case "nrd": //nrd = bw.nrd(x), break; case "ucv": //ucv = bw.ucv(x), break; case "bcv": //bcv = bw.bcv(x), break; case "sj": //sj = , "sj-ste" = bw.SJ(x, method="ste"), break; case "sj-dpi": //"sj-dpi" = bw.SJ(x, method="dpi"), break; default: throw new ArgumentException("Unknown bandwith selection rule: " + bwSel.ToString()); } } if (!RMath.IsFinite(bw)) { throw new ArithmeticException("Bandwidth is not finite"); } bw = adjust * bw; if (!(bw > 0)) { throw new ArithmeticException("Bandwith is not positive"); } if (from.IsNaN()) { from = x.Min() - cut * bw; } if (to.IsNaN()) { to = x.Max() + cut * bw; } if (!RMath.IsFinite(from)) { throw new ArithmeticException("non-finite 'from'"); } if (!to.IsFinite()) { throw new ArithmeticException("non-finite 'to'"); } double lo = from - 4 * bw; double up = to + 4 * bw; var y = new DoubleVector(2 * n); MassDistribution(x, weights, lo, up, y, n); y.Multiply(totMass); var kords = new DoubleVector(2 * n); kords.FillWithLinearSequenceGivenByStartAndEnd(0, 2 * (up - lo)); for (int i = n + 1, j = n - 1; j >= 0; i++, j--) { kords[i] = -kords[j]; } switch (kernel) { case ConvolutionKernel.Gaussian: kords.Map(new Probability.NormalDistribution(0, bw).PDF); break; case ConvolutionKernel.Rectangular: double a = bw * Math.Sqrt(3); kords.Map(delegate(double xx) { return(Math.Abs(xx) < a ? 0.5 / a : 0); }); break; case ConvolutionKernel.Triangular: a = bw * Math.Sqrt(6); kords.Map(delegate(double xx) { return(Math.Abs(xx) < a ? (1 - Math.Abs(xx) / a) / a : 0); }); break; case ConvolutionKernel.Epanechnikov: a = bw * Math.Sqrt(5); kords.Map(delegate(double xx) { return(Math.Abs(xx) < a ? 0.75 * (1 - RMath.Pow2(Math.Abs(xx) / a)) / a : 0); }); break; case ConvolutionKernel.Biweight: a = bw * Math.Sqrt(7); kords.Map(delegate(double xx) { return(Math.Abs(xx) < a ? 15.0 / 16.0 * RMath.Pow2(1 - RMath.Pow2(Math.Abs(xx) / a)) / a : 0); }); break; case ConvolutionKernel.Cosine: a = bw / Math.Sqrt(1.0 / 3 - 2 / RMath.Pow2(Math.PI)); kords.Map(delegate(double xx) { return(Math.Abs(xx) < a ? (1 + Math.Cos(Math.PI * xx / a)) / (2 * a) : 0); }); break; case ConvolutionKernel.Optcosine: a = bw / Math.Sqrt(1 - 8 / RMath.Pow2(Math.PI)); kords.Map(delegate(double xx) { return(Math.Abs(xx) < a ? Math.PI / 4 * Math.Cos(Math.PI * xx / (2 * a)) / a : 0); }); break; default: throw new ArgumentException("Unknown convolution kernel"); } var result = new DoubleVector(2 * n); Fourier.FastHartleyTransform.CyclicRealConvolution(y.GetInternalData(), kords.GetInternalData(), result.GetInternalData(), 2 * n, null); y.Multiply(1.0 / (2 * n)); VectorMath.MaxOf(y, 0, y); var xords = VectorMath.CreateEquidistantSequenceByStartEndLength(lo, up, n); var xu = VectorMath.CreateEquidistantSequenceByStartEndLength(from, to, n_user); double[] res2 = new double[xu.Length]; Interpolation.LinearInterpolation.Interpolate(xords, result, n, xu, xu.Length, 0, out res2); return(new ProbabilityDensityResult() { X = xu, Y = VectorMath.ToROVector(res2), Bandwidth = bw }); }
static FrameManager() { _instance = new FrameManager(); _sensor = KinectSensor.GetDefault(); _frameResolutions[SourceType.COLOR] = Box.S_1920_1080; _frameResolutions[SourceType.GREEN_SCREEN] = Box.S_1920_1080; _frameResolutions[SourceType.DEPTH] = Box.S_512_424; _frameResolutions[SourceType.INFRARED] = Box.S_512_424; _frameResolutions[SourceType.BODY_INDEX] = Box.S_512_424; _frameResolutions[SourceType.BACKGROUND] = _frameResolutions[SourceType.GREEN_SCREEN]; foreach (SourceType thisSourceType in _frameResolutions.Keys) { _displayableBuffers[thisSourceType] = new byte[_frameResolutions[thisSourceType].Area * (_outputPixelFormat.BitsPerPixel / 8)]; } _bodyIndexToColorMap.Add(0, 0xFF0000FF); // BLUE _bodyIndexToColorMap.Add(1, 0x00FF00FF); // GREEN _bodyIndexToColorMap.Add(2, 0x0000FFFF); // RED _bodyIndexToColorMap.Add(3, 0x00FFFFFF); // YELLOW _bodyIndexToColorMap.Add(4, 0xFF00FFFF); // PURPLE _bodyIndexToColorMap.Add(5, 0xFFFFFFFF); // WHITE foreach (int bodyIndex in _bodyIndexToColorMap.Keys) { _colorToBodyIndexMap.Add(_bodyIndexToColorMap[bodyIndex], bodyIndex); } _instance.InitializeBackgroundImage(); _rawDepthPixels = new UInt16[_frameResolutions[SourceType.DEPTH].Area]; _rawInfraredPixels = new UInt16[_frameResolutions[SourceType.INFRARED].Area]; _rawBodyIndexPixels = new byte[_frameResolutions[SourceType.BODY_INDEX].Area]; _cameraSpacePoints = new CameraSpacePoint[Box.S_1920_1080.Area]; _boxBlur_3_by_3 = new ConvolutionKernel(1.0f / 9f, new int[, ] { { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, }); _boxBlur_5_by_5 = new ConvolutionKernel(1.0f / 25f, new int[, ] { { 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1 }, }); _boxBlur_7_by_7 = new ConvolutionKernel(1.0f / 49f, new int[, ] { { 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1 }, }); _boxBlur_9_by_9 = new ConvolutionKernel(1.0f / 81f, new int[, ] { { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1 } }); _identity_3_by_3 = new ConvolutionKernel(1, new int[, ] { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } }); _gaussianBlur_5_by_5 = new ConvolutionKernel(1.0f / 256.0f, new int[, ] { { 1, 4, 6, 4, 1 }, { 4, 16, 24, 16, 4 }, { 6, 24, 36, 24, 6 }, { 4, 16, 24, 16, 4 }, { 1, 4, 6, 4, 1 }, }); _gaussianBlur_3_by_3 = new ConvolutionKernel(1.0f / 16.0f, new int[, ] { { 1, 2, 1 }, { 2, 4, 2 }, { 1, 2, 1 } }); _edgeDetection = new ConvolutionKernel(1.0f, new int[, ] { { -1, -1, -1 }, { -1, 8, -1 }, { -1, -1, -1 } }); /* * _experimental = new ConvolutionKernel(1, new float[,] { * { 0.00401f, 0.005895f, 0.007763f, 0.009157f, 0.009675f, 0.009157f, 0.007763f, 0.005895f, 0.00401f}, * { 0.005895f, 0.008667f, 0.011412f, 0.013461f, 0.014223f, 0.013461f, 0.011412f, 0.008667f, 0.005895f}, * { 0.007763f, 0.011412f, 0.015028f, 0.017726f, 0.018729f, 0.017726f, 0.015028f, 0.011412f, 0.007763f}, * { 0.009157f, 0.013461f, 0.017726f, 0.020909f, 0.022092f, 0.020909f, 0.017726f, 0.013461f, 0.009157f}, * { 0.009675f, 0.014223f, 0.018729f, 0.022092f, 0.023342f, 0.022092f, 0.018729f, 0.014223f, 0.009675f}, * { 0.009157f, 0.013461f, 0.017726f, 0.020909f, 0.022092f, 0.020909f, 0.017726f, 0.013461f, 0.009157f}, * { 0.007763f, 0.011412f, 0.015028f, 0.017726f, 0.018729f, 0.017726f, 0.015028f, 0.011412f, 0.007763f}, * { 0.005895f, 0.008667f, 0.011412f, 0.013461f, 0.014223f, 0.013461f, 0.011412f, 0.008667f, 0.005895f}, * { 0.00401f, 0.005895f, 0.007763f, 0.009157f, 0.009675f, 0.009157f, 0.007763f, 0.005895f, 0.00401f} * }); * * _experimental2 = new ConvolutionKernel(1, new float[,] { * { 0.000518f, 0.021715f, 0.00051f}, * { 0.021715f, 0.91107f , 0.021715f}, * { 0.000518f, 0.021715f, 0.000518f } * }); */ }
/// <summary> /// /// </summary> /// <param name="x"></param> /// <param name="bw"></param> /// <param name="bwSel"></param> /// <param name="adjust"></param> /// <param name="kernel"></param> /// <param name="weights"></param> /// <param name="width"></param> /// <param name="widthSel"></param> /// <param name="n"></param> /// <param name="from"></param> /// <param name="to"></param> /// <param name="cut"></param> /// <remarks>Adapted from the R-project (www.r-project.org), Version 2.72, file density.R</remarks> public static ProbabilityDensityResult ProbabilityDensity( this IROVector x, double bw, string bwSel, double adjust, ConvolutionKernel kernel, IROVector weights, double width, string widthSel, int n, double from, double to, double cut // default: 3 ) { double wsum; if (null == weights) { weights = VectorMath.GetConstantVector(1.0 / x.Length, x.Length); wsum = 1; } else { wsum = weights.Sum(); } double totMass = 1; int n_user = n; n = Math.Max(n, 512); if (n > 512) n = BinaryMath.NextPowerOfTwoGreaterOrEqualThan(n); if (bw.IsNaN() && !(width.IsNaN() && null == widthSel)) { if (!width.IsNaN()) { // S has width equal to the length of the support of the kernel // except for the gaussian where it is 4 * sd. // R has bw a multiple of the sd. double fac = 1; switch (kernel) { case ConvolutionKernel.Gaussian: fac = 4; break; case ConvolutionKernel.Rectangular: fac = 2 * Math.Sqrt(3); break; case ConvolutionKernel.Triangular: fac = 2 * Math.Sqrt(6); break; case ConvolutionKernel.Epanechnikov: fac = 2 * Math.Sqrt(5); break; case ConvolutionKernel.Biweight: fac = 2 * Math.Sqrt(7); break; case ConvolutionKernel.Cosine: fac = 2 / Math.Sqrt(1 / 3 - 2 / (Math.PI * Math.PI)); break; case ConvolutionKernel.Optcosine: fac = 2 / Math.Sqrt(1 - 8 / (Math.PI * Math.PI)); break; default: throw new ArgumentException("Unknown convolution kernel"); } bw = width / fac; } else { bwSel = widthSel; } } if (null != bwSel) { if (x.Length < 2) throw new ArgumentException("need at least 2 points to select a bandwidth automatically"); switch (bwSel.ToLowerInvariant()) { case "nrd0": //nrd0 = bw.nrd0(x), break; case "nrd": //nrd = bw.nrd(x), break; case "ucv": //ucv = bw.ucv(x), break; case "bcv": //bcv = bw.bcv(x), break; case "sj": //sj = , "sj-ste" = bw.SJ(x, method="ste"), break; case "sj-dpi": //"sj-dpi" = bw.SJ(x, method="dpi"), break; default: throw new ArgumentException("Unknown bandwith selection rule: " + bwSel.ToString()); } } if (!RMath.IsFinite(bw)) throw new ArithmeticException("Bandwidth is not finite"); bw = adjust * bw; if (!(bw > 0)) throw new ArithmeticException("Bandwith is not positive"); if (from.IsNaN()) from = x.GetMinimum() - cut * bw; if (to.IsNaN()) to = x.GetMaximum() + cut * bw; if (!RMath.IsFinite(from)) throw new ArithmeticException("non-finite 'from'"); if (!to.IsFinite()) throw new ArithmeticException("non-finite 'to'"); double lo = from - 4 * bw; double up = to + 4 * bw; var y = new DoubleVector(2 * n); MassDistribution(x, weights, lo, up, y, n); y.Multiply(totMass); var kords = new DoubleVector(2 * n); kords.FillWithLinearSequenceGivenByStartEnd(0, 2 * (up - lo)); for (int i = n + 1, j = n - 1; j >= 0; i++, j--) kords[i] = -kords[j]; switch (kernel) { case ConvolutionKernel.Gaussian: kords.Apply(new Probability.NormalDistribution(0, bw).PDF); break; case ConvolutionKernel.Rectangular: double a = bw * Math.Sqrt(3); kords.Apply(delegate(double xx) { return Math.Abs(xx) < a ? 0.5 / a : 0; }); break; case ConvolutionKernel.Triangular: a = bw * Math.Sqrt(6); kords.Apply(delegate(double xx) { return Math.Abs(xx) < a ? (1 - Math.Abs(xx) / a) / a : 0; }); break; case ConvolutionKernel.Epanechnikov: a = bw * Math.Sqrt(5); kords.Apply(delegate(double xx) { return Math.Abs(xx) < a ? 0.75 * (1 - RMath.Pow2(Math.Abs(xx) / a)) / a : 0; }); break; case ConvolutionKernel.Biweight: a = bw * Math.Sqrt(7); kords.Apply(delegate(double xx) { return Math.Abs(xx) < a ? 15.0 / 16.0 * RMath.Pow2(1 - RMath.Pow2(Math.Abs(xx) / a)) / a : 0; }); break; case ConvolutionKernel.Cosine: a = bw / Math.Sqrt(1.0 / 3 - 2 / RMath.Pow2(Math.PI)); kords.Apply(delegate(double xx) { return Math.Abs(xx) < a ? (1 + Math.Cos(Math.PI * xx / a)) / (2 * a) : 0; }); break; case ConvolutionKernel.Optcosine: a = bw / Math.Sqrt(1 - 8 / RMath.Pow2(Math.PI)); kords.Apply(delegate(double xx) { return Math.Abs(xx) < a ? Math.PI / 4 * Math.Cos(Math.PI * xx / (2 * a)) / a : 0; }); break; default: throw new ArgumentException("Unknown convolution kernel"); } var result = new DoubleVector(2 * n); Fourier.FastHartleyTransform.CyclicRealConvolution(y.GetInternalData(), kords.GetInternalData(), result.GetInternalData(), 2 * n, null); y.Multiply(1.0 / (2 * n)); VectorMath.Max(y, 0, y); var xords = VectorMath.CreateEquidistantSequenceByStartEndLength(lo, up, n); var xu = VectorMath.CreateEquidistantSequenceByStartEndLength(from, to, n_user); double[] res2 = new double[xu.Length]; Interpolation.LinearInterpolation.Interpolate(xords, result, n, xu, xu.Length, 0, out res2); return new ProbabilityDensityResult() { X = xu, Y = VectorMath.ToROVector(res2), Bandwidth = bw }; }
public static unsafe void ApplyConvolution(ImageChannel <TPixel> img, ConvolutionKernel k) { if (img.Width < 2 || img.Height < 2) { return; } int widthTypeScaled = img.Width * img.Step; int kernelHeight = k.Width; int kernelWidth = k.Height; int scale = k.Scale; int[,] kernel = k.Kernel; int extend = Math.Max(kernelWidth, kernelHeight) / 2; ImageChannel <TPixel> maskImage = new ImageChannel <TPixel>(img.Width + extend * 2, img.Height + extend * 2); FillImage(maskImage, (TPixel)0); //这里效率不高。原本只需要填充四周扩大的部分即可 CopyChannel(img, maskImage, new System.Drawing.Point(0, 0), new System.Drawing.Rectangle(0, 0, img.Width, img.Height), new System.Drawing.Point(extend, extend)); int step = img.Step; int maskStep = maskImage.Step; int width = img.Width; int height = img.Height; TPixel *start = (TPixel *)img.StartIntPtr; TPixel *maskStart = (TPixel *)maskImage.StartIntPtr; // 复制边界像素 TPixel *dstStart = maskStart + extend; int maskWidth = img.Width + extend * 2; int maskHeight = img.Height + extend * 2; TPixel *dstContentStart = maskStart + extend + maskWidth * extend; // 复制上方的像素 for (int y = 0; y < extend; y++) { TPixel *lineStart = dstStart + y * maskWidth; TPixel *lineEnd = lineStart + width; TPixel *copyStart = dstContentStart; while (lineStart != lineEnd) { *lineStart = *copyStart; lineStart++; copyStart++; } } // 复制下方的像素 for (int y = height + extend; y < maskHeight; y++) { TPixel *lineStart = dstStart + y * maskWidth; TPixel *lineEnd = lineStart + width; TPixel *copyStart = dstContentStart + height * maskWidth - maskWidth; while (lineStart != lineEnd) { *lineStart = *copyStart; lineStart++; copyStart++; } } // 复制左右两侧的像素 TPixel *dstLine = maskStart + maskWidth * extend; TPixel p = default(TPixel); for (int y = extend; y < height + extend; y++) { p = dstLine[extend]; for (int x = 0; x < extend; x++) { dstLine[x] = p; } p = dstLine[extend + width - 1]; for (int x = width + extend; x < maskWidth; x++) { dstLine[x] = p; } dstLine += maskWidth; } // 复制四个角落的像素 // 左上 p = dstContentStart[0]; for (int y = 0; y < extend; y++) { for (int x = 0; x < extend; x++) { maskStart[y * maskWidth + x] = p; } } // 右上 p = dstContentStart[width - 1]; for (int y = 0; y < extend; y++) { for (int x = width + extend; x < maskWidth; x++) { maskStart[y * maskWidth + x] = p; } } // 左下 p = dstContentStart[(height - 1) * maskWidth]; for (int y = height + extend; y < maskHeight; y++) { for (int x = 0; x < extend; x++) { maskStart[y * maskWidth + x] = p; } } // 右下 p = dstContentStart[(height - 1) * maskWidth + width - 1]; for (int y = height + extend; y < maskHeight; y++) { for (int x = width + extend; x < maskWidth; x++) { maskStart[y * maskWidth + x] = p; } } if (scale == 1) { for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { TValue val = 0; for (int kw = 0; kw < kernelWidth; kw++) { for (int kh = 0; kh < kernelHeight; kh++) { val += maskStart[(h + kh) * maskWidth + (w + kw)] * kernel[kh, kw]; } } start[h * widthTypeScaled + w] = (TPixel)val; } } } else { double factor = 1.0 / scale; for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { TValue val = 0; for (int kw = 0; kw < kernelWidth; kw++) { for (int kh = 0; kh < kernelHeight; kh++) { val += maskStart[(h + kh) * maskWidth + (w + kw)] * kernel[kh, kw]; } } start[h * widthTypeScaled + w] = (TPixel)(val * factor); } } } maskImage.Dispose(); }
public ConvolutionProcessor(GraphicsInterface gi, int width, int height, ConvolutionKernel whichKernel) :base(gi, width, height, Convolution_Frag) { curker = (int)whichKernel; }
public unsafe void ApplyConvolution(ConvolutionKernel k) { int kernelHeight = k.Width; int kernelWidth = k.Height; int scale = k.Scale; int[,] kernel = k.Kernel; int extend = Math.Max(kernelWidth, kernelHeight) / 2; TImage maskImage = new TImage(Width + extend * 2, Height + extend * 2); maskImage.Fill(0);//这里效率不高。原本只需要填充四周扩大的部分即可 maskImage.Copy(this, new System.Drawing.Point(0, 0), new System.Drawing.Rectangle(0, 0, this.Width, this.Height), new System.Drawing.Point(extend, extend)); int width = this.Width; int height = this.Height; TPixel *start = (TPixel *)this.StartIntPtr; // 复制边界像素 TPixel *dstStart = maskImage.Start + extend; int extendWidth = this.Width + extend * 2; int extendHeight = this.Height + extend * 2; // 复制上方的像素 for (int y = 0; y < extend; y++) { TPixel *dstP = dstStart + y * extendWidth; TPixel *srcStart = start; TPixel *srcEnd = srcStart + width; while (srcStart != srcEnd) { *dstP = *srcStart; srcStart++; dstP++; } } // 复制下方的像素 for (int y = height + extend; y < extendHeight; y++) { TPixel *dstP = dstStart + y * extendWidth; TPixel *srcStart = start + (height - 1) * width; TPixel *srcEnd = srcStart + width; while (srcStart != srcEnd) { *dstP = *srcStart; srcStart++; dstP++; } } // 复制左右两侧的像素 TPixel *dstLine = maskImage.Start + extendWidth * extend; TPixel *srcLine = start; TPixel p = default(TPixel); for (int y = extend; y < height + extend; y++) { for (int x = 0; x < extend; x++) { p = srcLine[0]; dstLine[x] = p; } p = srcLine[width - 1]; for (int x = width + extend; x < extendWidth; x++) { dstLine[x] = p; } dstLine += extendWidth; srcLine += width; } // 复制四个角落的像素 // 左上 p = start[0]; for (int y = 0; y < extend; y++) { for (int x = 0; x < extend; x++) { maskImage[y, x] = p; } } // 右上 p = start[width - 1]; for (int y = 0; y < extend; y++) { for (int x = width + extend; x < extendWidth; x++) { maskImage[y, x] = p; } } // 左下 p = start[(height - 1) * width]; for (int y = height + extend; y < extendHeight; y++) { for (int x = 0; x < extend; x++) { maskImage[y, x] = p; } } // 右下 p = start[height * width - 1]; for (int y = height + extend; y < extendHeight; y++) { for (int x = width + extend; x < extendWidth; x++) { maskImage[y, x] = p; } } if (scale == 1) { for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { int val = 0; for (int kw = 0; kw < kernelWidth; kw++) { for (int kh = 0; kh < kernelHeight; kh++) { val += maskImage[h + kh, w + kw] * kernel[kh, kw]; } } start[h * width + w] = (TPixel)val; } } } else { double factor = 1.0 / scale; for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { int val = 0; for (int kw = 0; kw < kernelWidth; kw++) { for (int kh = 0; kh < kernelHeight; kh++) { val += maskImage[h + kh, w + kw] * kernel[kh, kw]; } } start[h * width + w] = (TPixel)(val * factor); } } } maskImage.Dispose(); }