Exemple #1
0
        public static void Binarization(ByteImage btm, int suggestedtreshold)
        {
            int    pixAmount = 0;
            double sum       = 0;

            for (int x = (int)(0.15 * btm.Width); x < btm.Width - (int)(0.15 * btm.Width); x++)
            {
                for (int y = (int)(0.15 * btm.Height); y < btm.Height - (int)(0.15 * btm.Height); y++)
                {
                    byte[] oldColour;
                    oldColour = btm.getPixel(x, y);
                    sum      += (double)oldColour[1];
                    pixAmount++;
                }
            }
            int treshold = (int)sum / pixAmount;

            if (suggestedtreshold > 0)
            {
                treshold = suggestedtreshold;
            }
            for (int x = 0; x < btm.Width; x++)
            {
                for (int y = 0; y < btm.Height; y++)
                {
                    byte[] oldColour;
                    oldColour = btm.getPixel(x, y);
                    var value = oldColour[1] < treshold ? 0 : 255;
                    btm.setPixel(x, y, oldColour[0], (byte)value, (byte)value, (byte)value);
                }
            }
        }
Exemple #2
0
        public static byte[] MarkFaceCenter(ByteImage btm, int X, int Y)
        {
            var currPix = btm.getPixel(X, Y);

            byte[] newCol = new byte[] { currPix[0], (byte)220, (byte)0, (byte)0 };

            btm.setPixel(X, Y, newCol);
            btm.setPixel(X - 1, Y, newCol);
            btm.setPixel(X + 1, Y, newCol);

            btm.setPixel(X + 1, Y + 1, newCol);
            btm.setPixel(X, Y - 1, newCol);
            btm.setPixel(X, Y + 1, newCol);

            btm.setPixel(X - 1, Y - 1, newCol);
            btm.setPixel(X - 2, Y, newCol);
            btm.setPixel(X + 2, Y, newCol);

            btm.setPixel(X - 2, Y - 2, newCol);
            btm.setPixel(X + 2, Y + 2, newCol);
            btm.setPixel(X, Y - 2, newCol);
            btm.setPixel(X, Y + 2, newCol);

            return(newCol);
        }
Exemple #3
0
        public static void DrawLine(Point[] points, byte[] color, ByteImage picture)
        {
            bool horizontal = false;


            if (points[1].X - points[0].X > 0)
            {
                horizontal = true;
            }

            if (horizontal)
            {
                for (int x = points[0].X; x < points[1].X; x++)
                {
                    picture.setPixel(x, points[0].Y, color);
                }
            }
            else
            {
                for (int y = points[0].Y; y < points[1].Y; y++)
                {
                    picture.setPixel(points[0].X, y, color);
                }
            }
        }
        private void performLoadingPictures(BitmapImage btmi, string FileName, int mode)
        {
            if (mode == 0)
            {
                pic1Loaded      = false;
                pic1OriginalBtm = (Bitmap)Bitmap.FromFile(FileName);
                var temp = new BitmapImage(new Uri(FileName));
                WriteablePic1OriginalBtm = new WriteableBitmap(temp);
                pic1OriginalByteImage    = new ByteImage(WriteablePic1OriginalBtm, pic1OriginalBtm);

                pic1ProcessedBtm          = (Bitmap)Bitmap.FromFile(FileName);
                temp                      = new BitmapImage(new Uri(FileName));
                WriteablePic1ProcessedBtm = new WriteableBitmap(temp);
                pic1ProcessedByteImage    = new ByteImage(WriteablePic1ProcessedBtm, pic1ProcessedBtm);
                pic1Loaded                = true;
                pic1Processed             = false;
                features1                 = null;
            }
            else if (mode == 1)
            {
                pic2Loaded      = false;
                pic2OriginalBtm = (Bitmap)Bitmap.FromFile(FileName);
                var temp = new BitmapImage(new Uri(FileName));
                WriteablePic2OriginalBtm = new WriteableBitmap(temp);
                pic2OriginalByteImage    = new ByteImage(WriteablePic2OriginalBtm, pic2OriginalBtm);

                pic2ProcessedBtm          = (Bitmap)Bitmap.FromFile(FileName);
                temp                      = new BitmapImage(new Uri(FileName));
                WriteablePic2ProcessedBtm = new WriteableBitmap(temp);
                pic2ProcessedByteImage    = new ByteImage(WriteablePic2ProcessedBtm, pic2ProcessedBtm);
                pic2Loaded                = true;
                pic2Processed             = false;
                features2                 = null;
            }
        }
 private async Task GetFeatures()
 {
     if (pic1Loaded && !pic1Processed)
     {
         await Task.Run(() =>
         {
             pic1ProcessedByteImage = new ByteImage(pic1OriginalByteImage);
             var a = Helper.ProcessPicture(pic1ProcessedByteImage);
             pic1ProcessedByteImage = a.Item1;
             features1     = a.Item2;
             pic1Processed = true;
         });
     }
     if (pic2Loaded && !pic2Processed)
     {
         await Task.Run(() =>
         {
             pic2ProcessedByteImage = new ByteImage(pic2OriginalByteImage);
             var b = Helper.ProcessPicture(pic2ProcessedByteImage);
             pic2ProcessedByteImage = b.Item1;
             features2     = b.Item2;
             pic2Processed = true;
         });
     }
     if (pic1ProcessedByteImage != null && pic1Processed)
     {
         face1_processed.Source = pic1ProcessedByteImage.ToBitmapSource();
     }
     if (pic2ProcessedByteImage != null && pic2Processed)
     {
         face2_processed.Source = pic2ProcessedByteImage.ToBitmapSource();
     }
 }
