0

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'))
Sara
  • 245
  • 4
  • 11
  • Does this answer your question? [Plt.show shows full graph but savefig is cropping the image](https://stackoverflow.com/questions/37427362/plt-show-shows-full-graph-but-savefig-is-cropping-the-image) – Ynjxsjmh May 11 '22 at 07:37
  • no, because that will change the size of the image. I want the image to have a specified number of rows and columns. I can see I didn't make it clear. Thanks for pointing it out. I have edited my question. – Sara May 11 '22 at 08:08
  • I think rather than to overcome these clipped issue in matplotlib, you can choose another image library to do this task. – Ynjxsjmh May 11 '22 at 08:25
  • I actually just figured a way to do this in matplotlib, which I will post in just a sec. But what library do you have in mind? – Sara May 11 '22 at 08:35
  • Maybe [PIL](https://pypi.org/project/Pillow/). – Ynjxsjmh May 11 '22 at 10:24

1 Answers1

0

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(?)
Sara
  • 245
  • 4
  • 11