static void Main(string[] args) { MyCustomDatasetItem[] featureData = { }; List<MyCustomDatasetItem> testPoints = new List<MyCustomDatasetItem>(); for (int i = 0; i < 1000; i++) { //points around (1,1) with most 1 distance testPoints.Add(new MyCustomDatasetItem(1, 1 + ((float)i / 1000))); testPoints.Add(new MyCustomDatasetItem(1, 1 - ((float)i / 1000))); testPoints.Add(new MyCustomDatasetItem(1 - ((float)i / 1000), 1)); testPoints.Add(new MyCustomDatasetItem(1 + ((float)i / 1000), 1)); //points around (5,5) with most 1 distance testPoints.Add(new MyCustomDatasetItem(5, 5 + ((float)i / 1000))); testPoints.Add(new MyCustomDatasetItem(5, 5 - ((float)i / 1000))); testPoints.Add(new MyCustomDatasetItem(5 - ((float)i / 1000), 5)); testPoints.Add(new MyCustomDatasetItem(5 + ((float)i / 1000), 5)); } featureData = testPoints.ToArray(); HashSet<MyCustomDatasetItem[]> clusters; var dbs = new DbscanAlgorithm<MyCustomDatasetItem>((x, y) => Math.Sqrt(((x.X - y.X) * (x.X - y.X)) + ((x.Y - y.Y) * (x.Y - y.Y)))); dbs.ComputeClusterDbscan(allPoints: featureData, epsilon: .01, minPts: 10, clusters: out clusters); }
/// <summary> /// Most basic usage of Dbscan implementation, with no eventing and async mechanism /// </summary> /// <param name="features">Features provided</param> private static void RunOfflineDbscan(List <MyFeature> features) { var simpleDbscan = new DbscanAlgorithm <MyFeature>(EuclidienDistance); var result = simpleDbscan.ComputeClusterDbscan(allPoints: features.ToArray(), epsilon: .01, minimumPoints: 10); Console.WriteLine($"Noise: {result.Noise.Count}"); Console.WriteLine($"# of Clusters: {result.Clusters.Count}"); }
static void Main(string[] args) { MyCustomFeature[] featureData = { }; var testPoints = new List <MyCustomFeature>(); //points around (1,1) with most 1 distance testPoints.Add(new MyCustomFeature(1, 1)); for (int i = 1; i <= 1000; i++) { float v = ((float)i / 1000); testPoints.Add(new MyCustomFeature(1, 1 + v)); testPoints.Add(new MyCustomFeature(1, 1 - v)); testPoints.Add(new MyCustomFeature(1 - v, 1)); testPoints.Add(new MyCustomFeature(1 + v, 1)); } //points around (5,5) with most 1 distance testPoints.Add(new MyCustomFeature(5, 5)); for (int i = 1; i <= 1000; i++) { float v = ((float)i / 1000); testPoints.Add(new MyCustomFeature(5, 5 + v)); testPoints.Add(new MyCustomFeature(5, 5 - v)); testPoints.Add(new MyCustomFeature(5 - v, 5)); testPoints.Add(new MyCustomFeature(5 + v, 5)); } featureData = testPoints.ToArray(); //INFO: applied euclidean distance as metric calculation function var dbscan = new DbscanAlgorithm <MyCustomFeature>( (feature1, feature2) => Math.Sqrt( ((feature1.X - feature2.X) * (feature1.X - feature2.X)) + ((feature1.Y - feature2.Y) * (feature1.Y - feature2.Y)) ) ); var result = dbscan.ComputeClusterDbscan(allPoints: featureData, epsilon: .01, minimumPoints: 10); }
/// <summary> /// This is the method that actually does the work. /// </summary> /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param> protected override void SolveInstance(IGH_DataAccess DA) { bool IsPointData = false; GH_Structure <IGH_Goo> data = new GH_Structure <IGH_Goo>(); List <double> eps = new List <double>(); List <int> minP = new List <int>(); if (!DA.GetDataTree(0, out data)) { return; } if (!DA.GetDataList(1, eps)) { return; } if (!DA.GetDataList(2, minP)) { return; } data.Simplify(GH_SimplificationMode.CollapseAllOverlaps); List <DataSetItemPoint[]> points = new List <DataSetItemPoint[]>(); for (int i = 0; i < data.Branches.Count; i++) { DataSetItemPoint[] pp = new DataSetItemPoint[data.Branches[i].Count]; for (int j = 0; j < data.Branches[i].Count; j++) { if (data.Branches[i][j] is GH_Point) { IsPointData = true; GH_Point target = new GH_Point(); if (GH_Convert.ToGHPoint(data.Branches[i][j], GH_Conversion.Both, ref target)) { pp[j] = new DataSetItemPoint(target.Value.X, target.Value.Y, target.Value.Z, 0.0); } } else { break; } } if (IsPointData) { points.Add(pp); } else { break; } } // double data if (!IsPointData) { DataSetItemPoint[] pp = new DataSetItemPoint[data.Branches.Count]; for (int i = 0; i < data.Branches.Count; i++) { DataSetItemPoint p = new DataSetItemPoint(); for (int j = 0; j < data.Branches[i].Count; j++) { if (data.Branches[i][j] is GH_Number) { if (GH_Convert.ToDouble(data.Branches[i][j], out double value, GH_Conversion.Both)) { switch (j) { case 0: p.X = value; break; case 1: p.Y = value; break; case 2: p.Z = value; break; case 3: p.W = value; break; } } } } pp[i] = p; } points.Add(pp); } if (IsPointData) { DataTree <IGH_Goo> output = new DataTree <IGH_Goo>(); for (int i = 0; i < points.Count; i++) { DbscanAlgorithm <DataSetItemPoint> dbs = new DbscanAlgorithm <DataSetItemPoint>((x, y) => Math.Sqrt(((x.X - y.X) * (x.X - y.X)) + ((x.Y - y.Y) * (x.Y - y.Y)) + ((x.Z - y.Z) * (x.Z - y.Z)) + ((x.W - y.W) * (x.W - y.W)))); dbs.ComputeClusterDbscan(points[i].ToArray(), eps[i], minP[i], out HashSet <DataSetItemPoint[]> clusters3d); for (int j = 0; j < clusters3d.Count; j++) { ConcurrentQueue <GH_Point> _points = new ConcurrentQueue <GH_Point>(); Parallel.ForEach(clusters3d.ElementAt(j), p => { _points.Enqueue(new GH_Point(new Point3d(p.X, p.Y, p.Z))); }); output.AddRange(_points.ToList(), new GH_Path(i, j)); } } DA.SetDataTree(0, output); } else { DataTree <GH_Number> output = new DataTree <GH_Number>(); for (int i = 0; i < points.Count; i++) { DbscanAlgorithm <DataSetItemPoint> dbs = new DbscanAlgorithm <DataSetItemPoint>((x, y) => Math.Sqrt(((x.X - y.X) * (x.X - y.X)) + ((x.Y - y.Y) * (x.Y - y.Y)) + ((x.Z - y.Z) * (x.Z - y.Z)) + ((x.W - y.W) * (x.W - y.W)))); dbs.ComputeClusterDbscan(points[i].ToArray(), eps[i], minP[i], out HashSet <DataSetItemPoint[]> clusters3d); for (int j = 0; j < clusters3d.Count; j++) { ConcurrentQueue <List <double> > _points = new ConcurrentQueue <List <double> >(); for (int k = 0; k < clusters3d.ElementAt(j).Length; k++) { List <GH_Number> ii = new List <GH_Number>(); GH_Number target1 = new GH_Number(); GH_Number target2 = new GH_Number(); GH_Number target3 = new GH_Number(); GH_Number target4 = new GH_Number(); if (GH_Convert.ToGHNumber(clusters3d.ElementAt(j).ElementAt(k).X, GH_Conversion.Both, ref target1)) { ii.Add(target1); } if (GH_Convert.ToGHNumber(clusters3d.ElementAt(j).ElementAt(k).Y, GH_Conversion.Both, ref target2)) { ii.Add(target2); } if (GH_Convert.ToGHNumber(clusters3d.ElementAt(j).ElementAt(k).Z, GH_Conversion.Both, ref target3)) { ii.Add(target3); } if (GH_Convert.ToGHNumber(clusters3d.ElementAt(j).ElementAt(k).W, GH_Conversion.Both, ref target4)) { ii.Add(target4); } output.AddRange(ii, new GH_Path(i, j, k)); } } } DA.SetDataTree(0, output); } }
static void Main(string[] args) { MyCustomFeature[] featureData = { }; var testPoints = new List <MyCustomFeature>() { }; //points around (1,1) with most 1 distance testPoints.Add(new MyCustomFeature(1, 1)); for (int i = 1; i <= 1000; i++) { var v = (float)i / 1000; testPoints.Add(new MyCustomFeature(1, 1 + v)); testPoints.Add(new MyCustomFeature(1, 1 - v)); testPoints.Add(new MyCustomFeature(1 - v, 1)); testPoints.Add(new MyCustomFeature(1 + v, 1)); } //points around (5,5) with most 1 distance testPoints.Add(new MyCustomFeature(5, 5)); for (int i = 1; i <= 1000; i++) { var v = (float)i / 1000; testPoints.Add(new MyCustomFeature(5, 5 + v)); testPoints.Add(new MyCustomFeature(5, 5 - v)); testPoints.Add(new MyCustomFeature(5 - v, 5)); testPoints.Add(new MyCustomFeature(5 + v, 5)); } //noise point testPoints.Add(new MyCustomFeature(10, 10)); featureData = testPoints.ToArray(); //INFO: applied euclidean distance as metric calculation function var dbscan = new DbscanAlgorithm <MyCustomFeature>( (feature1, feature2) => Math.Sqrt( ((feature1.X - feature2.X) * (feature1.X - feature2.X)) + ((feature1.Y - feature2.Y) * (feature1.Y - feature2.Y)) ) ); var result = dbscan.ComputeClusterDbscan(allPoints: featureData, epsilon: .01, minimumPoints: 10); Console.WriteLine($"Noise: {result.Noise.Length}"); Console.WriteLine($"# of Clusters: {result.Clusters.Count}"); //INFO: applied euclidean distance as metric calculation function //INFO: second argument of constructor takes an instance implemented with IDbscanEventPublisher interface var dbscanWithEventing = new DbscanAlgorithm <MyCustomFeature>( (feature1, feature2) => Math.Sqrt( ((feature1.X - feature2.X) * (feature1.X - feature2.X)) + ((feature1.Y - feature2.Y) * (feature1.Y - feature2.Y)) ), new DbscanLogger() ); var resultWithEventing = dbscanWithEventing.ComputeClusterDbscan(allPoints: featureData, epsilon: .01, minimumPoints: 10); Console.WriteLine($"Noise: {resultWithEventing.Noise.Length}"); Console.WriteLine($"# of Clusters: {resultWithEventing.Clusters.Count}"); }
private void ProcessFrame(object sender, EventArgs e) { if (BeforeProcessFrame != null) BeforeProcessFrame(); Mat curImage = new Mat(); var imageGrabbed = capture.Retrieve(curImage); { if (!imageGrabbed) { capture.Stop(); return; } if (counter == 0) { } Interlocked.Increment(ref counter); if (counter == 1) { } if (counter % FrameInterval != 0) { if (counter % FrameInterval == 1) { prevImage = new Image<Bgr, byte>(curImage.Bitmap); } return; } //Process starts here var prevGray = prevImage.Convert<Gray, byte>(); var curGray = curImage.ToImage<Gray, byte>(); var denseResult = new DenseOpticalFlowAlgorithm(prevGray, curGray, Parameters) { VectorNoiseThreshold = VectorGlobalThreshold, WindowSideLength = WindowSideLength, ComputeFlowImage = ComputeFlowImage }.Compute(); if (OpticalFlowVectorsProcessed != null) { OpticalFlowVectorsProcessed(denseResult.FlowVectorImage); } OpticalFlowPoint[] pointsToCluster = denseResult.FlowLineArray .Where(x => x.OverThreshold) .Select(x => new OpticalFlowPoint( x.Line.P2, x.Line.GetExteriorAngleDegree(DenseOpticalFlowAlgorithm.UnitVectorOfX))) .ToArray(); var clusters = new DbscanAlgorithm<OpticalFlowPoint>( (p, x) => p - x, Math.Abs(OrientationAngle) <= 0 || Math.Abs(OrientationAngle) >= 360 ? (Func<OpticalFlowPoint, OpticalFlowPoint, bool>)null : (point, x) => Math.Abs(point.ExteriorAngleDegree - x.ExteriorAngleDegree) < OrientationAngle) .ComputeClusterDbscan(pointsToCluster, Epsilon, MinPts); #region Draw vectors per frame var processedImage = new Image<Bgr, byte>(curImage.Bitmap); foreach (var line in denseResult.FlowLineArray.Where(x => x.OverThreshold).Select(x => x.Line).ToArray()) { processedImage.Draw(new CircleF(line.P2, 2), new Bgr(Color.Yellow)); } #endregion //draw cluster rectangles foreach (var points in clusters) { var polyLines = PointCollection.BoundingRectangle(points.Select(x => x.EndPoint).ToArray()); processedImage.Draw(polyLines, new Bgr(Color.Red), 2); } //draw convex hull foreach (var points in clusters) { PointF[] hull = CvInvoke.ConvexHull(points.Select(x => x.EndPoint).ToArray()); processedImage.DrawPolyline(Array.ConvertAll(hull, Point.Round), true, new Bgr(Color.Blue)); } ImageProcessed(processedImage); } }