Exemple #6
0
        public static int Blackout(ByteImage btm)
        {
            int    pixAmount = 0;
            double sum       = 0;

            for (int x = (int)(0.15 * btm.Width); x < btm.Width - (int)(0.15 * btm.Width); x++)
            {
                for (int y = (int)(0.15 * btm.Height); y < btm.Height - (int)(0.15 * btm.Height); y++)
                {
                    byte[] oldColour;
                    oldColour = btm.getPixel(x, y);
                    sum      += (double)oldColour[1];
                    pixAmount++;
                }
            }
            int treshold = (int)sum / pixAmount;

            for (int x = 0; x < btm.Width; x++)
            {
                for (int y = 0; y < btm.Height; y++)
                {
                    byte[] oldColour;
                    oldColour = btm.getPixel(x, y);
                    var value = oldColour[1] < ((byte)(1.2 * treshold)) ? 0 : oldColour[1];
                    btm.setPixel(x, y, oldColour[0], (byte)value, (byte)value, (byte)value);
                }
            }
            return(treshold);
        }
Exemple #7
0
 public static void StretchColors(ByteImage btm, int treshold, double a, double b)
 {
     for (int x = 0; x < btm.Width; x++)
     {
         for (int y = 0; y < btm.Height; y++)
         {
             byte[] oldColour;
             oldColour = btm.getPixel(x, y);
             var value = oldColour[1] < treshold ? (byte)(a * (double)oldColour[1]) : (byte)(b * (double)oldColour[1]);
             btm.setPixel(x, y, oldColour[0], (byte)value, (byte)value, (byte)value);
         }
     }
 }
Exemple #8
0
 public static void GrayScale(ByteImage btm)
 {
     for (int x = 0; x < btm.Width; x++)
     {
         for (int y = 0; y < btm.Height; y++)
         {
             byte[] oldColour;
             oldColour = btm.getPixel(x, y);
             var value = (0.2 * (double)oldColour[1]) + (0.7 * (double)oldColour[2]) + (0.1 * (double)oldColour[3]);
             btm.setPixel(x, y, oldColour[0], (byte)value, (byte)value, (byte)value);
         }
     }
 }
Exemple #9
0
 public static void Test(ByteImage btm)
 {
     for (int x = 0; x < btm.Width; x++)
     {
         for (int y = 0; y < btm.Height; y++)
         {
             byte[] oldColour;
             oldColour = btm.getPixel(x, y);
             var value = CastColor((byte)(Math.Abs((double)oldColour[1] - (double)oldColour[2])));
             btm.setPixel(x, y, oldColour[0], (byte)value, (byte)value, (byte)value);
         }
     }
 }
Exemple #10
0
        public ByteImage(ByteImage bitmap)
        {
            Width  = bitmap.Width;
            Height = bitmap.Height;
            int size = Width * Height * 4;

            Pixels = new byte[size];
            Stride = bitmap.Stride;
            for (int x = 0; x < size; x++)
            {
                Pixels[x] = bitmap.Pixels[x];
            }
            Bitmap = new Bitmap(bitmap.Bitmap);
        }
