【问题标题】:How to resize / rescale a SVG graphic in an iPython / Jupyter Notebook?如何在 iPython / Jupyter Notebook 中调整 SVG 图形的大小?
【发布时间】:2018-12-29 08:35:10
【问题描述】:

我有一个大型 SVG(.svg 图形)对象要显示在 iPython / Jupyter Notebook 中。事实上,我有一个用 Keras 创建的大型神经网络模型图形来显示。

from IPython.display import SVG
from keras.utils.vis_utils import model_to_dot

SVG(model_to_dot(model,show_shapes=True).create(prog='dot', format='svg'))

所以,我想调整/重新缩放/缩小 SVG 图形以适合我的笔记本页面(尤其是水平方向,因为页面宽度是有限的)。

【问题讨论】:

    标签: python svg keras jupyter-notebook


    【解决方案1】:

    另一种选择是使用“dpi”(每英寸点数)属性。有点hacky,但这让我可以缩小我的SVG。 Tensorflow: model_to_doc

        from IPython.display import SVG
        from keras.utils import model_to_dot
    
        SVG(model_to_dot(model, show_shapes= True, show_layer_names=True, dpi=65).create(prog='dot', format='svg'))
    

    【讨论】:

    • 非常好!当允许 dpi 时,我的解决方案太复杂了。谢谢
    【解决方案2】:

    使用 spaCy 时特别有用的新改进解决方案(在 2.2.4 版本中测试)。为了能够在不裁剪的情况下缩放 .svg,我们必须在 XML / HTML svg 表示中添加viewBox

    缩放前:

    import spacy
    import re
    from spacy import displacy
    
    nlp_model = spacy.load("en_core_web_sm")
    doc = nlp_model(u"To be or not to be, that is the question")
    svg = displacy.render(doc,  style='dep', page=True, jupyter=False)
    
    def add_viewbox_svg(svg):
        regex = r'class="displacy" width="([\d\.]*)" height="([\d\.]*)'
        match_results = re.findall(regex,svg)
        new_svg = svg.replace("<svg ","<svg viewBox='0 0 "+
                              match_results[0][0]+" "+
                              match_results[0][1]+
                              "' preserveAspectRatio='none' ")
        return new_svg
    
    new_svg = add_viewbox_svg(svg)
    

    然后使用样式:

    style = "<style>svg{width:100% !important;height:100% !important;</style>"
    display(HTML(style))
    display(HTML(new_svg))
    

    缩放后:

    【讨论】:

    • 我从中得到的只是裁剪的 SVG
    【解决方案3】:

    这对我有用:

    from IPython.display import SVG, display, HTML
    import base64
    _html_template='<img width="{}" src="data:image/svg+xml;base64,{}" >'
    
    def svg_to_fixed_width_html_image(svg, width="100%"):
        text = _html_template.format(width, base64.b64encode(svg))
        return HTML(text)
    
    svg_to_fixed_width_html_image(svg)
    

    【讨论】:

      【解决方案4】:

      以上基于 CSS 的解决方法似乎对我不起作用,因为 width= 和 height= 都直接设置在生成的 SVG 元素的属性中。

      作为额外的解决方法,我得到了以下解决方法:

      iv1_dot = model_to_dot(iv1_model, show_shapes=False, show_layer_names=False, rankdir='LR')
      iv1_dot.set_size('48x8')
      SVG(iv1_dot.create(prog=['dot'], format='svg'))
      

      这允许我以英寸为单位指定 graphviz 绘图的大小(在上述情况下为 48x8)。

      【讨论】:

        【解决方案5】:

        上面和下面的答案非常好,但取决于系统。根据您的浏览器插件、Jupyter 版本、Colab 环境等,它们可能会或可能不会总是对您有用。通常,SVG() 将点图像转换为 SVG 文件,但通过自定义关联来调整其大小很棘手HTML。我建议使用这个:

        from keras.utils import plot_model
        plot_model(model, to_file='model.png')
        

        然后可以使用上面answer by user48956中的sn-p来调整生成的图片大小。但大多数时候,它会自行扩展。

        进一步参考:Here

        【讨论】:

          【解决方案6】:

          其他解决方案都对我的用例有一些问题。因此,我提出了这个解决方案,它直接使用BeautifulSoup 操作 svg 数据:

          from IPython.display import SVG
          from bs4 import BeautifulSoup
          import re
          
          
          def scale_svg(svg_object, scale=1.0):
          
              soup = BeautifulSoup(svg_object.data, 'lxml')
              svg_elt = soup.find("svg")
              w = svg_elt.attrs["width"].rstrip("pt")
              h = svg_elt.attrs["height"].rstrip("pt")
          
              ws = float(w)*scale
              hs = float(h)*scale
          
              svg_elt.attrs["width"] = f"{ws}pt"
              svg_elt.attrs["height"] = f"{hs}pt"
              svg_elt.attrs["viewbox"] = f"0.00 0.00 {ws} {hs}"
          
              g_elt = svg_elt.find("g")
              tf = g_elt.attrs["transform"]
              # non-greedy regex-search-and-replace
              tf2 = re.sub(
                  "scale\(.*?\)",
                  f"scale({scale} {scale})",
                  tf
              )
              g_elt.attrs["transform"] = tf2
          
              svg_object.data = str(svg_elt)
              
              return svg_object
          
          s1 = SVG("""
          <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="103.0pt" viewbox="0.00 0.00 170.0 103.0" width="170.0pt">
          <g class="graph" id="graph0" transform="scale(1.0 1.0) rotate(0) translate(4 199)">
          <title>G</title>
          <polygon fill="#ffffff" points="-4,4 -4,-199 166,-199 166,4 -4,4" stroke="transparent"/>
          <!-- node0000 -->
          <g class="node" id="node1">
          <title>node0000</title>
          <ellipse cx="81" cy="-159" fill="none" rx="36" ry="36" stroke="#000000"/>
          <text fill="#000000" font-family="Times,serif" font-size="10.00" text-anchor="middle" x="81" y="-156.5">ABCDEFGH</text>
          </g>
          </g>
          </svg>
          """)
          
          scale_svg(s1, 3.2)
          

          【讨论】:

            猜你喜欢
            • 2018-04-25
            • 1970-01-01
            • 2016-02-22
            • 1970-01-01
            • 2014-01-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-11-11
            相关资源
            最近更新 更多