【发布时间】:2019-05-27 17:19:34
【问题描述】:
我正在尝试在 python 库 matplotlib 显示的图像网格顶部精确覆盖 1 像素宽的线网格。
不幸的是,我似乎无法对结果进行足够精细的控制,以实现线网格与数据网格的正确对齐,如下面的代码所示。结果似乎总是很接近,但并不完全正确。
我尝试过同时使用imshow 和pcolormesh 函数,但都遇到了问题。
imshow 方法:
import matplotlib.pyplot as plt
import numpy as np
size = 60
border = 5
#create test data for image and ticks location
im = np.zeros(shape=(size,size),dtype=np.float32)
ticks = np.arange(size)+0.5
#create test checkerboard pattern outside of border area
for index in range(size-2*border):
im[border+index,border:-border] += index % 2
for index in range(size-2*border):
im[border:-border,index+border] -= index % 2
im = np.abs(im)
#display image with imshow
plt.imshow(im, interpolation='nearest', cmap='binary', vmin=0, vmax=1)
ax = plt.gca()
ax.set_xticks(ticks)
ax.set_xticklabels([])
ax.set_yticks(ticks)
ax.set_yticklabels([])
ax.grid(color='r', linestyle='-', linewidth=1)
#sometimes line is off by 1 pixel
plt.show()
我希望红线的线网格准确地覆盖数据网格的棋盘格图案,但它们相差一个像素。
此缩放图像显示了结果,并且偏移量很容易看到:
我也尝试过使用 pcolormesh 和 edgecolor(使用与上面相同的数据):
plt.pcolormesh(im, cmap='binary', vmin=0, vmax=1, edgecolors='r', linewidth=0.005)
plt.show()
这里的红线网格对齐更好,但线宽不一致,有时是 1 像素宽,有时是 2 像素宽,如下图所示:
在这里,理想情况下,我希望始终获得 1 像素宽的线条。 可以使用 linewidth 参数,但是如果我将其设置得太小,那么线条开始具有 0 像素宽度并且它们完全消失,而且我不太了解 linewidth 的单位是什么。
总之,如果有任何关于如何在定位(红线网格不偏离黑白棋盘格)和线宽(在屏幕上总是正好 1 像素宽)方面实现一致性的建议,我将不胜感激。
【问题讨论】:
-
网格被捕捉到最近的像素,但如果一个与像素边界重叠,它有时会变得两倍宽。如果您真的想像这样戳像素,我可以建议 matplotlib 不是最好的工具吗? Pillow 将允许您将图像文件读取和写入到 numpy 数组中,并且您可以直接在那里更改 RGBA 值。当假设分辨率足够高,抗锯齿可以在屏幕或图形中做出令人愉悦的表示时,Matplotlib 的效果会更好。
-
Hallo @Jody ,用例是具有数千个芯片的晶圆图的交互式显示(也允许放大等功能),我们还显示其他内容,如值的直方图分布 - 因此matplotlib 解决方案将更加理想和简单(如果可能的话)。虽然问题仅在最缩小的级别可见,但您可以在此处看到整个晶圆,因此最有用。
-
我认为这两个在 GitHub 上都有问题。您可以在那里挖掘并发表评论。但基本上 imshow 和刻度/网格捕捉到最近的像素和 pcolormesh 使用抗锯齿。此外还有一些错误 w imshow 以及它如何从数据转换为图像像素。
-
github.com/matplotlib/matplotlib/issues/12934 描述了此问题,并且大多数其他类似问题都已链接。我已经不再担心这个问题了,因为我认为 matplotlib 很快就会转向使用 cairo 作为主要的光栅化后端,并且它已经解决了很多这些问题。
标签: python matplotlib