Exemple #11
0
        private static ByteImage CutOffFace(List <Point> corners, ByteImage ori)
        {
            int       width  = corners.ElementAt(1).X - corners.ElementAt(0).X;
            int       height = corners.ElementAt(2).Y - corners.ElementAt(0).Y;
            ByteImage face   = new ByteImage(width, height);

            for (int x = 0; x < face.Width; x++)
            {
                for (int y = 0; y < face.Height; y++)
                {
                    face.setPixel(x, y, ori.getPixel(x + corners.ElementAt(0).X, y + corners.ElementAt(0).Y));
                }
            }
            return(face);
        }
Exemple #12
0
 public static int[] GetVerticalHistogram(ByteImage btm, byte comparedColor)
 {
     int[] histogram = new int[btm.Height];
     for (int y = 0; y < btm.Height; y++)
     {
         for (int x = 0; x < btm.Width; x++)
         {
             byte[] oldColour;
             oldColour = btm.getPixel(x, y);
             var value = oldColour[1] == comparedColor ? 1 : 0;
             histogram[y] += value;
         }
     }
     return(histogram);
 }
Exemple #13
0
        public static int GetTreshold(ByteImage btm)
        {
            int    pixAmount = 0;
            double sum       = 0;

            for (int x = 0; x < btm.Width; x++)
            {
                for (int y = 0; y < btm.Height; y++)
                {
                    byte[] oldColour;
                    oldColour = btm.getPixel(x, y);
                    sum      += (double)oldColour[1];
                    pixAmount++;
                }
            }
            int treshold = (int)sum / pixAmount;

            return(treshold);
        }
Exemple #14
0
 public static Point CorrectPoint(Point point, ByteImage orig)
 {
     if (point.X >= orig.Width)
     {
         point.X = orig.Width - 1;
     }
     if (point.X < 0)
     {
         point.X = 0;
     }
     if (point.Y >= orig.Height)
     {
         point.Y = orig.Height - 1;
     }
     if (point.Y < 0)
     {
         point.Y = 0;
     }
     return(point);
 }
Exemple #15
0
        private static List <Point> DrawBorders(ByteImage ori, List <int> horizontalBorders, List <int> verticalBorders, byte[] color)
        {
            List <Point> corners     = new List <Point>();
            Point        center      = new Point(horizontalBorders.ElementAt(1), verticalBorders.ElementAt(1));
            Point        upLeft      = new Point(horizontalBorders.ElementAt(0), verticalBorders.ElementAt(0));
            Point        upRight     = new Point(horizontalBorders.ElementAt(2), verticalBorders.ElementAt(0));
            Point        bottomLeft  = new Point(horizontalBorders.ElementAt(0), verticalBorders.ElementAt(2));
            Point        bottomRight = new Point(horizontalBorders.ElementAt(2), verticalBorders.ElementAt(2));

            Point meanCenter = new Point((((Math.Abs(upRight.X - upLeft.X) / 2) + upLeft.X) + center.X) / 2, (((Math.Abs(upRight.Y - bottomRight.Y) / 2) + upRight.Y) + center.Y) / 2);

            int meanWidth = (Math.Abs(upLeft.X - meanCenter.X) + Math.Abs(meanCenter.X - upRight.X)) / 2;
            int meanHeigt = (Math.Abs(upLeft.Y - meanCenter.Y) + Math.Abs(meanCenter.Y - upRight.Y)) / 2;

            upLeft      = CorrectPoint(new Point(meanCenter.X - meanWidth - (int)(0.1 * meanWidth), meanCenter.Y - meanHeigt - (int)(0.1 * meanHeigt)), ori);
            upRight     = CorrectPoint(new Point(meanCenter.X + meanWidth + (int)(0.1 * meanWidth), meanCenter.Y - meanHeigt - (int)(0.1 * meanHeigt)), ori);
            bottomLeft  = CorrectPoint(new Point(meanCenter.X - meanWidth - (int)(0.1 * meanWidth), meanCenter.Y + meanHeigt + (int)(0.1 * meanHeigt)), ori);
            bottomRight = CorrectPoint(new Point(meanCenter.X + meanWidth + (int)(0.1 * meanWidth), meanCenter.Y + meanHeigt + (int)(0.1 * meanHeigt)), ori);

            corners.Add(upLeft);
            corners.Add(upRight);
            corners.Add(bottomLeft);
            corners.Add(bottomRight);

            for (int x = bottomLeft.X; x < bottomRight.X; x++)
            {
                ori.setPixel(x, upLeft.Y, color);
                ori.setPixel(x, bottomLeft.Y, color);
            }

            for (int y = upLeft.Y; y < bottomLeft.Y; y++)
            {
                ori.setPixel(upLeft.X, y, color);
                ori.setPixel(upRight.X, y, color);
            }

            return(corners);
        }
