从 BMP 或 SVG (C#) 获取 Vertices/Edges

Get Vertices/Edges From BMP or SVG (C#)

我有一张 JPG、BMP 或 SVG 图像(请参见下面的示例),我需要一种算法来提取顶点 (X, Y) 坐标和 egdes(即指示哪些顶点相连的列表) .对于每个顶点对,边可以是布尔值 true/false 的形式,或者只是连接的顶点对列表。欢迎任何想法。

例如,我想要一个输入图像并输出两个列表的函数(或一系列函数):

顶点:

顶点 1:X = 1,Y = 2

顶点 2:X = 3,Y = 5

顶点 3:X = 3,Y = 7

...

:

边 1:(顶点 1,顶点 3)

边 2:(顶点 1,顶点 4)

边 3:(顶点 4,顶点 10)

...

顶点坐标系可以是任何坐标系(例如,基于 SVG 坐标的像素),也可以是其他用户定义的坐标系。

例如,我从示例图像(左)中提取了以下坐标(像素)并在 Matlab 中绘制了它们(右)。

所以,例如,我可以说角顶点大致是: (10, 10)、(290, 10)、(290, 190) 和 (10, 190)。

但我想要一个算法来自动检测这些坐标,并告诉我左上角顶点 (10, 190) 和右上角顶点 (290, 190) 之间有一条边,等等。我也需要识别内部块等的每个顶点和边

此外,对于更复杂的图表,我也需要它才能正常工作。例如,我能够提取必要的像素并生成以下 Matlab 图:

和之前一样,很清楚顶点在哪里"should be",但是由于线条粗细,有很多簇像素首先需要"smoothed out",等等我我不确定如何着手执行此操作并使识别过程自动化 vertices/edges。

注1:我使用的获取像素坐标的方法基本上是:

我想的粗略算法是:

上面的算法有很多问题,所以我希望其他人能有更好的想法或类似的C#代码等

我希望流程尽可能自动化。

注2:我也可以把图片转成SVG格式(已经实现)。据我了解,SVG 格式可能非常适合我的应用程序,因为它可以更轻松地使流程自动化;但是,我发现 SVG 结构非常混乱。

我已经阅读了一些关于 SVG 格式的在线文献并且我了解它是如何工作的,但我想知道是否有某种已经存在的库或者可以让我很容易地识别 "path" 在 SVG 文件等中

例如,我从一个 SVG 文件中获得的 "paths" 之一是以下形式:

<path d="M70 1810 c0 -91 3 -110 15 -110 12 0 15 17 15 95 l0 95 1405 
0 1405 0 0 -410 0 -411 -87 3 -88 3 -1 35 c0 19 -1 124 -2 233 l-2 197 
-70 0 -70 0 0 -320 0 -320 153 0 c83 0 162 3 175 6 l22 6 0 504 0 504 
-1435 0 -1435 0 0 -110z m2647 -490 c1 -113 2 -217 2 -232 l1 -27 88 -3 
87 -3 0 -70 0 -70  145 0 -145 0 -3 295 c-1 162 0 301 3 308 3 9 21 12 
57 10 l53 -3 2 -205z"/>

我知道这遵循三次贝塞尔曲线,但我想知道是否有任何现有算法可以处理 "path" 代码并提取相关坐标等。

感谢您的帮助!!

SVG 路径解析并不难(除非你有复杂的 SVG,但看起来不是这样)

  1. 查找路径

    路径以 <path 标记开始,通常以 /> 结束,因此找到路径 start/end,然后仅使用其中的字符串。

  2. 找到d="

    那是路径字符串数据(所以你跳过格式化等......)这个结尾用"标记所以再次只使用里面的字符串

  3. 处理路径字符串

    1. 读取单个字符(跳过空格)
    2. 根据字符读取正确的数字计数并将实体添加到矢量表示 例如:

      • M 表示绝对移动所以 x,y 跟随 所以 cursor = (x,y);
      • m 表示相对移动 所以 x,y 跟随 所以 cursor+= (x,y);
      • L 表示绝对线 so x,y follows so add_line(cursor,(x,y)); cursor = (x,y);
      • l 表示相对线 so x,y follows so add_line(cursor,cursor+(x,y)); cursor += (x,y);
      • C 表示绝对 BEZIER 立方 所以 x1,y1,x2,y2,x3,y3 遵循 所以 add_cubic_BEZIER(cursor,(x1,y1),(x2,y2),(x3,y3)); cursor=(x3,y3)
      • 等...命令m,M,l,L,h,H,v,V,c,C,s,S,q,Q,t,T仅在点数和curve/line
      • 的类型上有所不同
      • z 的意思就是你从末尾的 cursor 到起点
      • 添加一行
    3. 如果下一个字符串以数字开头,则将其作为最后一个命令处理并转到 #2

    4. 转到#1

就是这样。所以你所需要的只是简单的字符串解析,能够读取 mantissa/exponent 形式的数字,如 -125.547e-99 并跳过 spaces/tabs。您不需要只解码整个 SVG 路径。

因为每个 SVG 可以有很多路径,然后在首先解析后 <path 找到另一个解析它......直到没有人离开。有时 <path 包含变换矩阵甚至所有者 tag 通常 <g 所以可能会堆叠一些变换,但我认为没有这些东西你的导出很简单。