如何获取Matplotlib生成的散点图的像素坐标?

时间:2012-12-01 18:44:13

标签: python matplotlib

我使用Matplotlib生成散点图的PNG文件。现在,对于每个散点图,除了PNG文件之外,我还还要生成散点图中各点的像素坐标列表。

我用来为散点图生成PNG文件的代码基本上是这样的:

from matplotlib.figure import Figure
from matplotlib.pyplot import setp
from matplotlib.backends.backend_agg import FigureCanvasAgg

...

fig = Figure(figsize=(3, 3), dpi=100)
ax = fig.gca()
for (x, y), m, c in zip(points, markers, colors):
    ax.scatter(x, y, marker=m, c=c, s=SIZE, vmin=VMIN, vmax=VMAX)

# several assorted tweaks like ax.spines['top'].set_color('none'), etc.

setp(fig, 'facecolor', 'none')

# FigureCanvasAgg(fig).print_png(FILEPATH)

...(其中UPPERCASE中的变量代表可设置的参数)。

如何在结果PNG中生成与(px, py)中的点对应的points对像素坐标列表?

[编辑:删除了关于imshow的一些废话。]

[编辑:

好的,这是我最终提出的,基于Joe Kington的建议。

# continued from above...

cnvs = FigureCanvasAgg(fig)
fig.set_canvas(cnvs)
_, ht = cnvs.get_width_height()
pcoords = [(int(round(t[0])), int(round(ht - t[1]))) for t in
           ax.transData.transform(points)]
fig.savefig(FILEPATH, dpi=fig.dpi)

得到的像素坐标(在pcoords中)非常接近正确的值。事实上,y coords是完全正确的。 x坐标是1或2像素关闭,这足以满足我的目的。

2 个答案:

答案 0 :(得分:12)

这样做非常简单,但要了解正在发生的事情,您需要阅读有关matplotlib变换的内容。 transformations tutorial是一个很好的起点。

无论如何,这是一个例子:

import numpy as np
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
points, = ax.plot(range(10), 'ro')
ax.axis([-1, 10, -1, 10])

# Get the x and y data and transform it into pixel coordinates
x, y = points.get_data()
xy_pixels = ax.transData.transform(np.vstack([x,y]).T)
xpix, ypix = xy_pixels.T

# In matplotlib, 0,0 is the lower left corner, whereas it's usually the upper 
# right for most image software, so we'll flip the y-coords...
width, height = fig.canvas.get_width_height()
ypix = height - ypix

print 'Coordinates of the points in pixel coordinates...'
for xp, yp in zip(xpix, ypix):
    print '{x:0.2f}\t{y:0.2f}'.format(x=xp, y=yp)

# We have to be sure to save the figure with it's current DPI
# (savfig overrides the DPI of the figure, by default)
fig.savefig('test.png', dpi=fig.dpi)

这会产生:

Coordinates of the points in pixel coordinates...
125.09  397.09
170.18  362.18
215.27  327.27
260.36  292.36
305.45  257.45
350.55  222.55
395.64  187.64
440.73  152.73
485.82  117.82
530.91  82.91

enter image description here

答案 1 :(得分:0)

尝试注释框:http://matplotlib.org/examples/pylab_examples/demo_annotation_box.html

import matplotlib.pyplot as plt
from matplotlib.offsetbox import TextArea, DrawingArea, OffsetImage, \
     AnnotationBbox

for (x, y), m, c in zip(points, markers, colors):
    ax.scatter(x, y, marker=m, c=c, s=SIZE, vmin=VMIN, vmax=VMAX)

    for px, py in zip(x,y):
        offsetbox = TextArea( " %s, %s" (px, py ) , minimumdescent=False)
        ab = AnnotationBbox(offsetbox,(px, py ),
                        xybox=(-20, 40),
                        xycoords='data',
                        boxcoords="offset points",
                        arrowprops=dict(arrowstyle="->"))
        ax.add_artist(ab)

我当前的计算机上没有安装matplotlib,因此我的代码可能无效。