/// <summary>
        /// Вычисление градиента изображения
        /// </summary>
        /// <param name="image">Изображение</param>
        private void CountGradient(GreyImage image)
        {
            try
            {
                GreyImage copyImage = (GreyImage)image.Copy();

                int imageHeight = image.Height - 1;
                int imageWidth = image.Width - 1;

                for (int i = 0; i < imageHeight; i++)
                    for (int j = 0; j < imageWidth; j++)
                    {
                        int gradientX = Math.Abs(copyImage.Pixels[i, j].Color.Data - copyImage.Pixels[i + 1, j].Color.Data);
                        int gradientY = Math.Abs(copyImage.Pixels[i, j].Color.Data - copyImage.Pixels[i, j + 1].Color.Data);

                        int gradient = gradientX + gradientY;
                        if (gradient > ColorBase.MAX_COLOR_VALUE)
                            gradient = ColorBase.MAX_COLOR_VALUE;
                        image.Pixels[i, j].Color.Data = (byte) gradient;
                    }
            }
            catch (Exception exception)
            {
                throw exception;
            }
        }
        /// <summary>
        /// Бинаризация методом Ниблака
        /// </summary>
        /// <param name="image"></param>
        public void Binarize(GreyImage image)
        {
            try
            {
                int windowSize = this.WindowSize;
                int lowIndex = windowSize / 2;
                int highIndexI = image.Height - lowIndex;
                int highIndexJ = image.Width - lowIndex;

                GreyImage copyImage = (GreyImage)image.Copy();

                for (int i = lowIndex; i < highIndexI; i++)
                    for (int j = lowIndex; j < highIndexJ; j++)
                    {
                        double matExp = CountMatExp(copyImage, i, j);
                        double sigma = CountSigma(copyImage, i, j, matExp);

                        int treshold = (int) (matExp + this.K * sigma);
                        if (image.Pixels[i, j].Color.Data < treshold)
                            image.Pixels[i, j].Color.Data = (byte)ColorBase.MIN_COLOR_VALUE;
                        else
                            image.Pixels[i, j].Color.Data = (byte)ColorBase.MAX_COLOR_VALUE;
                    }
            }
            catch (Exception exception)
            {
                throw exception;
            }
        }
