Example #1
0
        //NOTE: This ignores gain and iterations
        public static Convolution2D Subtract(Convolution2D orig, Convolution2D filtered, string description = "")
        {
            int width = Math.Min(orig.Width, filtered.Width);
            int height = Math.Min(orig.Height, filtered.Height);

            #region Calculate offsets

            int diffX = orig.Width - filtered.Width;
            int diffY = orig.Height - filtered.Height;

            int offsetOrigX = 0;
            int offsetOrigY = 0;
            int offsetFiltX = 0;
            int offsetFiltY = 0;

            if (diffX > 0)
            {
                offsetOrigX = Subtract_GetOffset(diffX);
            }
            else if (diffX < 0)
            {
                offsetFiltX = Subtract_GetOffset(-diffX);
            }

            if (diffY > 0)
            {
                offsetOrigY = Subtract_GetOffset(diffY);
            }
            else if (diffY < 0)
            {
                offsetFiltY = Subtract_GetOffset(-diffY);
            }

            #endregion

            double[] values = new double[width * height];

            for (int y = 0; y < height; y++)
            {
                int filterY = (offsetFiltY + y) * filtered.Width;
                int origY = (offsetOrigY + y) * orig.Width;
                int valuesY = y * width;

                for (int x = 0; x < width; x++)
                {
                    int filterIndex = filterY + offsetFiltX + x;
                    int origIndex = origY + offsetOrigX + x;

                    values[valuesY + x] = orig.Values[origIndex] - filtered.Values[filterIndex];
                }
            }

            return new Convolution2D(values, width, height, true, description: description);
        }