Exemple #16
0
        public static void GaussFiltr(ByteImage btm)
        {
            double a = 2.0;

            double[,] wages = new double[5, 5] {
                { 1, 1, 1, 1, 1 }, { 1, 1, a, 1, 1 }, { 1, a, a *a, a, 1 }, { 1, 1, a, 1, 1 }, { 1, 1, 1, 1, 1 }
            };

            for (int x = 0; x < btm.Width; x++)
            {
                for (int y = 0; y < btm.Height; y++)
                {
                    var    currpix = btm.getPixel(x, y);
                    double sumR    = 0.0;
                    double sumG    = 0.0;
                    double sumB    = 0.0;
                    double dividor = 0.0;
                    for (int x2 = -2; x2 < 3; x2++)
                    {
                        for (int y2 = -2; y2 < 3; y2++)
                        {
                            if (x + x2 >= 0 && y + y2 >= 0 && x + x2 < btm.Width && y + y2 < btm.Height)
                            {
                                double currWage = wages[x2 + 2, y2 + 2];
                                var    pix      = btm.getPixel(x + x2, y + y2);
                                sumR    += (double)(pix[1]) * currWage;
                                sumG    += (double)(pix[2]) * currWage;
                                sumB    += (double)(pix[3]) * currWage;
                                dividor += currWage;
                            }
                        }
                    }
                    btm.setPixel(x, y, currpix[0], CastColor((byte)(sumR / dividor)), CastColor((byte)(sumG / dividor)), CastColor((byte)(sumB / dividor)));
                }
            }
        }
Exemple #17
0
        private static int GetSkinCollor(ByteImage picture)
        {
            int iteration    = 15;
            int colorCounter = 3;

            int[] Sums    = new int[colorCounter];
            int[] Counter = new int[colorCounter];
            int[] Values  = new int[colorCounter];
            for (int i = 0; i < colorCounter; i++)
            {
                Values[i]  = (255 / colorCounter) * i;
                Sums[i]    = 0;
                Counter[i] = 0;
            }

            for (int i = 0; i < iteration; i++)
            {
                for (int x = 0; x < picture.Width; x++)
                {
                    for (int y = 0; y < picture.Height; y++)
                    {
                        byte[] color = picture.getPixel(x, y);
                        int    dist  = 255;
                        int    indx  = 0;
                        for (int c = 0; c < colorCounter; c++)
                        {
                            if (Math.Abs(color[1] - Values[c]) < dist)
                            {
                                dist = Math.Abs(color[1] - Values[c]);
                                indx = c;
                            }
                        }
                        Sums[indx] += color[1];
                        Counter[indx]++;
                    }
                }

                for (int c = 0; c < colorCounter; c++)
                {
                    Values[c]  = Sums[c] / Counter[c];
                    Sums[c]    = 0;
                    Counter[c] = 0;
                }
            }

            for (int x = 0; x < picture.Width; x++)
            {
                for (int y = 0; y < picture.Height; y++)
                {
                    byte[] color = picture.getPixel(x, y);
                    int    dist  = 255;
                    int    indx  = 0;
                    for (int c = 0; c < colorCounter; c++)
                    {
                        if (Math.Abs(color[1] - Values[c]) < dist)
                        {
                            dist = Math.Abs(color[1] - Values[c]);
                            indx = c;
                        }
                    }
                    Sums[indx] += color[1];
                    Counter[indx]++;
                }
            }

            int mostCommonCounter = 0;
            int mostCommonIndex   = 0;

            for (int c = 0; c < colorCounter; c++)
            {
                if (Counter[c] > mostCommonCounter)
                {
                    mostCommonCounter = Counter[c];
                    mostCommonIndex   = c;
                }
            }

            /*for (int x = 0; x < picture.Width; x++)
             * {
             *  for (int y = 0; y < picture.Height; y++)
             *  {
             *      byte[] color = picture.getPixel(x, y);
             *      int dist = 255;
             *      int indx = 0;
             *      for (int c = 0; c < colorCounter; c++)
             *      {
             *          if (Math.Abs(color[1] - Values[c]) < dist)
             *          {
             *              dist = Math.Abs(color[1] - Values[c]);
             *              indx = c;
             *          }
             *      }
             *      picture.setPixel(x, y, color[0], (byte)Values[indx], (byte)Values[indx], (byte)Values[indx]);
             *  }
             * }*/

            return(Values[mostCommonIndex]);
        }
