Bbox是一个描述矩形区域的对象,BboxImage则是在Bbox中描绘图像的对象。下面是一个简单的例子:
import pylab as plfrom matplotlib.image import BboxImagefrom matplotlib.transforms import Bboxball_img = pl.imread("blue_ball.png") ?ax = pl.subplot(111)bbox = Bbox.from_bounds(250, 200, 100, 150) ?bboximg = BboxImage(bbox, data=ball_img) ?ax.add_artist(bboximg) ?pl.show()
调用pylab.imread()载入图像,得到的是一个形状为(图像高, 图像宽, 4)的三维数组,其中4为图像的通道数。?调用Bbox类的静态方法from_bounds()创建一个左下角坐标为(250,200)、宽100,高150的Bbox对象。?通过矩形区域bbox和图像数组ball_img创建一个BboxImage对象。?并通过add_artist()将BboxImage对象添加进子图对象的artist列表。下图是程序的输出结果:
请调整图表的大小,观察图像的位置变化。可以看出图像相对于窗口左下角的位置始终保持不变。因此可知Bbox对象所指定的矩形区域是相对于窗口坐标系的。在窗口坐标系中,窗口的左下角为坐标原点,X轴的正方向为右方,Y轴的正方向为上方,坐标值以像素为单位。
为了在数据坐标系定位图像的中心,我们需要编写一个BboxBase的派生类,完成坐标系转换工作:
from matplotlib.transforms import BboxBaseclass CenterPointBBox(BboxBase): def __init__(self, x, y, transform, width, height): self.center_x = x self.center_y = y self.image_width = width self.image_height = height self._transform = transform def get_points(self): x, y = self._transform.transform((self.center_x, self.center_y)) ? w = self.image_width // 2 h = self.image_height //2 points = np.array([[x-w, y-h],[x-w+self.image_width, y-h+self.image_height]]) ? return points
所有的Bbox类都从BboxBase继承,只需要重载其get_points()方法,返回一个格式如下的二维数组即可:
[[左下角X轴坐标, 左下角Y轴坐标], [右上角X轴坐标, 右上角Y轴坐标]]
CenterPointBBox类有5个参数,其中x和y是矩形区域的中心坐标,transform是将中点坐标转换到窗口坐标系的坐标转换对象。例如若(x,y)为数据坐标系中的坐标,那么transform就是将数据坐标系转换为窗口坐标系的对象。width和height是矩形区域的以像素为单位的宽和高。
在get_points()中,?通过坐标转换对象_transform的transform()方法,将坐标转换为窗口坐标。?计算矩形区域的左下角和右上角的坐标。
用CenterPointBBox在数据坐标系中绘制图像
有了CenterPointBBox类,我们很容易写出在数据坐标系中一系列点上绘制图像的函数。
def plot_points_with_image(xs, ys, img): ax = pl.gca() for x, y in zip(xs, ys): bbox = CenterPointBBox(x, y, ax.transData, img.shape[1], img.shape[0]) ? imgbox = BboxImage(bbox) imgbox.set_data(img) ax.add_artist(imgbox)ball_img = pl.imread("blue_ball.png")ax = pl.subplot(111)xs = np.linspace(0, 2*np.pi, 100)ys = np.sin(xs)pl.plot(xs, ys, zorder=-1) ?plot_points_with_image(xs[::10], ys[::10], ball_img)pl.show()
注意图像的第1轴长度为宽度,而第0轴长度为高度。?为了让图像覆盖曲线,将曲线的zorder设置为-1。程序的输出如下图所示。
还可以使用offsetbox模块中提供的AnnotationBbox和OffsetImage实现相同的功能。AnnotationBbox是一个标注框,其中可以放置任何Artist对象,我们在其中放置一个OffsetImage对象,它能按照指定的比例显示图像,缺省比例为1。关于这两个对象的各种参数,请读者查看相关文档及源代码。
用AnnotationBbox和OffsetImage在数据坐标系中绘制图像
import numpy as npfrom matplotlib.offsetbox import AnnotationBbox, OffsetImageimport pylab as pldef plot_points_with_image(xs, ys, img): ax = pl.gca() for x, y in zip(xs, ys): imagebox = OffsetImage(img) ab = AnnotationBbox(imagebox, (x, y), xycoords='data', frameon = False) ax.add_artist(ab)xs = np.linspace(0, 2*np.pi, 100)ys = np.sin(xs)ax = pl.subplot(111)pl.plot(xs, ys, zorder=-1)ball_img = pl.imread("blue_ball.png")plot_points_with_image(xs[::10], ys[::10], ball_img)pl.show()
联系客服