public CvContours GetNearPointContour(Point pt, CenterDrawMode centerMode)
        {
            CvContours resultContours = new CvContours();
            int        nearId         = 0;
            double     minLen         = double.MaxValue;

            for (int nId = 0; nId < m_contours.Count; nId++)
            {
                Point centerPoint = m_contours[nId].BoundingCenter;
                switch (centerMode)
                {
                case CenterDrawMode.PixelWeightCenter:
                    centerPoint = m_contours[nId].WeightCenter;
                    break;

                case CenterDrawMode.HistogramCenter:
                    centerPoint = m_contours[nId].HistogramCenter;
                    break;
                }

                double len = (centerPoint.X - pt.X) * (centerPoint.X - pt.X) +
                             (centerPoint.Y - pt.Y) * (centerPoint.Y - pt.Y);

                if (len < minLen)
                {
                    minLen = len;
                    nearId = nId;
                }
            }

            resultContours.m_contours.Add(m_contours[nearId].Clone());
            return(resultContours);
        }
        public CvContours GetAroundContours(CenterDrawMode centerMode, int histogramScale = 1, double radiusScale = 1, MovingPredictType movingType = MovingPredictType.None, int movingRange = 1)
        {
            CvContours resultContour = new CvContours();

            foreach (var contour in m_contours)
            {
                resultContour.m_contours.Add(contour.ToAraundContour(centerMode, histogramScale, radiusScale, movingType, movingRange));
            }

            return(resultContour);
        }
        public CvContours GetInsideRectArea(Rectangle rect)
        {
            CvContours resultContours = new CvContours();

            foreach (var contour in m_contours)
            {
                if (contour.IsInsideRect(rect))
                {
                    resultContours.m_contours.Add(contour.Clone());
                }
            }
            return(resultContours);
        }
        /// <summary>
        /// Сдвигает контуры
        /// </summary>
        /// <param name="shiftX"></param>
        /// <param name="shiftY"></param>
        /// <param name="width">Если не -1 будет введино ограничение на макс ширену</param>
        /// <param name="height">Если не -1 будет введино ограничение на макс высоту</param>
        /// <returns></returns>
        public CvContours Shift(int shiftX, int shiftY, int width = -1, int height = -1)
        {
            CvContours resultContour = new CvContours();

            foreach (var contour in m_contours)
            {
                var shiftCntr = contour.Clone();
                shiftCntr.Shift(shiftX, shiftY, width, height);
                resultContour.m_contours.Add(shiftCntr);
            }

            return(resultContour);
        }
        public CvContours GetPerimeterInRange(double minVal, double maxVal)
        {
            CvContours resultContours = new CvContours();

            foreach (var contour in m_contours)
            {
                if ((contour.Perimeter >= minVal) && (contour.Perimeter <= maxVal))
                {
                    resultContours.m_contours.Add(contour.Clone());
                }
            }

            return(resultContours);
        }
        public CvContours GetAreaInRange(double minVal, double maxVal)
        {
            CvContours resultContour = new CvContours();

            foreach (var contour in m_contours)
            {
                if ((contour.Area >= minVal) && (contour.Area <= maxVal))
                {
                    resultContour.m_contours.Add(contour.Clone());
                }
            }

            return(resultContour);
        }
        public CvContours GetBoundingRectInRange(int minWidth, int maxWidth, int minHeight, int maxHeight)
        {
            CvContours resultContours = new CvContours();

            foreach (var contour in m_contours)
            {
                if ((contour.BoundingRect.Width >= minWidth) && (contour.BoundingRect.Width <= maxWidth) &&
                    (contour.BoundingRect.Height >= minHeight) && (contour.BoundingRect.Height <= maxHeight))
                {
                    resultContours.m_contours.Add(contour.Clone());
                }
            }

            return(resultContours);
        }
        public CvContours GetMaxAreaContour()
        {
            CvContours resultContours = new CvContours();
            int        maxAreaId      = 0;

            if (m_contours.Count == 0)
            {
                return(resultContours);
            }

            for (int nId = 0; nId < m_contours.Count; nId++)
            {
                if (m_contours[maxAreaId].Area < m_contours[nId].Area)
                {
                    maxAreaId = nId;
                }
            }

            resultContours.m_contours.Add(m_contours[maxAreaId].Clone());
            return(resultContours);
        }
        // По идее ещё нужен алгоритм кластеризации
        //public CvContours[] GetClasters()


        /// <summary>
        /// Сливает все конутра коллекции во внешний контур с единым центром
        /// </summary>
        /// <param name="centerMode"></param>
        /// <param name="histogramScale"></param>
        /// <param name="radiusScale"></param>
        /// <returns></returns>
        public CvContours GetConcatenateAroundContour(CenterDrawMode centerMode = CenterDrawMode.BoundingRectCenter, int histogramScale = 1, double radiusScale = 1)
        {
            CvContours resultContour = new CvContours();

            if (m_contours.Count == 0)
            {
                return(resultContour);
            }

            int totalPoints = 0;

            foreach (var contour in m_contours)
            {
                totalPoints += contour.PointsCnt;
            }

            if (totalPoints == 0)
            {
                return(resultContour);
            }

            double xx = 0;
            double yy = 0;

            int shift = 0;

            Point[] points = new Point[totalPoints];
            foreach (var contour in m_contours)
            {
                contour.CopyPointsTo(points, shift);
                shift += contour.PointsCnt;

                switch (centerMode)
                {
                case CenterDrawMode.BoundingRectCenter:
                    xx += contour.BoundingCenter.X;
                    yy += contour.BoundingCenter.Y;
                    break;

                case CenterDrawMode.PixelWeightCenter:
                    xx += contour.WeightCenter.X;
                    yy += contour.WeightCenter.Y;
                    break;

                case CenterDrawMode.HistogramCenter:
                    contour.UpdateXYHistogram();
                    xx += contour.HistogramCenter.X;
                    yy += contour.HistogramCenter.Y;
                    break;
                }
            }

            Point commonCenterPoint = new Point((int)(xx / m_contours.Count), (int)(yy / m_contours.Count));
            var   aroundPoints      = CvContourInfo.AraundPoints(commonCenterPoint, points, histogramScale, radiusScale);

            CvContourInfo contourInfo = new CvContourInfo(0, -1, aroundPoints);

            resultContour.m_contours.Add(contourInfo);

            return(resultContour);
        }