Example #3
0
        /// <summary>
        /// Применение морфологической операции расширения к контурному изображению
        /// </summary>
        /// <param name="image"></param>
        public override void Apply(GreyImage image)
        {
            try
            {
                if (image == null)
                    throw new ArgumentNullException("Null image in Apply");

                GreyImage copyImage = (GreyImage)image.Copy();

                int filterSize = this.Size;
                int lowIndex = filterSize / 2;
                int highIndexI = image.Height;
                int highIndexJ = image.Width - lowIndex;
                for (int i = 0; i < highIndexI; i++)
                    for (int j = lowIndex; j < highIndexJ; j++)
                    {
                        if (copyImage.Pixels[i, j].Color.Data == ColorBase.MIN_COLOR_VALUE)
                        {
                           //ool borderPixelFound = false;
                            for (int k = 0; k < filterSize; k++)
                                image.Pixels[i, k + j - lowIndex].Color.Data = (byte)ColorBase.MIN_COLOR_VALUE;
                                // (copyImage.Pixels[i, k + j - lowIndex].Color.Data == ColorBase.MIN_COLOR_VALUE)
                                  //borderPixelFound = true;
                          //  if (borderPixelFound)
                            //    image.Pixels[i, j].Color.Data = (byte) ColorBase.MIN_COLOR_VALUE;
                        }
                    }
            }
            catch (Exception exception)
            {
                throw exception;
            }
        }
        /// <summary>
        /// Применение SWT фильтра к серому изображению
        /// </summary>
        /// <param name="image">Серое изображение</param>
        public override void Apply(GreyImage image)
        {
            try
            {
                if (image == null)
                    throw new ArgumentNullException("Null image in Apply");
                if (image.Height != this._gaussSmoothedImage.Height || image.Width != this._gaussSmoothedImage.Width)
                    throw new ArgumentException("Image must be the same size with gaussSmoothedImage in ctor");
                this._maxIntensityDirectionImage = (GreyImage) image.Copy();
                if (this._maxIntensityDirectionImage == null)
                    throw new NullReferenceException("Null _minIntensityDirectionImage in Apply");
                this._minIntensityDirectionImage = (GreyImage)image.Copy();
                if (this._minIntensityDirectionImage == null)
                    throw new NullReferenceException("Null _minIntensityDirectionImage in Apply");

                FillMinIntensityImage(image);
                FillMaxIntensityImage(image);
            }
            catch (Exception exception)
            {
                throw exception;
            }
        }
        /// <summary>
        /// Применение фильтра Лапласа к серому изображению
        /// </summary>
        /// <param name="image">Серое изображение</param>
        public override void Apply(GreyImage image)
        {
            try
            {
                if (image == null)
                    throw new ArgumentNullException("Null image in Apply");
                if (image.Height < this.Size)
                    throw new ArgumentException("Image height must be >= filter size");
                if (image.Width < this.Size)
                    throw new ArgumentException("Image width must be >= filter size");

                GreyImage copyImage = (GreyImage)image.Copy();
                if (copyImage == null)
                    throw new NullReferenceException("Null copy image in Apply");

                int lowIndex = Size / 2;
                int highIndexI = image.Height - lowIndex;
                int highIndexJ = image.Width - lowIndex;
                for (int i = lowIndex; i < highIndexI; i++)
                    for (int j = lowIndex; j < highIndexJ; j++)
                    {
                        int gradientStrengthX = copyImage.Pixels[i - 1, j].Color.Data * Gx[0, 1] +
                          copyImage.Pixels[i, j - 1].Color.Data * Gx[1, 0] + copyImage.Pixels[i, j].Color.Data * Gx[1, 1] +
                          copyImage.Pixels[i, j + 1].Color.Data * Gx[1, 2] + copyImage.Pixels[i + 1, j].Color.Data * Gx[2, 1];

                        int gradientStrengthSqr = gradientStrengthX * gradientStrengthX + gradientStrengthX * gradientStrengthX;

                        if (gradientStrengthSqr > ColorBase.MAX_COLOR_VALUE)
                        {
                            image.Pixels[i, j].Color.Data = (byte)ColorBase.MIN_COLOR_VALUE;
                            image.Pixels[i, j].BorderType = BorderType.Border.STRONG;
                        }
                        else
                        {
                            image.Pixels[i, j].Color.Data = (byte)ColorBase.MAX_COLOR_VALUE;
                            image.Pixels[i, j].BorderType = BorderType.Border.WEAK;
                        }
                    }
            }
            catch (Exception exception)
            {
                throw exception;
            }
        }
        /// <summary>
        /// Применение фильтра Гаусса к серому изображению
        /// </summary>
        /// <param name="image">Серое изображение</param>
        public override void Apply(GreyImage image)
        {
            try
            {
                if (image == null)
                    throw new ArgumentNullException("Null image in Apply");
                if (image.Height < this.Size)
                    throw new ArgumentException("Image height must be >= filter size");
                if (image.Width < this.Size)
                    throw new ArgumentException("Image width must be >= filter size");

                GreyImage copyImage = (GreyImage) image.Copy();
                if (copyImage == null)
                    throw new NullReferenceException("Null copy image in Apply");

                int filterSize = this.Size;
                int lowIndex = filterSize / 2;
                int highIndexI = image.Height - lowIndex;
                int highIndexJ = image.Width - lowIndex;
                for (int i = lowIndex; i < highIndexI; i++)
                    for (int j = lowIndex; j < highIndexJ; j++)
                    {
                        int pixelColor = 0;
                        for (int k = 0; k < filterSize; k++)
                            for (int l = 0; l < filterSize; l++)
                                pixelColor += this.Kernel[k, l] * copyImage.Pixels[k + i - lowIndex, l + j - lowIndex].Color.Data;

                        pixelColor /= this.NormalizationRatio;
                        if (pixelColor > ColorBase.MAX_COLOR_VALUE)
                            pixelColor = ColorBase.MAX_COLOR_VALUE;
                        if (pixelColor < 0)
                            pixelColor = ColorBase.MIN_COLOR_VALUE;
                        image.Pixels[i, j].Color.Data = (byte) pixelColor;
                    }
            }
            catch (Exception exception)
            {
                throw exception;
            }
        }
