Beispiel #1
0
        public override bool Do()
        {
            try
            {
                m_contours.Clear();

                FilterDrawMode DrawOn     = (FilterDrawMode)EnumPropertys["DrawOn"].Value;
                CenterDrawMode CenterMode = (CenterDrawMode)EnumPropertys["CenterMode"].Value;


                FilterDrawMode   BoundingRect      = (FilterDrawMode)EnumPropertys["BoundingRect"].Value;
                bool             bShowBoundingRect = BoundingRect == FilterDrawMode.Show;
                FillDrawModeEnum FillMode          = (FillDrawModeEnum)EnumPropertys["FillMode"].Value;
                bool             bFill             = FillMode != FillDrawModeEnum.None;


                MovingPredictType movingType = (MovingPredictType)EnumPropertys["MovingType"].Value;


                foreach (var src in Sources)
                {
                    IContourFilter searchFilter = src as IContourFilter;
                    if (searchFilter == null)
                    {
                        continue;
                    }
                    var outData     = src.GetOut();
                    var contourSrcs = searchFilter.GetResultContours();
                    for (int dataID = 0; dataID < outData.Count; dataID++)
                    {
                        var dst            = outData[dataID].Image.Clone();
                        var aroundContours = contourSrcs[dataID].GetAroundContours(CenterMode,
                                                                                   IntPropertys["HScale"].Value,
                                                                                   FloatPropertys["RScale"].Value,
                                                                                   movingType, IntPropertys["MovingRange"].Value
                                                                                   );
                        m_contours.Add(aroundContours);

                        if (DrawOn == FilterDrawMode.Show)
                        {
                            if (FillMode == FillDrawModeEnum.SourceMeanColor)
                            {
                                aroundContours.UpdateMainColorAsMeanOfMask(dst);
                            }

                            aroundContours.Draw(dst, bFill, bShowBoundingRect, CenterMode);
                        }

                        this.m_out.Add(new DataSrc(dst, outData[dataID].Info, false));
                    }
                }
            }
            catch (CvException ex)
            {
                return(false);
            }
            return(true);
        }
        public override bool Do()
        {
            try
            {
                var bReqFullUpdate = !m_isSelfClearOut || (histogramsResults.Count == 0);
                if (bReqFullUpdate)
                {
                    histogramsResults.Clear();
                }

                IMovingPredict    movingPredict = null;
                MovingPredictType movingType    = (MovingPredictType)EnumPropertys["MovingType"].Value;
                switch (movingType)
                {
                case MovingPredictType.MovingAverage:
                    movingPredict = new MovingAverage(IntPropertys["MovingRange"].Value);
                    break;

                case MovingPredictType.MovingMediana:
                    movingPredict = new MovingMediana(IntPropertys["MovingRange"].Value);
                    break;

                default:
                    movingPredict = new MovingAverage(IntPropertys["MovingRange"].Value);
                    break;
                }

                int listID = 0;
                for (int srcID = 0; srcID < Sources.Count; srcID++)
                {
                    var outDatas = Sources[srcID].GetOut();
                    for (int dataID = 0; dataID < outDatas.Count; dataID++)
                    {
                        if (bReqFullUpdate)
                        {
                            histogramsResults.Add(RGBHistogram.GetHistograms(outDatas[dataID].Image));
                        }

                        Mat copy = outDatas[dataID].Image.Clone();


                        RGBHistogram.DrawChannel(copy, IntPropertys["x_show"].Value, IntPropertys["y_show"].Value,
                                                 FloatPropertys["scaleX"].Value, FloatPropertys["scaleY"].Value, movingPredict,
                                                 histogramsResults[listID], 0, new Bgr(0, 0, 255).MCvScalar, new Bgr(50, 0, 255).MCvScalar, false);


                        RGBHistogram.DrawChannel(copy, IntPropertys["x_show"].Value, IntPropertys["y_show"].Value,
                                                 FloatPropertys["scaleX"].Value, FloatPropertys["scaleY"].Value, movingPredict,
                                                 histogramsResults[listID], 1, new Bgr(255, 0, 0).MCvScalar, new Bgr(255, 0, 50).MCvScalar, false);

                        RGBHistogram.DrawChannel(copy, IntPropertys["x_show"].Value, IntPropertys["y_show"].Value,
                                                 FloatPropertys["scaleX"].Value, FloatPropertys["scaleY"].Value, movingPredict,
                                                 histogramsResults[listID], 2, new Bgr(0, 255, 0).MCvScalar, new Bgr(50, 255, 50).MCvScalar, false);

                        listID++;
                        this.m_out.Add(new DataSrc(copy, outDatas[dataID].Info, false));
                    }
                }
            }
            catch (Exception ex) {
                return(false);
            }
            return(true);
        }
        /// <summary>
        /// Создаёт контур из внешних точек при помощи афинной гистограммы
        /// </summary>
        /// <param name="centerMode">Выбор центра внешнего контура</param>
        /// <param name="histogramScale">Число баров гистограммы 3*histogramScale* (длина стороны матрицы)</param>
        /// <param name="radiusScale">Скалированный радиус от центра</param>
        /// <returns></returns>
        public CvContourInfo ToAraundContour(CenterDrawMode centerMode = CenterDrawMode.BoundingRectCenter, int histogramScale = 1, double radiusScale = 1, MovingPredictType movingType = MovingPredictType.None, int movingRange = 1)
        {
            CvContourInfo araundContour = new CvContourInfo();

            Point center = this.BoundingCenter;

            switch (centerMode)
            {
            case CenterDrawMode.PixelWeightCenter: center = this.WeightCenter; break;

            case CenterDrawMode.HistogramCenter:
                UpdateXYHistogram();
                center = this.HistogramCenter;
                break;
            }

            araundContour.m_points = AraundPoints(center, m_points, histogramScale, radiusScale, movingType, movingRange);

            araundContour.Id              = this.Id;
            araundContour.ParentId        = this.ParentId;
            araundContour.MainColor       = new MCvScalar(this.MainColor.V0, this.MainColor.V1, this.MainColor.V2);
            araundContour.PerimeterColor  = new MCvScalar(this.PerimeterColor.V0, this.PerimeterColor.V1, this.PerimeterColor.V2);
            araundContour.Area            = this.Area;
            araundContour.Perimeter       = this.Perimeter;
            araundContour.BoundingRect    = new Rectangle(this.BoundingRect.X, this.BoundingRect.Y, this.BoundingRect.Width, this.BoundingRect.Height);
            araundContour.BoundingCenter  = new Point(this.BoundingCenter.X, this.BoundingCenter.Y);
            araundContour.WeightCenter    = new Point(this.WeightCenter.X, this.WeightCenter.Y);
            araundContour.HistogramCenter = new Point(this.HistogramCenter.X, this.HistogramCenter.Y);

            return(araundContour);
        }
        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);
        }
        /// <summary>
        /// Отдаёт внешний мыссив точек при помощи афинной гистограммы
        /// Чтобы не счиатать чисто углу, считается двухмерная-гистограмм периметра прямоугольника с ранджем:
        /// [+1;-1]     []      [+1;+1]
        /// []          []          []
        /// [-1;-1]     []      [-1;+1]
        /// Все внешние точки периметра это элементы гистограммы, мин. размер [3;3] и он скейлится на [3*scale;3*scale], если конутр нужно описать более точными углами
        /// Периметр скорее описывает апроксимированный круг, а не квадрат
        /// </summary>
        /// <param name="center">Аффинный центр</param>
        /// <param name="points">Список точек</param>
        /// <param name="histogramScale">Число баров гистограммы 3*histogramScale* (длина стороны матрицы)</param>
        /// <param name="radiusScale">Изменяет радиус от центра для каждой внешней точки из пропорции</param>
        /// <param name="movingPredict">Если не null, то результат будет пропущен через скользящую для разглаживания контура</param>
        /// <returns></returns>
        public static Point[] AraundPoints(Point center, Point[] points, int histogramScale = 1, double radiusScale = 1, MovingPredictType movingType = MovingPredictType.None, int movingRange = 1)
        {
            int perimeterSRectSz = 2 * 3 * histogramScale + 2 * (3 * histogramScale - 2);

            Point[] exPoints = new Point[perimeterSRectSz];


            int maxIdx     = 3 * histogramScale - 1;
            int maxIdxHalf = (3 * histogramScale) / 2;

            int maxIdxHalfB = maxIdxHalf;

            if (histogramScale % 2 == 0)
            {
                maxIdxHalfB -= 1;
            }


            double reMaxIdx = 1.0 / maxIdx;


            // псевдоафинное пространсво
            double[,] sincosHistogram = new double[3 * histogramScale, 3 * histogramScale];

            // set Histogram
            foreach (var pt in points)
            {
                double sqlen = (center.X - pt.X) * (center.X - pt.X) +
                               (center.Y - pt.Y) * (center.Y - pt.Y);
                double len = Math.Sqrt(sqlen);

                if (len == 0)
                {
                    continue;
                }

                // [-1;+1]
                double sinx = (pt.X - center.X) / len;
                double cosx = (pt.Y - center.Y) / len;

                // [0;+2]
                sinx += 1;
                cosx += 1;

                // [0;+1]
                sinx /= 2;
                cosx /= 2;

                // [0;+maxIdx]
                int xx = (int)Math.Round(sinx * maxIdx, MidpointRounding.AwayFromZero);
                int yy = (int)Math.Round(cosx * maxIdx, MidpointRounding.AwayFromZero);

                if (sincosHistogram[xx, yy] < len)
                {
                    sincosHistogram[xx, yy] = len;
                }
            }

            // Для востановления будем пользоваться индексами гистограммы
            // w = l * sin(x)
            // h = l * cos(x)

            // теперь точки нужно связать, для этого их нужно в верном порядке обойти
            // Т.к. точки расположенный по кругу, остаётся искать не нулевые элементы в четвертях и их обхоить
            // обход по часовой стрелки:

            int ptId = 0;

            // w - sin
            // h - cos


            // верл - право
            for (int w = maxIdxHalf; w <= maxIdx; w++)
            {
                for (int h = 0; h < maxIdxHalf; h++)
                {
                    if (sincosHistogram[w, h] != 0)
                    {
                        double widht  = radiusScale * sincosHistogram[w, h] * (w * reMaxIdx * 2 - 1);
                        double height = radiusScale * sincosHistogram[w, h] * (h * reMaxIdx * 2 - 1);
                        exPoints[ptId++] = new Point(center.X + (int)(widht), center.Y + (int)(height));
                    }
                }
            }

            // низ право
            for (int h = maxIdxHalf; h <= maxIdx; h++)
            {
                for (int w = maxIdx; w > maxIdxHalfB; w--)
                {
                    if (sincosHistogram[w, h] != 0)
                    {
                        double widht  = radiusScale * sincosHistogram[w, h] * (w * reMaxIdx * 2 - 1);
                        double height = radiusScale * sincosHistogram[w, h] * (h * reMaxIdx * 2 - 1);
                        exPoints[ptId++] = new Point(center.X + (int)(widht), center.Y + (int)(height));
                    }
                }
            }

            //// низ лево
            for (int w = maxIdxHalfB; w >= 0; w--)
            {
                for (int h = maxIdx; h > maxIdxHalfB; h--)
                {
                    if (sincosHistogram[w, h] != 0)
                    {
                        double widht  = radiusScale * sincosHistogram[w, h] * (w * reMaxIdx * 2 - 1);
                        double height = radiusScale * sincosHistogram[w, h] * (h * reMaxIdx * 2 - 1);
                        exPoints[ptId++] = new Point(center.X + (int)(widht), center.Y + (int)(height));
                    }
                }
            }

            // верх лево
            for (int h = maxIdxHalfB; h >= 0; h--)
            {
                for (int w = 0; w < maxIdxHalf; w++)
                {
                    if (sincosHistogram[w, h] != 0)
                    {
                        double widht  = radiusScale * sincosHistogram[w, h] * (w * reMaxIdx * 2 - 1);
                        double height = radiusScale * sincosHistogram[w, h] * (h * reMaxIdx * 2 - 1);
                        exPoints[ptId++] = new Point(center.X + (int)(widht), center.Y + (int)(height));
                    }
                }
            }

            // Некоторые точки уходят в ноль, их стоит исключить из ответа
            // Плюс тут же пррёдусь скользящей средней по ним всем
            var outPoints = new Point[ptId];

            if (ptId > 0)
            {
                switch (movingType)
                {
                case MovingPredictType.None:
                    for (int n = 0; n < ptId; n++)
                    {
                        outPoints[n] = exPoints[n];
                    }
                    break;

                case MovingPredictType.MovingAverage:
                {
                    MovingAverage movingX = new MovingAverage(movingRange);
                    MovingAverage movingY = new MovingAverage(movingRange);

                    for (int n = 0; n < movingRange; n++)
                    {
                        movingX.Predict(exPoints[0].X);
                        movingY.Predict(exPoints[0].Y);
                    }

                    for (int n = 0; n < ptId; n++)
                    {
                        outPoints[n] = new Point((int)movingX.Predict(exPoints[n].X),
                                                 (int)movingY.Predict(exPoints[n].Y));
                    }
                }
                break;

                case MovingPredictType.MovingMediana:
                {
                    MovingMediana movingX = new MovingMediana(movingRange);
                    MovingMediana movingY = new MovingMediana(movingRange);

                    for (int n = 0; n < movingRange; n++)
                    {
                        movingX.Predict(exPoints[0].X);
                        movingY.Predict(exPoints[0].Y);
                    }

                    for (int n = 0; n < ptId; n++)
                    {
                        outPoints[n] = new Point((int)movingX.Predict(exPoints[n].X),
                                                 (int)movingY.Predict(exPoints[n].Y));
                    }
                }
                break;
                }
            }

            return(outPoints);
        }