'make sure text falls within plot using matplotlib
I am trying to generate random images of text and store them as image files in my computer so that I can use them to train a model later. But I don't know how make sure all the characters falls within the image boundaries. When I plot them out in python they always show, but if I looked at the saved image, some times the strings are cut. Also, I want to automate the process instead of plotting each out to check.
Furthermore, setting bbox_inches='tight' changes the image size, while I want to be able to specify the image size.
This is what I have tried so far
import matplotlib.pyplot as plt
import numpy as np
dpi = 100
h, w = 50, 100
plt.figure(figsize=(w / dpi, h / dpi), dpi=dpi)# so I will get w columns and h rows
text = str(np.random.uniform(100000, 1000000))# my string will always only be 6 characters
x = np.random.uniform(0, .3)# random positions
y = np.random.uniform(0, .5)
size = np.random.uniform(16, 23)# random text size
plt.text(x, y, text, fontdict={'size': size})
plt.axis('off')
plt.savefig(text + '.jpg'))
Solution 1:[1]
I figured a way to get around this. .get_window_extent() can help locate the edges of the text. Since I just want to generate random images, I can drop the image and generate the next one if the text it out of bounds. For non-random text, I suppose one can also use it to determine which way to shift text if it goes out of bounds.
Here is a sample solution with my random text case:
import matplotlib.pyplot as plt
import numpy as np
dpi = 100
w = 120 # number of columns
h = 50 # number of rows
N = 100 # number of random images to generate
count = 0
while count < N:
fig = plt.figure(frameon=False, dpi=dpi)
fig.set_size_inches(w / dpi, h / dpi)
ax = plt.Axes(fig, [0., 0., 1., 1.])
ax.set_axis_off()
fig.add_axes(ax)
number = str(np.random.randint(100000, 1000000))# random text
x = np.random.uniform(0, .1)# random position
y = np.random.uniform(0, .5)
size = np.random.uniform(w / dpi * 72 / 6, w / dpi * 72 / 3.3)
text = ax.text(x, y, number, fontdict={'size': size})
bbox = text.get_window_extent(fig.canvas.get_renderer())# !!! get the extent of the text
if (bbox.x1 < w) & (bbox.y1 < h):# !!! make sure the extent is within bounds before save
plt.savefig(f'{number}.jpg'), pad_inches=0, dpi=dpi)
count += 1
plt.close()# remember to close else bad for memory(?)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Sara |