Example #2
0
 public static Convolution2D Convolute(Convolution2D image, ConvolutionBase2D kernel, string description = "")
 {
     if (kernel is Convolution2D)
     {
         return Convolute_Single(image, (Convolution2D)kernel, description);
     }
     else if (kernel is ConvolutionSet2D)
     {
         return Convolute_Set(image, (ConvolutionSet2D)kernel, description);
     }
     else
     {
         throw new ApplicationException("Unexpected type of kernel: " + kernel.GetType().ToString());
     }
 }
        private void Browse_Click(object sender, RoutedEventArgs e)
        {
            const double MAXMULT = 2;

            try
            {
                var dialog = new Microsoft.Win32.OpenFileDialog();
                dialog.Multiselect = false;
                dialog.Title = "Please select an image";
                bool? result = dialog.ShowDialog();
                if (result == null || !result.Value)
                {
                    return;
                }

                _origConv = UtilityWPF.ConvertToConvolution(new BitmapImage(new Uri(dialog.FileName)));

                lblOrigWidth.Text = _origConv.Width.ToString("N0");
                lblOrigHeight.Text = _origConv.Height.ToString("N0");

                double max = Math.Max(_origConv.Width, _origConv.Height) * MAXMULT;

                trkWidth.Minimum = _origConv.Width;
                trkWidth.Maximum = max;
                trkWidth.Value = _origConv.Width;

                trkHeight.Minimum = _origConv.Height;
                trkHeight.Maximum = max;
                trkHeight.Value = _origConv.Height;

                _timer.IsEnabled = false;       // touching the sliders causes the timer to be enabled

                grdSize.Visibility = Visibility.Visible;

                ShowConvolution(_origConv);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
Example #4
0
        /// <summary>
        /// This is used for calling GetKernelBitmap
        /// </summary>
        /// <returns>
        /// Item1 = The dimensions of the image control (thumbSize, but maintains aspect ratio)
        /// Item2 = How big each pixel should be
        /// </returns>
        public static Tuple<Size, int> GetThumbSizeAndPixelMultiplier(Convolution2D kernel, int thumbSize)
        {
            // Figure out thumb size
            double width, height;
            if (kernel.Width == kernel.Height)
            {
                width = height = thumbSize;
            }
            else if (kernel.Width > kernel.Height)
            {
                width = thumbSize;
                height = Convert.ToDouble(kernel.Height) / Convert.ToDouble(kernel.Width) * thumbSize;
            }
            else
            {
                height = thumbSize;
                width = Convert.ToDouble(kernel.Width) / Convert.ToDouble(kernel.Height) * thumbSize;
            }

            // Figure out pixel size multiplier
            int pixelWidth = Convert.ToInt32(Math.Ceiling(width / kernel.Width));
            int pixelHeight = Convert.ToInt32(Math.Ceiling(height / kernel.Height));

            int pixelMult = Math.Max(pixelWidth, pixelHeight);
            if (pixelMult < 1)
            {
                pixelMult = 1;
            }

            return Tuple.Create(new Size(width, height), pixelMult);
        }
        private static double[][] GetRotations_BW(double[] input, int width, int height)
        {
            Convolution2D conv = new Convolution2D(input, width, height, false);
            Convolution2D conv90 = Convolutions.Rotate_90(conv, true);

            return new[]
            {
                input,
                conv90.Values,
                Convolutions.Rotate_90(conv90, true).Values,
                Convolutions.Rotate_90(conv, false).Values,
            };
        }
        /// <summary>
        /// This just shows the kernel, no options to change it
        /// </summary>
        public void ViewKernel(Convolution2D kernel)
        {
            this.Title = string.Format("{0} - {1}x{2}", TITLE, kernel.Width, kernel.Height);

            panelEdit.Visibility = Visibility.Collapsed;

            StoreKernel(kernel);
        }
            public void UpdateColors(bool isZeroToOne, bool isNegativeRedBlue)
            {
                // Coloring
                ConvolutionResultNegPosColoring coloring;
                if (isZeroToOne)
                {
                    coloring = ConvolutionResultNegPosColoring.BlackWhite;
                }
                else if (isNegativeRedBlue)
                {
                    coloring = ConvolutionResultNegPosColoring.RedBlue;
                }
                else
                {
                    coloring = ConvolutionResultNegPosColoring.Gray;
                }

                // Maximize color range
                double min = this.Bars.Min(o => o.Height);
                double max = this.Bars.Max(o => o.Height);
                double absMax = Math.Max(Math.Abs(min), Math.Abs(max));

                double scale;
                if (Math1D.IsInvalid(absMax) || Math1D.IsNearZero(absMax))
                {
                    scale = 1d;
                }
                else
                {
                    scale = 255d / absMax;
                }

                // Get colors
                double[] values = this.Bars.Select(o => o.Height).ToArray();
                Convolution2D conv = new Convolution2D(values, values.Length, 1, !isZeroToOne);
                byte[][] colors = Convolutions.GetColors(conv, coloring, scale);

                // Apply colors
                for (int cntr = 0; cntr < this.Bars.Length; cntr++)
                {
                    Color color = Color.FromRgb(colors[cntr][1], colors[cntr][2], colors[cntr][3]);

                    Material material = UtilityWPF.GetUnlitMaterial(color);
                    this.Bars[cntr].Model.BackMaterial = material;
                    this.Bars[cntr].Model.Material = material;
                }
            }
        private void StoreKernel(Convolution2D kernel)
        {
            _isProgramaticallyChangingSettings = true;

            _width = kernel.Width;
            _height = kernel.Height;

            // The kernel passed in is probably unit.  Maximize the height so that it looks nice and 3D
            _values = Convolutions.ToMaximized(kernel.Values).ToArray();       // taking ToArray to ensure it's cloned

            if (kernel.IsNegPos)
            {
                radRangeNegPos.IsChecked = true;
            }
            else
            {
                radRangeZeroPos.IsChecked = true;
            }

            txtWidth.Text = _width.ToString();
            txtHeight.Text = _height.ToString();

            _isProgramaticallyChangingSettings = false;

            RedrawAxis();
            RebuildBars();
            PixelValueChanged();

            double dist = Math1D.Avg(_axis.HalfX, _axis.HalfY) * 3;
            Vector3D newPos = _camera.Position.ToVector().ToUnit() * dist;
            _camera.Position = newPos.ToPoint();
        }
Example #9
0
        /// <summary>
        /// This takes the absolute value of each pixel in a convolution
        /// </summary>
        public static Convolution2D Abs(Convolution2D conv, bool toUnit = false)
        {
            double[] values = conv.Values.
                Select(o => Math.Abs(o)).
                ToArray();

            if (toUnit)
            {
                values = ToUnit(values);
            }

            string description = "";
            if (!string.IsNullOrEmpty(conv.Description))
            {
                description = string.Format("Abs({0})", description);
            }

            return new Convolution2D(values, conv.Width, conv.Height, false, conv.Gain, conv.Iterations, conv.ExpandBorder, description);
        }
Example #10
0
        public static Convolution2D ExtendBorders(Convolution2D conv, int width, int height)
        {
            if (width < conv.Width || height < conv.Height)
            {
                throw new ArgumentException(string.Format("The new size can't be smaller than old.  Old={0},{1}  --  New={2},{3}", conv.Width, conv.Height, width, height));
            }

            VectorInt offset = new VectorInt()
            {
                X = (width - conv.Width) / 2,
                Y = (height - conv.Height) / 2,
            };

            double[] values = new double[width * height];

            #region Copy the image

            for (int y = 0; y < conv.Height; y++)
            {
                int offsetOrigY = y * conv.Width;
                int offsetNewY = (y + offset.Y) * width;

                for (int x = 0; x < conv.Width; x++)
                {
                    values[offsetNewY + offset.X + x] = conv.Values[offsetOrigY + x];
                }
            }

            #endregion

            #region Edges

            bool hasNegX = offset.X > 0;
            AxisFor forNegX = new AxisFor(Axis.X, offset.X - 1, 0);
            if (hasNegX)
            {
                ExtendEdge(values, width, conv.Width, forNegX, new AxisFor(Axis.Y, offset.Y, offset.Y + conv.Height - 1));
            }

            bool hasNegY = offset.Y > 0;
            AxisFor forNegY = new AxisFor(Axis.Y, offset.Y - 1, 0);
            if (hasNegY)
            {
                ExtendEdge(values, width, conv.Height, forNegY, new AxisFor(Axis.X, offset.X, offset.X + conv.Width - 1));
            }

            bool hasPosX = width > offset.X + conv.Width;
            AxisFor forPosX = new AxisFor(Axis.X, offset.X + conv.Width, width - 1);
            if (hasPosX)
            {
                ExtendEdge(values, width, conv.Width, forPosX, new AxisFor(Axis.Y, offset.Y, offset.Y + conv.Height - 1));
            }

            bool hasPosY = height > offset.Y + conv.Height;
            AxisFor forPosY = new AxisFor(Axis.Y, offset.Y + conv.Height, height - 1);
            if (hasPosY)
            {
                ExtendEdge(values, width, conv.Height, forPosY, new AxisFor(Axis.X, offset.X, offset.X + conv.Width - 1));
            }

            #endregion
            #region Corners

            if (hasNegX && hasNegY)
            {
                ExtendCorner(values, width, forNegX, forNegY);
            }

            if (hasPosX && hasNegY)
            {
                ExtendCorner(values, width, forPosX, forNegY);
            }

            if (hasPosX && hasPosY)
            {
                ExtendCorner(values, width, forPosX, forPosY);
            }

            if (hasNegX && hasPosY)
            {
                ExtendCorner(values, width, forNegX, forPosY);
            }

            #endregion

            return new Convolution2D(values, width, height, conv.IsNegPos);
        }
Example #11
0
 private static Convolution2D Convolute_ExpandedBorder(Convolution2D image, Convolution2D kernel, string description)
 {
     throw new ApplicationException("finish this");
 }
Example #12
0
        /// <summary>
        /// This applies the convolution kernel to the image
        /// </summary>
        /// <remarks>
        /// http://homepages.inf.ed.ac.uk/rbf/HIPR2/convolve.htm
        /// http://homepages.inf.ed.ac.uk/rbf/HIPR2/gsmooth.htm
        /// http://homepages.inf.ed.ac.uk/rbf/HIPR2/sobel.htm
        /// http://homepages.inf.ed.ac.uk/rbf/HIPR2/canny.htm
        ///
        /// http://www.tannerhelland.com/952/edge-detection-vb6/
        /// </remarks>
        /// <param name="image">This is the original image</param>
        /// <param name="kernel">This is the kernel image (a small patch that will be slid over image)</param>
        /// <param name="expandBorder">
        /// True: The output image will be the same size as the input (but border cells need to be made up for this to happen)
        /// False: The output image will be smaller (output.W = image.W - kernel.W + 1, same with height)
        /// </param>
        /// <returns></returns>
        private static Convolution2D Convolute_Single(Convolution2D image, Convolution2D kernel, string description)
        {
            Convolution2D retVal = image;

            for (int cntr = 0; cntr < kernel.Iterations; cntr++)
            {
                if (kernel.ExpandBorder)
                {
                    retVal = Convolute_ExpandedBorder(retVal, kernel, description);
                }
                else
                {
                    retVal = Convolute_Standard(retVal, kernel, description);
                }
            }

            return retVal;
        }
Example #13
0
        private static Convolution2D Convolute_Set_MaxOf(Convolution2D image, ConvolutionSet2D kernel, string description)
        {
            #region validate
#if DEBUG
            if (kernel.OperationType != SetOperationType.MaxOf)
            {
                throw new ArgumentException("kernel must be MaxOf: " + kernel.OperationType.ToString());
            }
            else if (kernel.Convolutions.Length < 2)
            {
                throw new ArgumentException("MaxOf kernel set needs at least two children");
            }

            VectorInt firstReduce = kernel.Convolutions[0].GetReduction();

            for (int cntr = 1; cntr < kernel.Convolutions.Length; cntr++)
            {
                VectorInt nextReduce = kernel.Convolutions[cntr].GetReduction();

                if (firstReduce.X != nextReduce.X || firstReduce.Y != nextReduce.Y)
                {
                    throw new ArgumentException("When the operation is MaxOf, then all kernels must reduce the same amount");
                }
            }
#endif
            #endregion

            Convolution2D[] children = kernel.Convolutions.
                Select(o => Convolute(image, o, description)).
                ToArray();

            double[] retVal = new double[children[0].Values.Length];

            for (int index = 0; index < retVal.Length; index++)
            {
                double maxValue = 0;
                double maxAbsValue = 0;

                for (int cntr = 0; cntr < children.Length; cntr++)
                {
                    double abs = Math.Abs(children[cntr].Values[index]);
                    if (abs > maxAbsValue)
                    {
                        maxValue = children[cntr].Values[index];
                        maxAbsValue = abs;
                    }
                }

                retVal[index] = maxValue;
            }

            return new Convolution2D(retVal, children[0].Width, children[0].Height, image.IsNegPos || children.Any(o => o.IsNegPos), description: description);
        }
Example #14
0
        private static Convolution2D Convolute_Set(Convolution2D image, ConvolutionSet2D kernel, string description)
        {
            if (kernel.OperationType == SetOperationType.MaxOf)
            {
                // This is special, because it needs to convolute each child, then pick the values it wants to keep.  Also, each child will need to be the same size
                return Convolute_Set_MaxOf(image, kernel, description);
            }

            Convolution2D retVal = image;

            foreach (ConvolutionBase2D child in kernel.Convolutions)
            {
                retVal = Convolute(retVal, child, description);
            }

            if (kernel.OperationType == SetOperationType.Subtract)
            {
                retVal = Convolutions.Subtract(image, retVal, description);
            }

            return retVal;
        }
Example #15
0
        /// <summary>
        /// This looks at a patch that is extracted from the result of an image and a convolution.  This patch should be a relatively
        /// small rectangle centered around a bright spot (convolution.GetMax()).  This returns a score from 0 to 1.  This is looking
        /// for a peak that drops off (ideally a very large difference between the max pixel and min pixel)
        /// </summary>
        /// <remarks>
        /// TODO: May want another overload that takes a sample ideal patch to compare to:
        ///     Subtract patches, compare differences
        ///         line up the brightest point before subtracting
        ///         allow larger differences farther away from center
        /// </remarks>
        public static double GetExtractScore(Convolution2D patch, VectorInt brightestPoint, double? idealBrightness = null)
        {
            const double PERCENT_POS_MIN = .25;
            const double PERCENT_POS_MAX = .75;

            const double PERCENT_NEG_MIN = -.25;
            const double PERCENT_NEG_MAX = .5;

            if (patch.Width < 3 || patch.Height < 3)
            {
                return 0;
            }

            double max = patch[brightestPoint];

            // Get the min.  If not enough difference from max, then return zero
            var min = patch.GetMin();

            double percent = min.Item2 / max;

            double retVal = 0;

            if (patch.IsNegPos)
            {
                #region Neg/Pos

                if (percent < PERCENT_NEG_MIN)
                {
                    retVal = 1;
                }
                else if (percent < PERCENT_NEG_MAX)
                {
                    retVal = UtilityCore.GetScaledValue(1, 0, PERCENT_NEG_MIN, PERCENT_NEG_MAX, percent);
                }
                else
                {
                    return 0;
                }

                #endregion
            }
            else
            {
                #region Positive

                if (percent < PERCENT_POS_MIN)
                {
                    retVal = 1;
                }
                else if (percent < PERCENT_POS_MAX)
                {
                    retVal = UtilityCore.GetScaledValue(1, 0, PERCENT_POS_MIN, PERCENT_POS_MAX, percent);
                }
                else
                {
                    return 0;
                }

                #endregion
            }

            if (idealBrightness == null || max >= idealBrightness.Value)
            {
                return retVal;
            }

            return retVal * (max / idealBrightness.Value);
        }
Example #16
0
        public static string GetToolTip(Convolution2D conv, ConvolutionToolTipType type)
        {
            StringBuilder retVal = new StringBuilder(100);

            if (!string.IsNullOrEmpty(conv.Description))
            {
                retVal.Append(conv.Description);
            }

            if (type == ConvolutionToolTipType.Size || type == ConvolutionToolTipType.Size_MinMax)
            {
                if (retVal.Length > 0)
                {
                    retVal.AppendLine();
                }

                retVal.AppendFormat("{0}x{1}", conv.Width, conv.Height);
            }

            if (type == ConvolutionToolTipType.Size_MinMax)
            {
                retVal.AppendLine();

                double min = conv.Values.Min();
                double max = conv.Values.Max();

                retVal.AppendFormat("min: {0}\r\nmax: {1}", min.ToStringSignificantDigits(2), max.ToStringSignificantDigits(2));
            }

            if (retVal.Length == 0)
            {
                return null;        // otherwise there will be a tiny empty tooltip
            }
            else
            {
                return retVal.ToString();
            }
        }
Example #17
0
        //TODO: Take an enum or something that lets the user pick what type of removals to choose from
        public static Convolution2D RemoveSection(Convolution2D conv, int? count = null)
        {
            int actualCount = count ?? StaticRandom.Next(1, 4);

            //Convolution2D mask = GetMask_ScatterShot(conv.Width, conv.Height);
            Convolution2D mask = GetMask_Ellipse(conv.Width, conv.Height, actualCount);

            double[] values = new double[conv.Values.Length];

            for (int cntr = 0; cntr < values.Length; cntr++)
            {
                values[cntr] = conv.Values[cntr] * mask.Values[cntr];
            }

            values = Convolutions.ToUnit(values);

            return new Convolution2D(values, conv.Width, conv.Height, conv.IsNegPos, conv.Gain, conv.Iterations, conv.ExpandBorder, conv.Description);
        }
Example #18
0
        private static Convolution2D Convolute_Standard(Convolution2D image, Convolution2D kernel, string description)
        {
            int returnWidth = image.Width - kernel.Width + 1;
            int returnHeight = image.Height - kernel.Height + 1;

            if (returnWidth <= 0 || returnHeight <= 0)
            {
                throw new ArgumentException(string.Format("The kernel is too large for the image.  Image={0}x{1}, Kernel={2}x{3}", image.Width, image.Height, kernel.Width, kernel.Height));
            }

            double[] values = new double[returnWidth * returnHeight];

            for (int retY = 0; retY < returnHeight; retY++)
            {
                int returnOffset = retY * returnWidth;

                for (int retX = 0; retX < returnWidth; retX++)
                {
                    double returnValue = 0;

                    // Calculate the convoluted value at this return pixel
                    for (int kerY = 0; kerY < kernel.Height; kerY++)
                    {
                        int imageOffset = (retY + kerY) * image.Width;
                        int kernelOffet = kerY * kernel.Width;

                        for (int kerX = 0; kerX < kernel.Width; kerX++)
                        {
                            returnValue += image.Values[imageOffset + retX + kerX] * kernel.Values[kernelOffet + kerX];
                        }
                    }

                    // Store it
                    values[returnOffset + retX] = returnValue * kernel.Gain;
                }
            }

            return new Convolution2D(values, returnWidth, returnHeight, image.IsNegPos || kernel.IsNegPos, description: description);
        }
Example #19
0
        /// <summary>
        /// This reduces the convolution, keeping only the largest values in each source cell
        /// </summary>
        /// <remarks>
        /// NOTE: It's ok to enlarge if you need to, there will just be a hole of zeros in the center
        /// 
        /// MaxPool isn't really meant to be visually appealing, it's just a way to reduce in order to feed a neural net
        /// </remarks>
        public static Convolution2D MaxPool(Convolution2D conv, int width, int height)
        {
            if (conv.Width == width && conv.Height == height)
            {
                return conv;
            }

            #region Cell Sizes

            // X
            int[] xRanges;
            if (conv.Width == width)
            {
                xRanges = Enumerable.Range(0, width).Select(o => 1).ToArray();
            }
            else
            {
                xRanges = GetPoolCells(conv.Width, width);
            }

            Tuple<int, int>[] xStops = GetStops(xRanges);

            // Y
            int[] yRanges;
            if (conv.Height == height)
            {
                yRanges = Enumerable.Range(0, height).Select(o => 1).ToArray();
            }
            else
            {
                yRanges = GetPoolCells(conv.Height, height);
            }

            Tuple<int, int>[] yStops = GetStops(yRanges);

            #endregion

            double[] values = new double[width * height];

            for (int y = 0; y < height; y++)
            {
                int yOffset = y * width;

                for (int x = 0; x < width; x++)
                {
                    // Get the largest offset from zero from this cell
                    values[yOffset + x] = GetMax(conv.Values, conv.Width, xStops[x], yStops[y]);
                }
            }

            return new Convolution2D(values, width, height, conv.IsNegPos);
        }
Example #20
0
        private static Border GetThumbnail_Single(Convolution2D kernel, int thumbSize, ContextMenu contextMenu, ConvolutionToolTipType tooltipType)
        {
            // Figure out thumb size
            var sizes = GetThumbSizeAndPixelMultiplier(kernel, thumbSize);

            // Display it as a border and image
            Image image = new Image()
            {
                Source = GetBitmap_Aliased(kernel, sizes.Item2),
                Width = sizes.Item1.Width,
                Height = sizes.Item1.Height,
                ToolTip = GetToolTip(kernel, tooltipType),
            };

            Border border = new Border()
            {
                Child = image,
                BorderBrush = new SolidColorBrush(UtilityWPF.ColorFromHex("C0C0C0")),
                BorderThickness = new Thickness(1),
                Margin = new Thickness(6),
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
                ContextMenu = contextMenu,
                Tag = kernel,
            };

            return border;
        }
Example #21
0
        public static Convolution2D Normalize(Convolution2D conv, double scale = 1d)
        {
            double[] values = MathND.Normalize(conv.Values);

            if(!scale.IsNearValue(1d))
            {
                values = values.
                    Select(o => o * scale).
                    ToArray();
            }

            string description = "";
            if (!string.IsNullOrEmpty(conv.Description))
            {
                description = string.Format("Normalize({0})", description);
            }

            return new Convolution2D(values, conv.Width, conv.Height, conv.IsNegPos, conv.Gain, conv.Iterations, conv.ExpandBorder, description);
        }
Example #22
0
        private static double GetColorScale(Convolution2D conv, double? absMaxValue)
        {
            if (absMaxValue == null)
            {
                double min = conv.Values.Min(o => o);
                double max = conv.Values.Max(o => o);
                double absMax = Math.Max(Math.Abs(min), Math.Abs(max));

                if (Math1D.IsInvalid(absMax) || Math1D.IsNearZero(absMax))
                {
                    return 1d;
                }
                else
                {
                    return 255d / absMax;
                }
            }
            else
            {
                if (Math1D.IsInvalid(absMaxValue.Value) || Math1D.IsNearZero(absMaxValue.Value))
                {
                    return 1d;
                }
                else
                {
                    return 255d / absMaxValue.Value;
                }
            }
        }
        private void PixelValueChanged()
        {
            Convolution2D kernel = new Convolution2D(_values, _width, _height, radRangeNegPos.IsChecked.Value);
            ConvolutionResultNegPosColoring coloring = chkIsRedBlue.IsChecked.Value ? ConvolutionResultNegPosColoring.RedBlue : ConvolutionResultNegPosColoring.BlackWhite;

            // Show Kernel
            BitmapSource kernelBitmap = Convolutions.GetBitmap_Aliased(kernel, negPosColoring: coloring);
            imagePreview.Source = kernelBitmap;
            imagePreview.Width = kernelBitmap.PixelWidth;
            imagePreview.Height = kernelBitmap.PixelHeight;
        }
Example #24
0
        public static Convolution2D Rotate_90(Convolution2D convolution, bool isClockwise)
        {
            double[] newValues = Rotate_90(convolution.Values, convolution.Width, convolution.Height, isClockwise);

            //NOTE: width becomes height
            return new Convolution2D(newValues, convolution.Height, convolution.Width, convolution.IsNegPos, convolution.Gain, convolution.Iterations, convolution.ExpandBorder, convolution.Description);
        }
        /// <summary>
        /// This shows the kernel, and allows the user to edit it
        /// </summary>
        public void EditKernel(Convolution2D kernel)
        {
            this.Title = TITLE;

            panelEdit.Visibility = Visibility.Visible;

            StoreKernel(kernel);
        }
Example #26
0
        /// <summary>
        /// Runs a gaussian over the current row and the two prior.  Then copies those blurred values onto this row
        /// </summary>
        /// <param name="orthIndex">The row being copied to</param>
        private static void OverlayBlurredPixels(double[] values, int width, int orthHeight, int orthIndex, int orthInc, int edgeMidStart, int edgeMidStop, AxisFor orth, AxisFor edge, Convolution2D gauss, /*int opacityDistance,*/ Random rand)
        {
            if (orthHeight < 2 || edgeMidStop < edgeMidStart)
            {
                // There's not enough to do a full 3x3 blur.  A smaller sized blur could be done, but that's a lot of extra logic, and not really worth the trouble
                return;
            }

            //double opacity = UtilityCore.GetScaledValue_Capped(0d, 1d, 0, opacityDistance, Math.Abs(orthIndex - orth.Start));

            // Get a random midpoint
            int edgeMid = rand.Next(edgeMidStart, edgeMidStop + 1);

            AxisFor orth3 = new AxisFor(orth.Axis, orthIndex + (orthInc * 2), orthIndex);
            AxisFor leftEdge = new AxisFor(edge.Axis, edge.Start, edgeMid + (edge.Increment * 2));
            AxisFor rightEdge = new AxisFor(edge.Axis, edgeMid - (edge.Increment * 2), edge.Stop);

            // Copy the values (these are 3 tall, and edgeMid-edgeStart+2 wide)
            Convolution2D leftRect = CopyRect(values, width, leftEdge, orth3, false);
            Convolution2D rightRect = CopyRect(values, width, rightEdge, orth3, true);      // this one is rotated 180 so that when the gaussian is applied, it will be from the right border to the mid

            // Apply a gaussian (these are 1 tall, and edgeMid-edgeStart wide)
            Convolution2D leftBlurred = Convolutions.Convolute(leftRect, gauss);
            Convolution2D rightBlurred = Convolutions.Convolute(rightRect, gauss);

            // Overlay onto this newest row
            //TODO: use an opacity LERP from original edge
            OverlayRow(values, width, orthIndex, leftBlurred.Values, orth, edge, /*opacity,*/ true);
            OverlayRow(values, width, orthIndex, rightBlurred.Values, orth, edge, /*opacity,*/ false);
        }
        private void Save_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (this.SaveRequested == null)
                {
                    MessageBox.Show("There is no listener to the save event", this.Title, MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }

                double[] normalized = Convolutions.ToUnit(_values);

                Convolution2D kernel = new Convolution2D(normalized, _width, _height, radRangeNegPos.IsChecked.Value);

                this.SaveRequested(this, kernel);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
Example #28
0
        public static Convolution2D Rotate_45(Convolution2D convolution, bool isClockwise, bool shouldAdvanceEvensExtra = false)
        {
            if (convolution.Width != convolution.Height)
            {
                throw new ArgumentException("Width and height must be the same for 45 degree rotations");
            }

            double[] newValues = Rotate_45(convolution.Values, convolution.Width, isClockwise, shouldAdvanceEvensExtra);

            return new Convolution2D(newValues, convolution.Width, convolution.Height, convolution.IsNegPos, convolution.Gain, convolution.Iterations, convolution.ExpandBorder, convolution.Description);
        }
 // These merge the 3 back into one big array
 private static double[] MergeColor(Convolution2D r, Convolution2D g, Convolution2D b)
 {
     return MergeColor(r.Values, g.Values, b.Values);
 }
Example #30
0
 public static Convolution2D Invert(Convolution2D convolution, double? maxValue = null)
 {
     double[] newValues = Invert(convolution.Values, convolution.IsNegPos, maxValue);
     return new Convolution2D(newValues, convolution.Width, convolution.Height, convolution.IsNegPos, convolution.Gain, convolution.Iterations, convolution.ExpandBorder, convolution.Description);
 }