You may use an AnnotationBbox
inside of which an AuxTransformBox
is placed. This AuxTransformBox
would contain a proxy rectangle of the desired size. This can be made invisible (e.g. fc='none', ec='none'
). Its only function is to scale the AuxTransformBox
to the right size. Now the AnnotationBbox
can be given a border of some large linewidth. If it is sitting tight against the AuxTransformBox
the border will only start where the AuxTransformBox
ends. To let the border fit tightly, one can set the padding pad
to half the linewidth of the border. Since padding is given in units of fontsize, it is the fontsize which needs to be set to the linewidth and the padding to 0.5, pad=0.5,fontsize=linewidth
. Note that it appears that a slightly larger padding of 0.52 looks nicer on the plot; in any case this can be adjusted to one's liking.
Sounds complicated, but the code is copy and pastable to be used anywhere a Rectangle would usually be used.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from matplotlib.offsetbox import AnnotationBbox, AuxTransformBox
# Here's my "image"
X = np.arange(16).reshape(4,4)
# Suppose I want to highlight some feature in the middle boxes.
fig = plt.figure()
ax = fig.add_subplot(111)
ax.imshow(X, cmap=plt.cm.gray, interpolation='nearest', aspect="auto")
linewidth=14
xy, w, h = (0.5, 0.5), 2, 2
r = Rectangle(xy, w, h, fc='none', ec='gold', lw=1)
offsetbox = AuxTransformBox(ax.transData)
offsetbox.add_artist(r)
ab = AnnotationBbox(offsetbox, (xy[0]+w/2.,xy[1]+w/2.),
boxcoords="data", pad=0.52,fontsize=linewidth,
bboxprops=dict(facecolor = "none", edgecolor='r',
lw = linewidth))
ax.add_artist(ab)
plt.show()
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…