Example #7
0
        /// <summary>
        /// Применение морфологической операции эрозии к контурному изображению
        /// </summary>
        /// <param name="image"></param>
        public override void Apply(GreyImage image)
        {
            try
            {
                if (image == null)
                    throw new ArgumentNullException("Null image in Apply");

                GreyImage copyImage = (GreyImage)image.Copy();

                int filterSize = this.Size;
                int lowIndex = filterSize / 2;
                int highIndexI = image.Height - 1;
                int highIndexJ = image.Width - lowIndex;
                for (int i = 1; i < highIndexI; i++)
                    for (int j = lowIndex; j < highIndexJ; j++)
                    {
                        if (copyImage.Pixels[i, j].Color.Data == ColorBase.MIN_COLOR_VALUE)
                        {
                            int pixelsNumber = 0;
                            for (int k = 0; k < filterSize; k++)
                                if (copyImage.Pixels[i, k + j - lowIndex].Color.Data == ColorBase.MIN_COLOR_VALUE)
                                    ++pixelsNumber;
                            if (pixelsNumber == filterSize)
                            {
                                for (int k = 0; k < lowIndex; k++)
                                    image.Pixels[i, k + j - lowIndex].Color.Data = (byte)ColorBase.MAX_COLOR_VALUE;

                                for (int k = lowIndex + 1; k < filterSize; k++)
                                    image.Pixels[i, k + j - lowIndex].Color.Data = (byte)ColorBase.MAX_COLOR_VALUE;
                                image.Pixels[i, j].Color.Data = (byte)ColorBase.MIN_COLOR_VALUE;
                            }
                        }
                    }
            }
            catch (Exception exception)
            {
                throw exception;
            }
        }
        /// <summary>
        /// Применение фильтра Гаусса к серому изображению (многопоточная)
        /// </summary>
        /// <param name="image">Серое изображение</param>
        /// <param name="threadsNumber">Число потоков</param>
        public override GreyImage Apply(GreyImage image, int threadsNumber)
        {
            try
            {
                if (image == null)
                    throw new ArgumentNullException("Null image in Apply");
                if (image.Height < this.Size)
                    throw new ArgumentException("Image height must be >= filter size");
                if (image.Width < this.Size)
                    throw new ArgumentException("Image width must be >= filter size");
                if (threadsNumber <= 0)
                    throw new ArgumentException("Error threadsNumber in Apply");

                this._copyImage = (GreyImage)image.Copy();
                if (this._copyImage == null)
                    throw new NullReferenceException("Null copy image in Apply");

                this.Threads = new List<Thread>();

                int deltaI = image.Height / threadsNumber;
                int filterSize = this.Size;
                int lowIndex = filterSize / 2;
                int lowIndexI = lowIndex;
                int highIndexI = lowIndexI + deltaI;
                int highIndexJ = image.Width - lowIndex;

                for (int i = 0; i < threadsNumber; i++)
                {
                    if (i == threadsNumber - 1)
                        highIndexI = image.Height - lowIndex;

                    MatrixFilterData matrixFilterData = new ThreadData.MatrixFilterData(image, lowIndexI, highIndexI, lowIndex, highIndexJ);
                    Thread thread = new Thread(new ParameterizedThreadStart(this.ApplyThread));
                    this.Threads.Add(thread);
                    this.Threads[i].Start(matrixFilterData);

                    lowIndexI = highIndexI;
                    highIndexI += deltaI;
                }
                WaitForThreads();

                return this._copyImage;
            }
            catch (Exception exception)
            {
                throw exception;
            }
        }
        /// <summary>
        /// Применение фильтра Превитта к серому изображению
        /// </summary>
        /// <param name="image">Серое изображение</param>
        public override void Apply(GreyImage image)
        {
            try
            {
                if (image == null)
                    throw new ArgumentNullException("Null image in Apply");
                if (image.Height < this.Size)
                    throw new ArgumentException("Image height must be >= filter size");
                if (image.Width < this.Size)
                    throw new ArgumentException("Image width must be >= filter size");

                GreyImage copyImage = (GreyImage)image.Copy();
                if (copyImage == null)
                    throw new NullReferenceException("Null copy image in Apply");

                int lowIndex = Size / 2;
                int highIndexI = image.Height - lowIndex;
                int highIndexJ = image.Width - lowIndex;
                for (int i = lowIndex; i < highIndexI; i++)
                    for (int j = lowIndex; j < highIndexJ; j++)
                    {
                        byte pixelI_1J_1 = copyImage.Pixels[i - 1, j - 1].Color.Data;
                        byte pixelI_1J1 = copyImage.Pixels[i - 1, j + 1].Color.Data;
                        byte pixelI1J1 = copyImage.Pixels[i + 1, j + 1].Color.Data;

                        int gradientStrengthY = pixelI_1J_1 * Gy[0, 0] +
                          copyImage.Pixels[i - 1, j].Color.Data * Gy[0, 1] + pixelI_1J1 * Gy[0, 2] +
                          copyImage.Pixels[i + 1, j - 1].Color.Data * Gy[2, 0] + copyImage.Pixels[i + 1, j].Color.Data * Gy[2, 1] +
                          pixelI1J1 * Gy[2, 2];

                        int gradientStrengthX = pixelI_1J_1 * Gx[0, 0] +
                          pixelI_1J1 * Gx[0, 2] + copyImage.Pixels[i, j - 1].Color.Data * Gx[1, 0] +
                          copyImage.Pixels[i, j + 1].Color.Data * Gx[1, 2] + copyImage.Pixels[i + 1, j - 1].Color.Data * Gx[2, 0] +
                          pixelI1J1 * Gx[2, 2];

                        int gradientStrengthSqr = gradientStrengthX * gradientStrengthX + gradientStrengthY * gradientStrengthY;
                        image.Pixels[i, j].Gradient.Strength = (int)Math.Sqrt((double)gradientStrengthSqr);

                        if (gradientStrengthSqr > TRESHOLD)
                        {
                            image.Pixels[i, j].Color.Data = (byte)ColorBase.MIN_COLOR_VALUE;
                            image.Pixels[i, j].BorderType = BorderType.Border.STRONG;
                        }
                        else
                        {
                            image.Pixels[i, j].Color.Data = (byte)ColorBase.MAX_COLOR_VALUE;
                            image.Pixels[i, j].BorderType = BorderType.Border.WEAK;
                        }

                        if (gradientStrengthX == 0)
                        {
                            if (gradientStrengthY == 0)
                                image.Pixels[i, j].Gradient.Angle = 0;
                            else
                                image.Pixels[i, j].Gradient.Angle = 90;
                        }
                        else
                            image.Pixels[i, j].Gradient.Angle = (int)((Math.Atan((double)gradientStrengthY / gradientStrengthX)) * (180 / Math.PI));
                    }
            }
            catch (Exception exception)
            {
                throw exception;
            }
        }
        /// <summary>
        /// Выделение текста на изображении гибрибным подходом
        /// </summary>
        /// <param name="image">Изображение</param>
        public void DetectText(GreyImage image)
        {
            try
            {
                if (image == null)
                    throw new ArgumentNullException("Null image in DetectText");

               // textRegions = null;

                Thread edgeThread = new Thread(new ParameterizedThreadStart(this.EdgeBasedProcessThread));
                Thread gradientThread = new Thread(new ParameterizedThreadStart(this.GradientBasedProcessThread));

                GreyImage copyImage = (GreyImage)image.Copy();

                edgeThread.Start(copyImage);
                gradientThread.Start(copyImage);

                edgeThread.Join();
                gradientThread.Join();

                for (int i = 0; i < image.Height; i++)
                    for (int j = 0; j < image.Width; j++)
                    {
                        if (this._gradientImage.Pixels[i, j].Color.Data == ColorBase.MAX_COLOR_VALUE &&
                            this._edgeImage.Pixels[i, j].Color.Data == ColorBase.MIN_COLOR_VALUE)
                            copyImage.Pixels[i, j].Color.Data = (byte)ColorBase.MIN_COLOR_VALUE;
                        else
                            copyImage.Pixels[i, j].Color.Data = (byte)ColorBase.MAX_COLOR_VALUE;

                        copyImage.Pixels[i, j].BorderType = this._edgeImage.Pixels[i, j].BorderType;
                      //  image.Pixels[i, j].Color.Data = this._gradientImage.Pixels[i, j].Color.Data;
                    }

                this._dilation.Apply(copyImage);

                int[] heightHist = new int[copyImage.Height];
                int[] widthHist = new int[copyImage.Width];

                for (int i = 0; i < copyImage.Height; i++)
                {
                    int sum = 0;
                    for (int j = 0; j < copyImage.Width; j++)
                    {
                        if (copyImage.Pixels[i, j].Color.Data == (byte)ColorBase.MIN_COLOR_VALUE)
                            ++sum;
                    }
                    heightHist[i] = sum;
                }

                int maxH = heightHist.Max();

                for (int i = 0; i < copyImage.Width; i++)
                {
                    int sum = 0;
                    for (int j = 0; j < copyImage.Height; j++)
                    {
                        if (copyImage.Pixels[j, i].Color.Data == (byte)ColorBase.MIN_COLOR_VALUE)
                            ++sum;
                    }
                    widthHist[i] = sum;
                }
                int maxw = widthHist.Max();

                for (int i = 0; i < heightHist.Length; i++)
                {
                    if (maxH - heightHist[i] < 150)
                        heightHist[i] = 1;
                    else
                        heightHist[i] = 0;
                }

                for (int i = 0; i < widthHist.Length; i++)
                {
                    if (maxw - widthHist[i] < 50)
                        widthHist[i] = 1;
                    else
                        widthHist[i] = 0;
                }

                for (int i = 0; i < image.Height; i++)
                {
                    for (int j = 0; j < image.Width; j++)
                    {
                        if (heightHist[i] == 1 && widthHist[j] == 1)
                            image.Pixels[i, j].Color.Data = (byte)ColorBase.MIN_COLOR_VALUE;
                     //   else
                           // image.Pixels[i, j].Color.Data = (byte)ColorBase.MAX_COLOR_VALUE;

                    }
                }

              //  this._opening.Apply(image);
            }
            catch (Exception exception)
            {
                throw exception;
            }
        }
        /// <summary>
        /// Подавление не максимумов. Границами считаются только точки локального максимума
        /// </summary>
        /// <param name="image">Серое изображение</param>
        private void NonMaximaSuppression(GreyImage image)
        {
            try
            {
                if (image == null)
                    throw new ArgumentNullException("Null image in NonMaximasuppression");

                GreyImage copyImage = (GreyImage)image.Copy();
                if (copyImage == null)
                    throw new NullReferenceException("Null copy image in NonMaximaSuppression");

                int lowIndex = this.EdgeDetectionFilter.Size / 2;
                int highIndexI = image.Height - lowIndex;
                int highIndexJ = image.Width - lowIndex;
                for (int i = lowIndex; i < highIndexI; i++)
                    for (int j = lowIndex; j < highIndexJ; j++)
                    {
                        GradientData.RoundGradientDirection gradientDirection = image.Pixels[i, j].Gradient.RoundGradientDirection;
                        if (gradientDirection == GradientData.RoundGradientDirection.DEGREE_0)
                        {
                            int gradientStrength = copyImage.Pixels[i, j].Gradient.Strength;
                            if (!(gradientStrength > copyImage.Pixels[i, j - 1].Gradient.Strength &&   // i, j - 1
                                gradientStrength > copyImage.Pixels[i, j + 1].Gradient.Strength))   // i, j + 1
                                image.Pixels[i, j].Gradient.Strength = 0;
                        }
                        else if (gradientDirection == GradientData.RoundGradientDirection.DEGREE__45)
                        {
                            int gradientStrength = copyImage.Pixels[i, j].Gradient.Strength;
                            if (!(gradientStrength > copyImage.Pixels[i + 1, j - 1].Gradient.Strength &&
                            gradientStrength > copyImage.Pixels[i - 1, j + 1].Gradient.Strength))
                                image.Pixels[i, j].Gradient.Strength = 0;
                        }
                        else if (gradientDirection == GradientData.RoundGradientDirection.DEGREE_90)
                        {
                            int gradientStrength = copyImage.Pixels[i, j].Gradient.Strength;
                            if (!(gradientStrength > copyImage.Pixels[i + 1, j].Gradient.Strength &&   // i + 1, j
                            gradientStrength > copyImage.Pixels[i - 1, j].Gradient.Strength))    // i - 1, j
                                image.Pixels[i, j].Gradient.Strength = 0;
                        }
                        else if (gradientDirection == GradientData.RoundGradientDirection.DEGREE_135)
                        {
                            int gradientStrength = copyImage.Pixels[i, j].Gradient.Strength;
                            if (!(gradientStrength > copyImage.Pixels[i - 1, j - 1].Gradient.Strength &&
                            gradientStrength > copyImage.Pixels[i + 1, j + 1].Gradient.Strength))
                                image.Pixels[i, j].Gradient.Strength = 0;
                        }
                    }
            }
            catch (Exception exception)
            {
                throw exception;
            }
        }
 /// <summary>
 /// Определяет границы серого изображения
 /// </summary>
 /// <param name="image">Серое изображение</param>
 public void Detect(GreyImage image)
 {
     try
     {
         if (image == null)
             throw new ArgumentNullException("Null image in Detect");
         this.SmoothingFilter.Apply(image);
         _greySmoothedImage = (GreyImage)image.Copy();
         this.EdgeDetectionFilter.Apply(image);
         SetGradientDirection(image);
         NonMaximaSuppression(image);
         DoubleTresholding(image);
         EdgeTrackingByHysteresis(image);
         SetEdgesColor(image);
     }
     catch (Exception exception)
     {
         throw exception;
     }
 }
        /// <summary>
        /// Применение адаптивного фильтра Гаусса к серому изображению
        /// </summary>
        /// <param name="image">Серое изображение</param>
        private void ProcessImage(GreyImage image)
        {
            try
            {
                int imageHeight = image.Height - 2;
                int imageWidth = image.Width - 2;

                GreyImage copyImage = (GreyImage) image.Copy();

                for (int i = 1; i < imageHeight; i++)
                    for (int j = 1; j < imageWidth; j++)
                    {
                        double w1 = CalculateWeight(copyImage, i - 1, j - 1);
                        double w2 = CalculateWeight(copyImage, i - 1, j);
                        double w3 = CalculateWeight(copyImage, i - 1, j + 1);
                        double w4 = CalculateWeight(copyImage, i, j - 1);
                        double w5 = CalculateWeight(copyImage, i, j + 1);
                        double w6 = CalculateWeight(copyImage, i + 1, j - 1);
                        double w7 = CalculateWeight(copyImage, i + 1, j);
                        double w8 = CalculateWeight(copyImage, i + 1, j + 1);
                        double wCurrentPixel = CalculateWeight(copyImage, i, j);

                        double N = w1 + w2 + w3 + w4 + w5 + w6 + w7 + w8 + wCurrentPixel;
                        double newPixelValue = w1 * copyImage.Pixels[i - 1, j - 1].Color.Data + w2 * copyImage.Pixels[i - 1, j].Color.Data +
                            w3 * copyImage.Pixels[i - 1, j + 1].Color.Data + w4 * copyImage.Pixels[i, j - 1].Color.Data +
                            w5 * copyImage.Pixels[i, j + 1].Color.Data + w6 * copyImage.Pixels[i + 1, j - 1].Color.Data +
                            w7 * copyImage.Pixels[i + 1, j].Color.Data + w8 * copyImage.Pixels[i + 1, j + 1].Color.Data +
                            wCurrentPixel * copyImage.Pixels[i, j].Color.Data;
                        if (N == 0.0)
                            image.Pixels[i, j].Color.Data = (byte) ColorBase.MIN_COLOR_VALUE;
                        else
                        {
                            int newColor = (int) (newPixelValue / N);
                            if (newColor > ColorBase.MAX_COLOR_VALUE)
                                newColor = ColorBase.MAX_COLOR_VALUE;
                            if (newColor < ColorBase.MIN_COLOR_VALUE)
                                newColor = ColorBase.MIN_COLOR_VALUE;
                            image.Pixels[i, j].Color.Data = (byte)newColor;
                        }
                    }
            }
            catch (Exception exception)
            {
                throw exception;
            }
        }
        /// <summary>
        /// Усиление градиентного изображения фильтром 3 на 3
        /// </summary>
        /// <param name="image">Градиентное изображение </param>
        private void EnhanceGradientImage(GreyImage image)
        {
            try
            {
                int imageHeight = image.Height - 1;
                int imageWidth = image.Width - 1;

                GreyImage copyImage = (GreyImage)image.Copy();

                for (int i = 1; i < imageHeight; i++)
                    for (int j = 1; j < imageWidth; j++)
                        image.Pixels[i, j].Color.Data = (byte) GetMaximumIntensityFromNeibours(copyImage, i, j);
            }
            catch (Exception exception)
            {
                throw exception;
            }
        }