Bbox是一個(gè)描述矩形區(qū)域的對(duì)象,BboxImage則是在Bbox中描繪圖像的對(duì)象。下面是一個(gè)簡(jiǎn)單的例子:
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()
調(diào)用pylab.imread()載入圖像,得到的是一個(gè)形狀為(圖像高, 圖像寬, 4)的三維數(shù)組,其中4為圖像的通道數(shù)。?調(diào)用Bbox類的靜態(tài)方法from_bounds()創(chuàng)建一個(gè)左下角坐標(biāo)為(250,200)、寬100,高150的Bbox對(duì)象。?通過(guò)矩形區(qū)域bbox和圖像數(shù)組ball_img創(chuàng)建一個(gè)BboxImage對(duì)象。?并通過(guò)add_artist()將BboxImage對(duì)象添加進(jìn)子圖對(duì)象的artist列表。下圖是程序的輸出結(jié)果:
請(qǐng)調(diào)整圖表的大小,觀察圖像的位置變化??梢钥闯鰣D像相對(duì)于窗口左下角的位置始終保持不變。因此可知Bbox對(duì)象所指定的矩形區(qū)域是相對(duì)于窗口坐標(biāo)系的。在窗口坐標(biāo)系中,窗口的左下角為坐標(biāo)原點(diǎn),X軸的正方向?yàn)橛曳?,Y軸的正方向?yàn)樯戏?,坐?biāo)值以像素為單位。
為了在數(shù)據(jù)坐標(biāo)系定位圖像的中心,我們需要編寫(xiě)一個(gè)BboxBase的派生類,完成坐標(biāo)系轉(zhuǎn)換工作:
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()方法,返回一個(gè)格式如下的二維數(shù)組即可:
[[左下角X軸坐標(biāo), 左下角Y軸坐標(biāo)], [右上角X軸坐標(biāo), 右上角Y軸坐標(biāo)]]
CenterPointBBox類有5個(gè)參數(shù),其中x和y是矩形區(qū)域的中心坐標(biāo),transform是將中點(diǎn)坐標(biāo)轉(zhuǎn)換到窗口坐標(biāo)系的坐標(biāo)轉(zhuǎn)換對(duì)象。例如若(x,y)為數(shù)據(jù)坐標(biāo)系中的坐標(biāo),那么transform就是將數(shù)據(jù)坐標(biāo)系轉(zhuǎn)換為窗口坐標(biāo)系的對(duì)象。width和height是矩形區(qū)域的以像素為單位的寬和高。
在get_points()中,?通過(guò)坐標(biāo)轉(zhuǎn)換對(duì)象_transform的transform()方法,將坐標(biāo)轉(zhuǎn)換為窗口坐標(biāo)。?計(jì)算矩形區(qū)域的左下角和右上角的坐標(biāo)。
用CenterPointBBox在數(shù)據(jù)坐標(biāo)系中繪制圖像
有了CenterPointBBox類,我們很容易寫(xiě)出在數(shù)據(jù)坐標(biāo)系中一系列點(diǎn)上繪制圖像的函數(shù)。
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軸長(zhǎng)度為寬度,而第0軸長(zhǎng)度為高度。?為了讓圖像覆蓋曲線,將曲線的zorder設(shè)置為-1。程序的輸出如下圖所示。
還可以使用offsetbox模塊中提供的AnnotationBbox和OffsetImage實(shí)現(xiàn)相同的功能。AnnotationBbox是一個(gè)標(biāo)注框,其中可以放置任何Artist對(duì)象,我們?cè)谄渲蟹胖靡粋€(gè)OffsetImage對(duì)象,它能按照指定的比例顯示圖像,缺省比例為1。關(guān)于這兩個(gè)對(duì)象的各種參數(shù),請(qǐng)讀者查看相關(guān)文檔及源代碼。
用AnnotationBbox和OffsetImage在數(shù)據(jù)坐標(biāo)系中繪制圖像
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()
聯(lián)系客服