gpt4 book ai didi

python - 如何将 SVG 折线转换为 quickdraw stroke-3 numpy 格式?

转载 作者:行者123 更新时间:2023-12-04 08:10:40 26 4
gpt4 key购买 nike

我想将包含折线的基本 SVG 文件转换为 sketch-rnn 使用的stroke-3 格式(和 quickdraw dataset )。
据我了解,stroke-3 格式的每个折线点将是:

  • 存储为 [delta_x, delta_y, pen_up] , 其中
  • delta_x , delta_y表示相对于坐标
    前一点和
  • pen_up当笔抬起时有点为 1
    (例如 move_to 操作 a-la 海龟图形)或 0 当笔处于
    向下(例如 line_to 操作 a-la 海龟图形)。

  • 我尝试编写函数并转换 SVG,但是当我渲染笔划 3 格式的测试时,我得到了额外的一行。
    我的输入 SVG 如下所示:
    box svg

    <?xml version="1.0" encoding="UTF-8"?><svg viewBox="0 0 900 900" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#00c000" stroke-linecap="round"><path d="m324.56 326.77h62.721 62.721 62.721 62.721"/><path d="m575.44 326.77 0.1772 62.891 0.1771 62.891 0.1772 62.891 0.1771 62.891"/><path d="m576.15 578.33h-63.075-63.075l-63.075-1e-4h-63.075"/><path d="m323.85 578.33 0.1772-62.891 0.1772-62.891 0.1772-62.891 0.1771-62.891"/><path d="m575.44 326.77 29.765-32.469 29.765-32.469" stroke="#c00000"/><path d="m634.97 261.83h-92.486-92.486l-92.486-1e-4h-92.486" stroke="#c00000"/><path d="m265.03 261.83 44.647 48.704 14.882 16.235" stroke="#c00000"/><path d="m323.85 578.33-15.092 13.725-30.183 27.45-15.092 13.725" stroke="#c0c000"/><path d="m263.48 633.23h93.258 93.258l93.258 1e-4h93.258" stroke="#c0c000"/><path d="m636.52 633.23-60.366-54.9" stroke="#c0c000"/><path d="m634.97 261.83 0.3863 92.851 0.3862 92.851 0.3863 92.851 0.3863 92.851" stroke="#0000c0"/><path d="m636.52 633.23h-93.258l-93.258-1e-4h-93.258-93.258" stroke="#0000c0"/><path d="m263.48 633.23 0.3863-92.851 0.3863-92.851 0.3863-92.851 0.3862-92.851" stroke="#0000c0"/></g></svg>

    这是一个可视化效果,其中从 SVG 文件解析的线条呈现为浓绿色,而从转换后的 stroke-3 格式绘制的线条呈现为较细的红色:
    box line and strokes
    请注意右侧面上的对角线,它不存在于原始 SVG 中。
    我一定是在某处标记行操作而不是移动操作时做错了什么,但我一直盯着代码看太久了,我无法发现错误。
    这是一个最小的例子,展示了我使用 svg.path 的尝试:
    import xml.etree.ElementTree as ET
    import numpy as np
    from svg.path import parse_path
    from svg.path.path import Line, Move

    cubeSVG = '<?xml version="1.0" encoding="UTF-8"?><svg viewBox="0 0 900 900" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#00c000" stroke-linecap="round"><path d="m324.56 326.77h62.721 62.721 62.721 62.721"/><path d="m575.44 326.77 0.1772 62.891 0.1771 62.891 0.1772 62.891 0.1771 62.891"/><path d="m576.15 578.33h-63.075-63.075l-63.075-1e-4h-63.075"/><path d="m323.85 578.33 0.1772-62.891 0.1772-62.891 0.1772-62.891 0.1771-62.891"/><path d="m575.44 326.77 29.765-32.469 29.765-32.469" stroke="#c00000"/><path d="m634.97 261.83h-92.486-92.486l-92.486-1e-4h-92.486" stroke="#c00000"/><path d="m265.03 261.83 44.647 48.704 14.882 16.235" stroke="#c00000"/><path d="m323.85 578.33-15.092 13.725-30.183 27.45-15.092 13.725" stroke="#c0c000"/><path d="m263.48 633.23h93.258 93.258l93.258 1e-4h93.258" stroke="#c0c000"/><path d="m636.52 633.23-60.366-54.9" stroke="#c0c000"/><path d="m634.97 261.83 0.3863 92.851 0.3862 92.851 0.3863 92.851 0.3863 92.851" stroke="#0000c0"/><path d="m636.52 633.23h-93.258l-93.258-1e-4h-93.258-93.258" stroke="#0000c0"/><path d="m263.48 633.23 0.3863-92.851 0.3863-92.851 0.3863-92.851 0.3862-92.851" stroke="#0000c0"/></g></svg>'

    def svg_to_stroke3(svg_string):
    # parse the doc
    doc = ET.fromstring(svg_string)
    # get paths
    paths = doc.findall('.//{http://www.w3.org/2000/svg}path')

    strokes = []
    # previous x, y
    px, py = 0, 0

    for path_index, path in enumerate(paths):
    stroke = parse_path(path.attrib['d'])
    was_moving = False
    for operation_index, operation in enumerate(stroke):
    if isinstance(operation, Move):
    mx = int(operation.start.real)
    my = int(operation.start.imag)
    # prep this end point for check as next line first point
    was_moving = True

    strokes.append([mx-px, my-py, 1])
    # update previous (absolute) coordinates
    px = mx
    py = my

    if isinstance(operation, Line):
    sx = int(operation.start.real)
    sy = int(operation.start.imag)
    ex = int(operation.end.real)
    ey = int(operation.end.imag)
    if was_moving:
    # append delta x, y relative to previous move operation
    strokes.append([sx-px, sy-py, 0])
    was_moving = False
    # append delta x,y (line end relative to line start)
    strokes.append([ex-sx, ey-sy, 0])
    # update previous (absolute) coordinates
    px = ex
    py = ey

    # update previous end point

    strokes_np = np.array(strokes, dtype=np.int16)
    return strokes_np

    print(svg_to_stroke3(cubeSVG))
    此外,我已将上述内容作为易于运行的工具提供 Google Colab Notebook .

    最佳答案

    您的转换是正确的,错误在渲染代码中。必须是 is_down = data[i][2] == 0而不是 is_down = data[i-1][2] == 0draw_stroke3 .
    enter image description here
    此错误没有出现在其他路径中,但在两种情况下,新路径从前一条路径的末尾开始。在您真正移动到新起点的另一种情况下,附加线与已绘制的线重合。

    更新和更正:
    我注意到我误解了上笔位的含义:实际上它表明在绘制当前笔画后要提起笔,而不是像我一开始那样为当前笔画。因此,您的渲染代码似乎没问题,并且错误出在 stroke3 文件生成中。
    我想您可以通过记录每个操作的终点以及当前操作的操作代码(1 = 移动,0 = 绘制)来简单得多。转换为 numpy 数组后,我们可以通过前两列的差值轻松地将这些绝对位置转换为相对位移,然后将带有操作码的第三列向后移动一个位置:

    def svg_to_stroke3(svg_string):
    doc = ET.fromstring(svg_string)
    paths = doc.findall('.//{http://www.w3.org/2000/svg}path')
    strokes = [[0,0,0]]
    for path in paths:
    stroke = parse_path(path.attrib['d'])
    for op in stroke:
    if isinstance(op, Move):
    strokes.append([op.start.real, op.start.imag, 1])
    if isinstance(op, Line):
    strokes.append([op.end.real, op.end.imag, 0])
    strokes_np = np.array(strokes, dtype=np.int16)
    # convert x,y columns to relative displacements
    strokes_np[1:,:2] -= strokes_np[:-1,:2]
    # shift back op codes
    strokes_np[:-1,2] = strokes_np[1:,2]
    # remove [0,0,0]s and set previous op to 0
    m = (strokes_np == 0).all(1)
    strokes_np[np.argwhere(m)-1,2] = 0
    return strokes_np[~m]
    这提供了一个相当紧凑的表示(示例立方体为 49 行)并使用您的原始代码和 David Ha 的 draw_strokes() 正确呈现。 (如果按照惯例,您可以像 draw_strokes() 那样将笔向上举起,则可以不用我添加的第一行)。

    关于python - 如何将 SVG 折线转换为 quickdraw stroke-3 numpy 格式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65985435/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com