gpt4 book ai didi

python - 点文件的“锯齿状”输出

转载 作者:行者123 更新时间:2023-12-01 01:14:51 25 4
gpt4 key购买 nike

我一直在尝试将 sklearn 决策树中的 .dot 图插入到 pyplot 子图中,并且一直在努力做到这一点。 pygraphviz 库拒绝在我的 Windows 系统上工作,因此我使用以下方法插入图像:

from subprocess import check_call
from PIL import Image
import matplotlib.pyplot as plt

gridSpec = fig.add_gridspec(3, 2)
treeSubPlot = plt.subplot(gridSpec.new_subplotspec((2, 1)))
treeSubPlot.tick_params(axis = "both", which = "both", bottom = False, top = False, labelbottom = False, right = False, left = False, labelleft = False)
treeSubPlot.set_xlabel("Final model")

# Obtain the size of a single plot in inches to inform the dot picture creator.
height = treeSubPlot.get_window_extent().y1 - treeSubPlot.get_window_extent().y0
width = treeSubPlot.get_window_extent().x1 - treeSubPlot.get_window_extent().x0

check_call(['dot','-Tpng', "-Gsize=" + str(width/100) + "," + str(height/100) + "!", "-Gdpi=100", "-Gratio=fill", 'random_tree.dot','-o','random.png'])
randImg = Image.open("random.png")
treeSubplot.imshow(randImg, aspect = "auto")

使用 .dot 文件:

digraph Tree {
node [shape=box] ;
0 [label="B field <= 332.72\nsamples = 19\nvalue = 0.41"] ;
1 [label="samples = 11\nvalue = 0.67"] ;
0 -> 1 [labeldistance=2.5, labelangle=45, headlabel="True"] ;
2 [label="B field <= 576.73\nsamples = 8\nvalue = 0.04"] ;
0 -> 2 [labeldistance=2.5, labelangle=-45, headlabel="False"] ;
3 [label="samples = 4\nvalue = 0.05"] ;
2 -> 3 ;
4 [label="samples = 4\nvalue = 0.03"] ;
2 -> 4 ;
}

结果是情节,但由于缺乏更好的术语,它看起来非常“锯齿状”: Resulting subplot

我可以使用任何设置来阻止这种情况吗?我试图使图像完美地适合子图,但它仍然是锯齿状的。

最佳答案

有几个问题。

  • dot 生成的图像实际上并不是您在 -Gsize={},{}! 参数中指定的确切尺寸。
  • 存在舍入误差,因为 matplotlib 轴位于相对图形坐标中,而后者与像素的整数位置不精确匹配。
  • 最后,显示图像的轴非常小,因此上述效果变得更加明显。

我们可以想到的一种解决方案是找到轴的大致大小,调用 dot 程序并从中检索图像。然后根据实际图像大小设置轴的实际大小(与原始位置相比,这可能会将轴移动几个像素)。在下面的代码中,我采用了更大的轴。另请注意,较高的 dpi 或图形尺寸会增加可读性。

import numpy as np
from subprocess import check_call
from PIL import Image
import matplotlib.pyplot as plt
import matplotlib.transforms as mtrans

dpi = 100
fig = plt.figure(dpi=dpi)
gridSpec = fig.add_gridspec(3, 2)
ax = plt.subplot(gridSpec.new_subplotspec((2, 1)))
#ax = fig.add_subplot(111)

ax.tick_params(axis = "both", which = "both", bottom = False, top = False,
labelbottom = False, right = False, left = False, labelleft = False)
ax.set_xlabel("Final model")

# calculate nominal size supplied to `dot`
ext = ax.get_position().transformed(fig.transFigure).extents
bbox = mtrans.Bbox.from_extents(np.array(ext).astype(int))

height = bbox.height
width = bbox.width

# get image from dot
check_call(['dot','-Tpng', "-Gsize={},{}!".format(width/100, height/100),
"-Gdpi={}".format(100), "-Gratio=fill", 'random_tree.dot','-o','random.png'])
randImg = np.array(Image.open("random.png"))

# get ACTUAL size from produced image
aheight, awidth, _ = randImg.shape

# create new bounding box from actual size
abbox = mtrans.Bbox.from_bounds(bbox.x0, bbox.y0, awidth, aheight)
# transform bbox to figure coordintes
abboxf = bbox.transformed(fig.transFigure.inverted())
# Use the thus created bbox to modify the position of the axes
ax.set_position(abboxf)

# finally plot the data
ax.imshow(randImg, aspect = "auto")
# save image (this should now be correct)
plt.savefig("randomdot_mpl.png")
# show image (this might still be slightly wrong,
# if the GUI changes the figure size on the fly.)
plt.show()

enter image description here

正如你所看到的,结果仍然不完美(例如“values”中的 l 稍微粗一些)。一般来说,更好的解决方案可能是根本不将图像放置在轴内,而是使用 figimage ,这是放置在图形内部的未重新采样的图像。如果您仍然想显示其周围的轴,则需要使轴透明以“透明”。

这将通过以下代码完成

import numpy as np
from subprocess import check_call
from PIL import Image
import matplotlib.pyplot as plt
import matplotlib.transforms as mtrans

dpi = 100
fig = plt.figure(dpi=dpi)
#gridSpec = fig.add_gridspec(3, 2)
#ax = plt.subplot(gridSpec.new_subplotspec((2, 1)))
ax = fig.add_subplot(111)

ax.tick_params(axis = "both", which = "both", bottom = False, top = False,
labelbottom = False, right = False, left = False, labelleft = False)
ax.patch.set_visible(False)
ax.set_xlabel("Final model")

# calculate nominal size supplied to `dot`
ext = ax.get_position().transformed(fig.transFigure).extents
bbox = mtrans.Bbox.from_extents(np.array(ext).astype(int))

height = bbox.height
width = bbox.width

# get image from dot
check_call(['dot','-Tpng', "-Gsize={},{}!".format(width/100, height/100),
"-Gdpi={}".format(100), "-Gratio=fill", 'random_tree.dot','-o','random.png'])
randImg = np.array(Image.open("random.png"))

# produce a figimage, i.e. a non-resampled image
fig.figimage(randImg, xo=bbox.x0, yo=bbox.y0)

# save image (this should now be perfect)
plt.savefig("randomdot_mpl.png")
# show image (this should now be perfect)
plt.show()

enter image description here

关于python - 点文件的“锯齿状”输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54451011/

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