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); }