/// <summary>
        /// Автоматическое наращивание регионов по значению глубины
        /// </summary>
        /// <param name="depthMapValues">Значения карт глубины и размер шаблона для каждой карты глубины</param>
        /// <param name="depthDeviation">Отклонение глубины</param>
        /// <param name="MinRegionSize">Минимальный размер региона (количество шаблонов ,которые помещаются в регион)</param>
        /// <param name="writeToFile">Флаг записи результатов в файл</param>
        /// <param name="path">Путь (если не задан, то "")</param>
        public static List <int[, ]> AutoRegionGrowing(List <ResultsFromRegionGrowing> depthMapValues, double depthDeviation, int minRegionSize, bool writeToFile, string path = "")
        {
            List <int[, ]> matrixRegions = new List <int[, ]>();
            int            count         = 1; // Счетчик карт глубины

            foreach (var depthMapValue in depthMapValues)
            {
                Stopwatch timer = Stopwatch.StartNew(); // Старт секундомера для диагностики работы алгоритма
                Tracer.Info($"\nНаращивание регионов для {count}-й карты глубины...");

                List <int> deleteRegions = new List <int>();
                // Иницилизация матрицы и изображения с регионами
                int[,] regionsMatrix = new int[depthMapValue.DepthMapValue.GetLength(0), depthMapValue.DepthMapValue.GetLength(1)];
                Bitmap regionsImage = new Bitmap(depthMapValue.DepthMapValue.GetLength(0), depthMapValue.DepthMapValue.GetLength(1));

                Random rnd         = new Random(); // Рандом для задания случайного цвета для каждого региона
                int    regionValue = 1;            // Первый регион = 1, затем они увеличиваются на 1
                for (int i = 0; i < regionsMatrix.GetLength(0); i += depthMapValue.TemplateSize)
                {
                    for (int j = 0; j < regionsMatrix.GetLength(1); j += depthMapValue.TemplateSize)
                    {
                        if (regionsMatrix[i, j] == 0) // Если это не отмеченный регион
                        {
                            // Создание уникального региона
                            RegionUniqueness regionUniqueness = new RegionUniqueness(regionValue, Color.FromArgb(rnd.Next(20, 236), rnd.Next(20, 236), rnd.Next(20, 236)));
                            // Наращивание региона
                            GrowRegion(new Point(i, j), depthMapValue.DepthMapValue, depthDeviation, (minRegionSize * (depthMapValue.TemplateSize * depthMapValue.TemplateSize)),
                                       regionUniqueness, ref regionsMatrix, ref regionsImage, ref deleteRegions);
                            regionValue++; // Следующий регион будет на 1 больше
                        }
                    }
                }
                regionsImage.Save($@"{path}\RG\imageRegion{count + 1}.bmp");
                ClearSmallRegions(ref regionsMatrix, ref regionsImage, depthMapValue.TemplateSize, deleteRegions);
                matrixRegions.Add(regionsMatrix);
                timer.Stop(); // Остановка таймера
                Tracer.Info($"Наращивание регионов для {count}-й карты глубины завершено. Это заняло {timer.ElapsedMilliseconds} мс.");
                if (writeToFile)
                {
                    string outputMatrixRegion = $@"{path}\RG\matrixRegion{count}.txt"; // Путь к матрицы с отмеченными регионами
                    Tracer.Info($"Запись {count}-й матрицы с регионами в файл {outputMatrixRegion}...");
                    FileHelper.WriteMatrix(outputMatrixRegion, regionsMatrix, ' ');    // Сохранение матрицы с регионами в файл
                    string outputImageRegion = $@"{path}\RG\imageRegion{count}.bmp";   // Путь к изображению с отмеченными регионами
                    Tracer.Info($"Запись {count}-го изображения с регионами в файл {outputImageRegion}...\n");
                    regionsImage.Save(outputImageRegion);                              // Сохранение изображения в файл
                }
                count++;                                                               // Увеличение счетчика карт глубины
            }
            return(matrixRegions);
        }
        /// <summary>
        /// Разрастание области по значению глубины
        /// </summary>
        /// <param name="point">Точка с потенциальным регионом</param>
        /// <param name="depthMapValue">Значение карты глубины</param>
        /// <param name="depthDeviation">Отклонение глубины</param>
        /// <param name="minRegionSize">Минимальный размер региона</param>
        /// <param name="regionUniqueness">Уникальность региона (значение и цвет)</param>
        /// <param name="regionsMatrix">Матрица регионов</param>
        /// <param name="regionsImage">Изображение регионов</param>
        /// <param name="deleteRegions">Регионы, которые нужно будет удалить</param>
        private static void GrowRegion(Point point, double[,] depthMapValue, double depthDeviation, int minRegionSize, RegionUniqueness regionUniqueness, ref int[,] regionsMatrix, ref Bitmap regionsImage, ref List <int> deleteRegions)
        {
            Queue <Point> points = new Queue <Point>();                           // Очередь точек (они постояянно добавляются в методе CheckPoint, если это точка региона)

            points.Enqueue(point);                                                // Добавление стратовой точки в очередь

            regionsMatrix[point.X, point.Y] = regionUniqueness.RegionValue;       // Стартовая точка принадлежит к искомому региону
            regionsImage.SetPixel(point.X, point.Y, regionUniqueness.ColorValue); // Закрашиваем стартовую точку
            double depthValue = depthMapValue[point.X, point.Y];                  // Считаем, что значение глубины в точке эталонное

            int pixelsInRegion = 0;

            double[] parameters = new double[] // Массив параметров для проверки приндлежности точки к искомому региону
            {
                depthValue - depthDeviation,   // Левая граница параметра проверки глубины
                depthValue + depthDeviation,   // Правая граница параметра проверки глубины
            };

            while (true) // Цикл закончится тогда, когда закочатся все точки в очереди
            {
                Point tempPoint;
                if (points.Count > 0) // Пока есть точки в очереди
                {
                    tempPoint = points.Dequeue();
                }
                else // Иначе выход из цикла
                {
                    break;
                }
                if (tempPoint.X > 0) // Тогда проверяем точку слева от центра
                {
                    CheckPoint(new Point(tempPoint.X - 1, tempPoint.Y), parameters, points, depthMapValue, regionsMatrix, regionsImage, regionUniqueness, ref pixelsInRegion);
                }
                if (tempPoint.X > 0 && tempPoint.Y > 0) // Тогда проверяем точку слева сверху от центра
                {
                    CheckPoint(new Point(tempPoint.X - 1, tempPoint.Y - 1), parameters, points, depthMapValue, regionsMatrix, regionsImage, regionUniqueness, ref pixelsInRegion);
                }
                if (tempPoint.Y > 0) // Тогда проверяем точку сверху от центра
                {
                    CheckPoint(new Point(tempPoint.X, tempPoint.Y - 1), parameters, points, depthMapValue, regionsMatrix, regionsImage, regionUniqueness, ref pixelsInRegion);
                }
                if (tempPoint.X < depthMapValue.GetLength(0) - 1 && tempPoint.Y > 0) // Тогда проверяем точку справа сверху от центра
                {
                    CheckPoint(new Point(tempPoint.X + 1, tempPoint.Y - 1), parameters, points, depthMapValue, regionsMatrix, regionsImage, regionUniqueness, ref pixelsInRegion);
                }
                if (tempPoint.X < depthMapValue.GetLength(0) - 1) // Тогда проверяем точку справа от центра
                {
                    CheckPoint(new Point(tempPoint.X + 1, tempPoint.Y), parameters, points, depthMapValue, regionsMatrix, regionsImage, regionUniqueness, ref pixelsInRegion);
                }
                if (tempPoint.X < depthMapValue.GetLength(0) - 1 && tempPoint.Y < depthMapValue.GetLength(1) - 1) // Тогда проверяем точку справа снизу от центра
                {
                    CheckPoint(new Point(tempPoint.X + 1, tempPoint.Y + 1), parameters, points, depthMapValue, regionsMatrix, regionsImage, regionUniqueness, ref pixelsInRegion);
                }
                if (tempPoint.Y < depthMapValue.GetLength(1) - 1) // Тогда проверяем точку снизу от центра
                {
                    CheckPoint(new Point(tempPoint.X, tempPoint.Y + 1), parameters, points, depthMapValue, regionsMatrix, regionsImage, regionUniqueness, ref pixelsInRegion);
                }
                if (tempPoint.X > 0 && tempPoint.Y < depthMapValue.GetLength(1) - 1) // тогда проверяем точку слева снизу от центра
                {
                    CheckPoint(new Point(tempPoint.X - 1, tempPoint.Y + 1), parameters, points, depthMapValue, regionsMatrix, regionsImage, regionUniqueness, ref pixelsInRegion);
                }
            }

            if (pixelsInRegion < minRegionSize)
            {
                deleteRegions.Add(regionUniqueness.RegionValue); // Добавление региона
            }
        }
 /// <summary>
 /// Проверка точки на принадлежность к искомому региону
 /// </summary>
 /// <param name="point">Точка, которую необходимо проверить</param>
 /// <param name="parameters">Параметры для проверки</param>
 /// <param name="points">Очередь точек (если точка удовлетворяет условию, то добавить её в эту очередь)</param>
 /// <param name="depthValues">Значения глубины</param>
 /// <param name="regionsMatrix">Матрица, в которой будет выделяться регион</param>
 /// <param name="regionsImage">Изображение регионов</param>
 /// <param name="regionUniqueness">Уникальность региона (цвет и номер)</param>
 /// <param name="pixelsInRegion">Пикселей в регионе</param>
 private static void CheckPoint(Point point, double[] parameters, Queue <Point> points, double[,] depthValues, int[,] regionsMatrix, Bitmap regionsImage, RegionUniqueness regionUniqueness, ref int pixelsInRegion)
 {
     if (regionsMatrix[point.X, point.Y] != 0)
     {
         return;                                                                                           // Если точка помечена, то выйти из метода
     }
     if (depthValues[point.X, point.Y] >= parameters[0] && depthValues[point.X, point.Y] <= parameters[1]) // Если глубина в точке удовлетворяют условию, то это искомый регион
     {
         pixelsInRegion += 1;                                                                              // Счетчик пикселей для этого региона
         regionsMatrix[point.X, point.Y] = regionUniqueness.RegionValue;                                   // Присваиваем точке номер региона
         regionsImage.SetPixel(point.X, point.Y, regionUniqueness.ColorValue);                             // Рисуем пиксель, принадлежащий этому региону с уникальным цветом
         points.Enqueue(new Point(point.X, point.Y));                                                      // Добавление точки в очередь, чтобы из неё строились новые точки и регионы продалжали расти
     }
     else
     {
         regionsMatrix[point.X, point.Y] = 0; // Иначе это не наш регион
     }
 }