问题描述
跟进> 这个 ,我有一堆坐标,然后将它们作为坐标系绘制.现在,我想摆脱所有噪音,并过滤坐标,以提供"更清晰"或"更清洁"的路径,而"更少"或"更好"或"更好"的数据来处理.要解释更多,我需要揭露我的很棒的 绘画技能如下:
电流:
需要:
注意:
-
我需要删除坐标
-
我可能需要添加坐标
-
我可能需要忽略最短的邻居
我唯一能想到的是,使用最短路径算法,例如 a>.并在某种数据结构中填充数据,以包含每个节点的邻居和成本,然后执行算法.我不想启动可能是错误或浪费的东西.如果可能的话,我很想在上看到伪代码?
P.S我目前在WPF C#上,但我愿意使用C#或C ++进行任何任务.谢谢
推荐答案
您所追求的是找到路径应用程序.有几种方法可以解决此问题,但是更简单的方法是:
Pick a starting point, add to list While True: For each border_pt bordering last point on list: Count number of points bordering border_pt If count > best_count: Mark border_pt as best if border_pt is empty: break Add border_pt to list
这是一些C#代码,它可以根据您的云生成一个简单的列表:
using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApplication1 { class ExampleProgram : Form { const int GridWidth = 24; const int GridHeight = 15; List<Point> m_points = new List<Point>(); List<Point> m_trail = new List<Point>(); [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new ExampleProgram()); } ExampleProgram() { // Simple little tool to add a bunch of points AddPoints( 0, 4, 1, 3, 1, 4, 1, 5, 2, 4, 2, 5, 2, 6, 3, 4, 3, 5, 4, 5, 4, 6, 5, 5, 6, 5, 6, 4, 5, 4, 7, 4, 7, 3, 8, 3, 8, 4, 8, 5, 8, 6, 9, 6, 9, 5, 9, 4, 9, 3, 10, 2, 10, 3, 10, 4, 10, 5, 10, 6, 11, 5, 11, 4, 11, 3, 11, 2, 12, 4, 12, 5, 13, 5, 13, 6, 13, 8, 14, 8, 14, 7, 14, 6, 15, 7, 15, 8, 15, 9, 14, 9, 14, 10, 13, 10, 12, 10, 11, 10, 13, 11, 14, 11, 15, 11, 15, 12, 16, 12, 17, 12, 18, 12, 19, 12, 18, 11, 17, 11, 17, 10, 18, 10, 19, 10, 19, 9, 19, 8, 20, 8, 21, 8, 18, 7, 19, 7, 20, 7, 21, 7, 21, 6, 22, 6, 23, 6, 21, 5, 20, 5, 19, 5, 19, 4, 18, 4, 17, 4, 20, 3, 21, 3, 22, 3, 20, 2, 19, 2, 18, 2, 19, 1, 20, 1, 21, 1, 19, 0, 18, 0, 10, 0, 4, 1); // Very basic form logic ClientSize = new System.Drawing.Size(GridWidth * 20, GridHeight * 20); DoubleBuffered = true; Paint += ExampleProgram_Paint; // Add a new point to the form (commented out) // MouseUp += ExampleProgram_MouseUp_AddPoint; // Draw the trail we find MouseUp += ExampleProgram_MouseUp_AddTrail; // Pick a starting point to start finding the trail from // TODO: Left as an excersize for the reader to decide how to pick // the starting point programatically m_trail.Add(new Point(0, 4)); } IEnumerable<Point> Border(Point pt) { // Return all points that border a give point if (pt.X > 0) { if (pt.Y > 0) { yield return new Point(pt.X - 1, pt.Y - 1); } yield return new Point(pt.X - 1, pt.Y); if (pt.Y < GridHeight - 1) { yield return new Point(pt.X - 1, pt.Y + 1); } } if (pt.Y > 0) { yield return new Point(pt.X, pt.Y - 1); } if (pt.Y < GridHeight - 1) { yield return new Point(pt.X, pt.Y + 1); } if (pt.X < GridWidth - 1) { if (pt.Y > 0) { yield return new Point(pt.X + 1, pt.Y - 1); } yield return new Point(pt.X + 1, pt.Y); if (pt.Y < GridHeight - 1) { yield return new Point(pt.X + 1, pt.Y + 1); } } } void AddPoints(params int[] points) { // Helper to add a bunch of points to our list of points for (int i = 0; i < points.Length; i += 2) { m_points.Add(new Point(points[i], points[i + 1])); } } void ExampleProgram_MouseUp_AddTrail(object sender, MouseEventArgs e) { // Calculate the trail while (true) { // Find the best point for the next point int bestCount = 0; Point best = new Point(); // At the current end point, test all the points around it foreach (var pt in Border(m_trail[m_trail.Count - 1])) { // And for each point, see how many points this point borders int count = 0; if (m_points.Contains(pt) && !m_trail.Contains(pt)) { foreach (var test in Border(pt)) { if (m_points.Contains(test)) { if (m_trail.Contains(test)) { // This is a point both in the original cloud, and the current // trail, so give it a negative weight count--; } else { // We haven't visited this point, so give it a positive weight count++; } } } } if (count > bestCount) { // This point looks better than anything we've found, so // it's the best one so far bestCount = count; best = pt; } } if (bestCount <= 0) { // We either didn't find anything, or what we did find was bad, so // break out of the loop, we're done break; } m_trail.Add(best); } Invalidate(); } void ExampleProgram_MouseUp_AddPoint(object sender, MouseEventArgs e) { // Just add the point, and dump it out int x = (int)Math.Round((((double)e.X) - 10.0) / 20.0, 0); int y = (int)Math.Round((((double)e.Y) - 10.0) / 20.0, 0); m_points.Add(new Point(x, y)); Debug.WriteLine("m_points.Add(new Point(" + x + ", " + y + "));"); Invalidate(); } void ExampleProgram_Paint(object sender, PaintEventArgs e) { // Simple drawing, just draw a grid, and the points e.Graphics.Clear(Color.White); for (int x = 0; x < GridWidth; x++) { e.Graphics.DrawLine(Pens.Black, x * 20 + 10, 0, x * 20 + 10, ClientSize.Height); } for (int y = 0; y < GridHeight; y++) { e.Graphics.DrawLine(Pens.Black, 0, y * 20 + 10, ClientSize.Width, y * 20 + 10); } foreach (var pt in m_points) { e.Graphics.FillEllipse(Brushes.Black, (pt.X * 20 + 10) - 5, (pt.Y * 20 + 10) - 5, 10, 10); } foreach (var pt in m_trail) { e.Graphics.FillEllipse(Brushes.Red, (pt.X * 20 + 10) - 6, (pt.Y * 20 + 10) - 6, 12, 12); } } } }
其他推荐答案
您正在寻找一种称为稀疏或骨骼化的操作,然后可能进行一些后处理以删除小部件.有不同的算法提供不同的属性.例如 guo and Hall's 和 Zhang and Suen's .
其他推荐答案
您可能需要考虑将坐标视为二进制图像,并应用一些形态学技术图像.
Thinning 可能会给您良好的结果,但是处理类似在广泛的情况下,这可能很棘手.
问题描述
Following up with this, I have a bunch of coordinates and I draw them on a bitmap image as a coordinate system. Now, I would like to get rid of all the noise, and filter coordinates to give a "clearer" or "cleaner" path and "less" or "better" data to work on. To explain more, I will need to expose my awesome painting skills as follows:
Current:
Desired:
Notice:
I will need to delete coordinates
I might need to add coordinates
I might need to ignore shortest neighbor in some cases
The only thing I can think of, is to use a shortest path algorithm such as A* and Dijkstra. And populate data in some sort of data structure to contain neighbors and costs for every node and then to execute the algorithm. I don't want to start something that might be wrong or waste. I would love to see a pseudo code if possible on how could I solve such a problem?
P.S I am currently on Wpf C# but I am open to use C# or C++ for any task. Thanks
推荐答案
What you're after is a path finding application. There are several ways to approach this, but one of the simpler ways is to:
Pick a starting point, add to list While True: For each border_pt bordering last point on list: Count number of points bordering border_pt If count > best_count: Mark border_pt as best if border_pt is empty: break Add border_pt to list
Here's some C# code that does just that, it generates a simple list based on your cloud:
using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApplication1 { class ExampleProgram : Form { const int GridWidth = 24; const int GridHeight = 15; List<Point> m_points = new List<Point>(); List<Point> m_trail = new List<Point>(); [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new ExampleProgram()); } ExampleProgram() { // Simple little tool to add a bunch of points AddPoints( 0, 4, 1, 3, 1, 4, 1, 5, 2, 4, 2, 5, 2, 6, 3, 4, 3, 5, 4, 5, 4, 6, 5, 5, 6, 5, 6, 4, 5, 4, 7, 4, 7, 3, 8, 3, 8, 4, 8, 5, 8, 6, 9, 6, 9, 5, 9, 4, 9, 3, 10, 2, 10, 3, 10, 4, 10, 5, 10, 6, 11, 5, 11, 4, 11, 3, 11, 2, 12, 4, 12, 5, 13, 5, 13, 6, 13, 8, 14, 8, 14, 7, 14, 6, 15, 7, 15, 8, 15, 9, 14, 9, 14, 10, 13, 10, 12, 10, 11, 10, 13, 11, 14, 11, 15, 11, 15, 12, 16, 12, 17, 12, 18, 12, 19, 12, 18, 11, 17, 11, 17, 10, 18, 10, 19, 10, 19, 9, 19, 8, 20, 8, 21, 8, 18, 7, 19, 7, 20, 7, 21, 7, 21, 6, 22, 6, 23, 6, 21, 5, 20, 5, 19, 5, 19, 4, 18, 4, 17, 4, 20, 3, 21, 3, 22, 3, 20, 2, 19, 2, 18, 2, 19, 1, 20, 1, 21, 1, 19, 0, 18, 0, 10, 0, 4, 1); // Very basic form logic ClientSize = new System.Drawing.Size(GridWidth * 20, GridHeight * 20); DoubleBuffered = true; Paint += ExampleProgram_Paint; // Add a new point to the form (commented out) // MouseUp += ExampleProgram_MouseUp_AddPoint; // Draw the trail we find MouseUp += ExampleProgram_MouseUp_AddTrail; // Pick a starting point to start finding the trail from // TODO: Left as an excersize for the reader to decide how to pick // the starting point programatically m_trail.Add(new Point(0, 4)); } IEnumerable<Point> Border(Point pt) { // Return all points that border a give point if (pt.X > 0) { if (pt.Y > 0) { yield return new Point(pt.X - 1, pt.Y - 1); } yield return new Point(pt.X - 1, pt.Y); if (pt.Y < GridHeight - 1) { yield return new Point(pt.X - 1, pt.Y + 1); } } if (pt.Y > 0) { yield return new Point(pt.X, pt.Y - 1); } if (pt.Y < GridHeight - 1) { yield return new Point(pt.X, pt.Y + 1); } if (pt.X < GridWidth - 1) { if (pt.Y > 0) { yield return new Point(pt.X + 1, pt.Y - 1); } yield return new Point(pt.X + 1, pt.Y); if (pt.Y < GridHeight - 1) { yield return new Point(pt.X + 1, pt.Y + 1); } } } void AddPoints(params int[] points) { // Helper to add a bunch of points to our list of points for (int i = 0; i < points.Length; i += 2) { m_points.Add(new Point(points[i], points[i + 1])); } } void ExampleProgram_MouseUp_AddTrail(object sender, MouseEventArgs e) { // Calculate the trail while (true) { // Find the best point for the next point int bestCount = 0; Point best = new Point(); // At the current end point, test all the points around it foreach (var pt in Border(m_trail[m_trail.Count - 1])) { // And for each point, see how many points this point borders int count = 0; if (m_points.Contains(pt) && !m_trail.Contains(pt)) { foreach (var test in Border(pt)) { if (m_points.Contains(test)) { if (m_trail.Contains(test)) { // This is a point both in the original cloud, and the current // trail, so give it a negative weight count--; } else { // We haven't visited this point, so give it a positive weight count++; } } } } if (count > bestCount) { // This point looks better than anything we've found, so // it's the best one so far bestCount = count; best = pt; } } if (bestCount <= 0) { // We either didn't find anything, or what we did find was bad, so // break out of the loop, we're done break; } m_trail.Add(best); } Invalidate(); } void ExampleProgram_MouseUp_AddPoint(object sender, MouseEventArgs e) { // Just add the point, and dump it out int x = (int)Math.Round((((double)e.X) - 10.0) / 20.0, 0); int y = (int)Math.Round((((double)e.Y) - 10.0) / 20.0, 0); m_points.Add(new Point(x, y)); Debug.WriteLine("m_points.Add(new Point(" + x + ", " + y + "));"); Invalidate(); } void ExampleProgram_Paint(object sender, PaintEventArgs e) { // Simple drawing, just draw a grid, and the points e.Graphics.Clear(Color.White); for (int x = 0; x < GridWidth; x++) { e.Graphics.DrawLine(Pens.Black, x * 20 + 10, 0, x * 20 + 10, ClientSize.Height); } for (int y = 0; y < GridHeight; y++) { e.Graphics.DrawLine(Pens.Black, 0, y * 20 + 10, ClientSize.Width, y * 20 + 10); } foreach (var pt in m_points) { e.Graphics.FillEllipse(Brushes.Black, (pt.X * 20 + 10) - 5, (pt.Y * 20 + 10) - 5, 10, 10); } foreach (var pt in m_trail) { e.Graphics.FillEllipse(Brushes.Red, (pt.X * 20 + 10) - 6, (pt.Y * 20 + 10) - 6, 12, 12); } } } }
其他推荐答案
You are looking for an operation called thinning or skeletonization, possibly followed by some post-processing to remove small components. There are different algorithms for this that offer different properties. For example Guo and Hall's and Zhang and Suen's.
其他推荐答案
You might want to consider treating your coordinates as a binary image and apply some Morphological techniques to the image.
Thinning might give you good results, but processing like this can be tricky to get working well in a wide range of cases.