Exemple #18
0
        public static Tuple <ByteImage, float[]> ProcessPicture(ByteImage picture)
        {
            float[]   features = new float[4];
            ByteImage ori      = new ByteImage(picture);
            ByteImage onlyFace = new ByteImage(picture);
            int       CenterX  = 0;
            int       CenterY  = 0;

            Test(picture);
            int treshold = Blackout(picture);

            GaussFiltr(picture);

            StretchColors(picture, (int)(1.2 * (double)treshold), 0.1, 1.5);
            Binarization(picture, (int)(1.6 * (double)treshold));
            int[] horizontalHistogram = GetHorizontalHistogram(picture, 0);
            int[] verticalHistogram   = GetVerticalHistogram(picture, 0);
            //WYGLADZANIE !! moving average
            horizontalHistogram = Smooth(horizontalHistogram);
            verticalHistogram   = Smooth(verticalHistogram);
            //Znalezienie minimow !! moje algo
            CenterX = HorizontalCenter(horizontalHistogram);
            CenterY = VerticalCenter(verticalHistogram);

            var newColor = MarkFaceCenter(picture, CenterX, CenterY);

            FloodFill(picture, new System.Drawing.Point(CenterX, CenterY), new List <byte[]>()
            {
                new byte[] { 255, 255, 255, 255 }, newColor
            }, newColor);

            int[] horizontaRedlHistogram = GetHorizontalHistogram(picture, newColor[1]);
            int[] verticalRedHistogram   = GetVerticalHistogram(picture, newColor[1]);

            //WYGLADZANIE !! moving average
            horizontaRedlHistogram = Smooth(horizontaRedlHistogram);
            verticalRedHistogram   = Smooth(verticalRedHistogram);

            List <int> horizontalBorders = HorizontalLeftCenterRight(horizontaRedlHistogram);
            List <int> verticalBorders   = VerticalUpCenterBottom(verticalRedHistogram);

            GrayScale(ori);
            MarkFaceCenter(ori, horizontalBorders.ElementAt(1), verticalBorders.ElementAt(1));


            //TU MAMY W MIARE TWARZ

            List <System.Drawing.Point> corners = DrawBorders(ori, horizontalBorders, verticalBorders, newColor);

            picture  = ori;
            onlyFace = CutOffFace(corners, onlyFace);
            picture  = new ByteImage(onlyFace);

            GrayScale(picture);
            int skinColor = GetSkinCollor(picture);

            Binarization(picture, (int)(0.7 * (double)skinColor));
            horizontalHistogram = GetHorizontalHistogram(picture, 0);
            verticalHistogram   = GetVerticalHistogram(picture, 0);
            for (int i = 0; i < 10; i++)
            {
                horizontalHistogram = Smooth(horizontalHistogram);
                verticalHistogram   = Smooth(verticalHistogram);
            }

            Point[] liniaSrodka    = GetMidLine(horizontalHistogram, verticalHistogram);
            Point[] wysokoscTwarzy = GetFaceHeight(horizontalHistogram, verticalHistogram);
            wysokoscTwarzy[0].X = liniaSrodka[0].X;
            wysokoscTwarzy[1].X = liniaSrodka[0].X;
            Point[] szerokoscTwarzy = GetFaceWidth(horizontalHistogram, verticalHistogram);
            szerokoscTwarzy[0].Y = Math.Abs(wysokoscTwarzy[1].Y - wysokoscTwarzy[0].Y);
            szerokoscTwarzy[1].Y = Math.Abs(wysokoscTwarzy[1].Y - wysokoscTwarzy[0].Y);
            Point[] liniaOczu = GetEyesLine(horizontalHistogram, verticalHistogram);
            Point[] lniaUst   = GetMouthLine(horizontalHistogram, verticalHistogram);


            DrawLine(liniaSrodka, new byte[] { 255, 0, 255, 0 }, picture);     //Green
            DrawLine(wysokoscTwarzy, new byte[] { 255, 255, 0, 0 }, picture);  //Red
            DrawLine(szerokoscTwarzy, new byte[] { 255, 255, 0, 0 }, picture); //Red
            DrawLine(liniaOczu, new byte[] { 255, 0, 0, 255 }, picture);       //Blue
            DrawLine(lniaUst, new byte[] { 255, 0, 255, 255 }, picture);       //Turkus
            features = GetFloatFeatures(wysokoscTwarzy, szerokoscTwarzy, lniaUst, liniaOczu);


            return(new Tuple <ByteImage, float[]>(picture, features));
        }
