如何找到通过使用 matplotlib 绘制的图传递的像素
how to find the pixel passed by a plot drawn with matplotlib
我使用以下代码绘制一个函数:
t = np.arange(0., 5., 0.2)
plt.plot(t, (t**2)+10*np.sin(t))
plt.axis('off')
我想知道如何将绘图保存为 0/1 数组,如果绘图通过,像素值为 1,否则为 0。
一个后续问题是,如果我用一些线宽绘制绘图,我希望像素值只有在绘图的 "central" 线上时才为 1,否则为 0。如何我应该这样做吗?谢谢!
可以通过多种方式将图形转换为 RGBA 数组。
最简单的可能是将文件另存为 PNG,然后使用 plt.imread
或类似方式再次加载文件。如果这对你来说似乎是迂回的,你可以使用我在下面使用的 plot2img
,它获取 canvas 并通过作为字符串缓冲区的中间表示将其转换为数组。
之后,只需对图像进行阈值化并提取中轴,使用 scikit-image
提供的函数即可轻松完成。
#!/usr/bin/env python
"""
"""
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_agg import FigureCanvasAgg
from skimage.color import rgb2gray
from skimage.filters import threshold_otsu
from skimage.morphology import medial_axis
def plot2img(fig, remove_margins=True):
#
#
if remove_margins:
fig.subplots_adjust(left=0, bottom=0, right=1, top=1, wspace=0, hspace=0)
canvas = FigureCanvasAgg(fig)
canvas.draw()
img_as_string, (width, height) = canvas.print_to_buffer()
return np.fromstring(img_as_string, dtype='uint8').reshape((height, width, 4))
if __name__ == '__main__':
t = np.arange(0., 5., 0.2)
y = (t**2)+10*np.sin(t)
# plot in a large figure such that the resulting image has a high resolution
fig, ax = plt.subplots(figsize=(20, 20))
ax.plot(t, y)
ax.axis('off')
# convert figure to an RGBA array
as_rgba = plot2img(fig)
# close plot made with non-interactive Agg backend so that we can open the other later
plt.close('all')
# threshold the image
as_grayscale = rgb2gray(as_rgba)
threshold = threshold_otsu(as_grayscale)
as_bool = as_grayscale < threshold
# find midline
midline = medial_axis(as_bool)
# plot results
fig, (ax1, ax2) = plt.subplots(1, 2)
ax1.imshow(as_bool, cmap='gray_r')
ax2.imshow(midline, cmap='gray_r')
plt.show()
我使用以下代码绘制一个函数:
t = np.arange(0., 5., 0.2)
plt.plot(t, (t**2)+10*np.sin(t))
plt.axis('off')
我想知道如何将绘图保存为 0/1 数组,如果绘图通过,像素值为 1,否则为 0。
一个后续问题是,如果我用一些线宽绘制绘图,我希望像素值只有在绘图的 "central" 线上时才为 1,否则为 0。如何我应该这样做吗?谢谢!
可以通过多种方式将图形转换为 RGBA 数组。
最简单的可能是将文件另存为 PNG,然后使用 plt.imread
或类似方式再次加载文件。如果这对你来说似乎是迂回的,你可以使用我在下面使用的 plot2img
,它获取 canvas 并通过作为字符串缓冲区的中间表示将其转换为数组。
之后,只需对图像进行阈值化并提取中轴,使用 scikit-image
提供的函数即可轻松完成。
#!/usr/bin/env python
"""
"""
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_agg import FigureCanvasAgg
from skimage.color import rgb2gray
from skimage.filters import threshold_otsu
from skimage.morphology import medial_axis
def plot2img(fig, remove_margins=True):
#
#
if remove_margins:
fig.subplots_adjust(left=0, bottom=0, right=1, top=1, wspace=0, hspace=0)
canvas = FigureCanvasAgg(fig)
canvas.draw()
img_as_string, (width, height) = canvas.print_to_buffer()
return np.fromstring(img_as_string, dtype='uint8').reshape((height, width, 4))
if __name__ == '__main__':
t = np.arange(0., 5., 0.2)
y = (t**2)+10*np.sin(t)
# plot in a large figure such that the resulting image has a high resolution
fig, ax = plt.subplots(figsize=(20, 20))
ax.plot(t, y)
ax.axis('off')
# convert figure to an RGBA array
as_rgba = plot2img(fig)
# close plot made with non-interactive Agg backend so that we can open the other later
plt.close('all')
# threshold the image
as_grayscale = rgb2gray(as_rgba)
threshold = threshold_otsu(as_grayscale)
as_bool = as_grayscale < threshold
# find midline
midline = medial_axis(as_bool)
# plot results
fig, (ax1, ax2) = plt.subplots(1, 2)
ax1.imshow(as_bool, cmap='gray_r')
ax2.imshow(midline, cmap='gray_r')
plt.show()