将 svg 文件导入 matplotlib 图形
Importing an svg file into a matplotlib figure
我喜欢制作高质量的图,因此尽可能避免光栅化图形。
我正在尝试将 svg 文件导入到 matplotlib 图形中:
import matplotlib.pyplot as plt
earth = plt.imread('./gfx/earth.svg')
fig, ax = plt.subplots()
im = ax.imshow(earth)
plt.show()
这与 png 完美配合。有人可以告诉我如何使用 svg 或至少将我指向正确的文档。
我知道有人问过类似的问题(但没有回答):here。自那以后有什么变化吗?
P.S。我知道我可以导出一个高分辨率的 png 并达到类似的效果。这不是我要找的解决方案。
这是我要导入的图像:
SVG(Scalable Vector Graphics)是一种矢量格式,意思是图像不是由像素组成的,而是可以任意缩放的相对路径。
NumPy/Matplotlib,作为数值软件,只能真正处理像素图形,无法处理svg
。我建议首先将 svg
文件转换为例如png
文件,方法是在 Inkscape(免费)等软件中打开并保存该文件。然后,在Python.
中打开导出的png
或者,在 the picture's information page (click on the download button to the right of the picture) 上使用维基媒体提供的 png
格式的文件版本。
如果你真的认为你需要矢量形式,那么,没有办法做到这一点。您始终可以手动将 matplotlib 图叠加到图上(使用 matplotlib Artist 在图上绘制 canvas),或通过一些 pycairo
魔法,然后保存。但是 Matplotlib 不能直接处理 svg
内容。
也许您正在寻找的是 svgutils
import svgutils.compose as sc
from IPython.display import SVG # /!\ note the 'SVG' function also in svgutils.compose
import numpy as np
# drawing a random figure on top of your SVG
fig, ax = plt.subplots(1, figsize=(4,4))
ax.plot(np.sin(np.linspace(0,2.*np.pi)), np.cos(np.linspace(0,2.*np.pi)), 'k--', lw=2.)
ax.plot(np.random.randn(20)*.3, np.random.randn(20)*.3, 'ro', label='random sampling')
ax.legend()
ax2 = plt.axes([.2, .2, .2, .2])
ax2.bar([0,1], [70,30])
plt.xticks([0.5,1.5], ['water ', ' ground'])
plt.yticks([0,50])
plt.title('ratio (%)')
fig.savefig('cover.svg', transparent=True)
# here starts the assembling using svgutils
sc.Figure("8cm", "8cm",
sc.Panel(sc.SVG("./Worldmap_northern.svg").scale(0.405).move(36,29)),
sc.Panel(sc.SVG("cover.svg"))
).save("compose.svg")
SVG('compose.svg')
输出:
致 2021 年来到这里的任何人...
我建议看一下 cairosvg
包
(conda install -c conda-forge cairosvg
)
import cairosvg
import matplotlib.pyplot as plt
from PIL import Image
from io import BytesIO
img = cairosvg.svg2png("... the content of the svg file ...")
img = Image.open(BytesIO(img_png))
plt.imshow(img)
我喜欢制作高质量的图,因此尽可能避免光栅化图形。
我正在尝试将 svg 文件导入到 matplotlib 图形中:
import matplotlib.pyplot as plt
earth = plt.imread('./gfx/earth.svg')
fig, ax = plt.subplots()
im = ax.imshow(earth)
plt.show()
这与 png 完美配合。有人可以告诉我如何使用 svg 或至少将我指向正确的文档。
我知道有人问过类似的问题(但没有回答):here。自那以后有什么变化吗?
P.S。我知道我可以导出一个高分辨率的 png 并达到类似的效果。这不是我要找的解决方案。
这是我要导入的图像:
SVG(Scalable Vector Graphics)是一种矢量格式,意思是图像不是由像素组成的,而是可以任意缩放的相对路径。
NumPy/Matplotlib,作为数值软件,只能真正处理像素图形,无法处理svg
。我建议首先将 svg
文件转换为例如png
文件,方法是在 Inkscape(免费)等软件中打开并保存该文件。然后,在Python.
png
或者,在 the picture's information page (click on the download button to the right of the picture) 上使用维基媒体提供的 png
格式的文件版本。
如果你真的认为你需要矢量形式,那么,没有办法做到这一点。您始终可以手动将 matplotlib 图叠加到图上(使用 matplotlib Artist 在图上绘制 canvas),或通过一些 pycairo
魔法,然后保存。但是 Matplotlib 不能直接处理 svg
内容。
也许您正在寻找的是 svgutils
import svgutils.compose as sc
from IPython.display import SVG # /!\ note the 'SVG' function also in svgutils.compose
import numpy as np
# drawing a random figure on top of your SVG
fig, ax = plt.subplots(1, figsize=(4,4))
ax.plot(np.sin(np.linspace(0,2.*np.pi)), np.cos(np.linspace(0,2.*np.pi)), 'k--', lw=2.)
ax.plot(np.random.randn(20)*.3, np.random.randn(20)*.3, 'ro', label='random sampling')
ax.legend()
ax2 = plt.axes([.2, .2, .2, .2])
ax2.bar([0,1], [70,30])
plt.xticks([0.5,1.5], ['water ', ' ground'])
plt.yticks([0,50])
plt.title('ratio (%)')
fig.savefig('cover.svg', transparent=True)
# here starts the assembling using svgutils
sc.Figure("8cm", "8cm",
sc.Panel(sc.SVG("./Worldmap_northern.svg").scale(0.405).move(36,29)),
sc.Panel(sc.SVG("cover.svg"))
).save("compose.svg")
SVG('compose.svg')
输出:
致 2021 年来到这里的任何人...
我建议看一下 cairosvg
包
(conda install -c conda-forge cairosvg
)
import cairosvg
import matplotlib.pyplot as plt
from PIL import Image
from io import BytesIO
img = cairosvg.svg2png("... the content of the svg file ...")
img = Image.open(BytesIO(img_png))
plt.imshow(img)