Exemple #19
0
        private static void FloodFill(ByteImage bmp, System.Drawing.Point pt, List <byte[]> targetColors, byte[] replacementColor)
        {
            List <Queue <System.Drawing.Point> > stackList = new List <Queue <System.Drawing.Point> >();

            bool[][] isAdded = new bool[bmp.Width][];
            for (int i = 0; i < isAdded.Length; i++)
            {
                isAdded[i] = new bool[bmp.Height];
                for (int j = 0; j < bmp.Height; j++)
                {
                    isAdded[i][j] = false;
                }
            }
            Queue <System.Drawing.Point> pixels = new Queue <System.Drawing.Point>();

            //ByteImage tempPict = new ByteImage(bmp);
            pixels.Enqueue(pt);
            stackList.Add(pixels);
            isAdded[pt.X][pt.Y] = true;
            int lB = 0;
            int rB = bmp.Width;
            int uB = bmp.Height;
            int bB = 0;

            int stackIndex = 0;

            while (ShouldContinue(stackList))
            {
                System.Drawing.Point a = stackList[stackIndex].Dequeue();

                if (a.X < rB && a.X >= lB &&
                    a.Y < uB && a.Y >= bB)    //make sure we stay within bounds
                {
                    bool isPushed = false;
                    foreach (var c in targetColors)
                    {
                        if (!isPushed && bmp.getPixel(a.X, a.Y)[1] == c[1])
                        {
                            bmp.setPixel(a.X, a.Y, replacementColor);
                            if (a.X - 1 < rB && a.X - 1 >= lB && a.Y < uB && a.Y >= bB && !isAdded[a.X - 1][a.Y])
                            {
                                stackList[stackIndex].Enqueue(new System.Drawing.Point(a.X - 1, a.Y));
                                isAdded[a.X - 1][a.Y] = true;
                            }
                            if (a.X + 1 < rB && a.X + 1 >= lB && a.Y < uB && a.Y >= bB && !isAdded[a.X + 1][a.Y])
                            {
                                stackList[stackIndex].Enqueue(new System.Drawing.Point(a.X + 1, a.Y));
                                isAdded[a.X + 1][a.Y] = true;
                            }
                            if (a.X < rB && a.X >= lB && a.Y - 1 < uB && a.Y - 1 >= bB && !isAdded[a.X][a.Y - 1])
                            {
                                stackList[stackIndex].Enqueue(new System.Drawing.Point(a.X, a.Y - 1));
                                isAdded[a.X][a.Y - 1] = true;
                            }
                            if (a.X < rB && a.X >= lB && a.Y + 1 < uB && a.Y + 1 >= bB && !isAdded[a.X][a.Y + 1])
                            {
                                stackList[stackIndex].Enqueue(new System.Drawing.Point(a.X, a.Y + 1));
                                isAdded[a.X][a.Y + 1] = true;
                            }
                            isPushed = true;
                        }
                    }
                }
                if (stackList[stackIndex].Count > 30000)
                {
                    stackIndex++;
                    stackList.Add(new Queue <System.Drawing.Point>());
                    System.Drawing.Point b = stackList[stackIndex - 1].Dequeue();
                    stackList[stackIndex].Enqueue(b);
                }
                else if (stackList[stackIndex].Count == 0)
                {
                    stackList.RemoveAt(stackIndex);
                    stackIndex--;
                }
            }
        }