Skip to content

Commit 9d265a5

Browse files
authored
Merge pull request #29 from Belval/text-orientation-and-variable-spacing
Text orientation and variable spacing
2 parents 8d49da9 + f47b69e commit 9d265a5

9 files changed

Lines changed: 264 additions & 28 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ tqdm
2222
You can simply use `pip install -r requirements.txt` too.
2323

2424
## New
25+
- Change the text orientation using the `-or` parameter
26+
- Change the space width using the `-sw` parameter
2527
- Specify text color range using `-tc '#000000,#FFFFFF'`, please note that the quotes are **necessary**
2628
- Explicit alignement when using `-al` with fixed width (0: Left, 1: Center, 2: Right)
2729
- Fixed width using `-wd`
28-
- Generate random strings with letters, numbers and symbols (Thank you @FHainzl)
29-
- Save the labels in a file instead of in the file name (Thank you @FHainzl)
3030
- Add support for Simplified and Traditional Chinese
3131

3232
## How does it work?

TextRecognitionDataGenerator/computer_text_generator.py

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,51 @@
44

55
class ComputerTextGenerator(object):
66
@classmethod
7-
def generate(cls, text, font, text_color, font_size):
7+
def generate(cls, text, font, text_color, font_size, orientation, space_width):
8+
if orientation == 0:
9+
return cls.__generate_horizontal_text(text, font, text_color, font_size, space_width)
10+
elif orientation == 1:
11+
return cls.__generate_vertical_text(text, font, text_color, font_size, space_width)
12+
else:
13+
raise ValueError("Unknown orientation " + str(orientation))
14+
15+
@classmethod
16+
def __generate_horizontal_text(cls, text, font, text_color, font_size, space_width):
17+
image_font = ImageFont.truetype(font=font, size=font_size)
18+
words = text.split(' ')
19+
space_width = image_font.getsize(' ')[0] * space_width
20+
21+
words_width = [image_font.getsize(w)[0] for w in words]
22+
text_width = sum(words_width) + int(space_width) * (len(words) - 1)
23+
text_height = max([image_font.getsize(w)[1] for w in words])
24+
25+
txt_img = Image.new('RGBA', (text_width, text_height), (0, 0, 0, 0))
26+
27+
txt_draw = ImageDraw.Draw(txt_img)
28+
29+
colors = [ImageColor.getrgb(c) for c in text_color.split(',')]
30+
c1, c2 = colors[0], colors[-1]
31+
32+
fill = (
33+
random.randint(c1[0], c2[0]),
34+
random.randint(c1[1], c2[1]),
35+
random.randint(c1[2], c2[2])
36+
)
37+
38+
for i, w in enumerate(words):
39+
txt_draw.text((sum(words_width[0:i]) + i * int(space_width), 0), w, fill=fill, font=image_font)
40+
41+
return txt_img
42+
43+
@classmethod
44+
def __generate_vertical_text(cls, text, font, text_color, font_size, space_width):
845
image_font = ImageFont.truetype(font=font, size=font_size)
9-
text_width, text_height = image_font.getsize(text)
46+
47+
space_height = int(image_font.getsize(' ')[1] * space_width)
48+
49+
char_heights = [image_font.getsize(c)[1] if c != ' ' else space_height for c in text]
50+
text_width = max([image_font.getsize(c)[0] for c in text])
51+
text_height = sum(char_heights)
1052

1153
txt_img = Image.new('RGBA', (text_width, text_height), (0, 0, 0, 0))
1254

@@ -21,6 +63,7 @@ def generate(cls, text, font, text_color, font_size):
2163
random.randint(c1[2], c2[2])
2264
)
2365

24-
txt_draw.text((0, 0), text, fill=fill, font=image_font)
66+
for i, c in enumerate(text):
67+
txt_draw.text((0, sum(char_heights[0:i])), c, fill=fill, font=image_font)
2568

2669
return txt_img

TextRecognitionDataGenerator/data_generator.py

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,18 @@ def generate_from_tuple(cls, t):
2121
cls.generate(*t)
2222

2323
@classmethod
24-
def generate(cls, index, text, font, out_dir, height, extension, skewing_angle, random_skew, blur, random_blur, background_type, distorsion_type, distorsion_orientation, is_handwritten, name_format, width, alignment, text_color):
24+
def generate(cls, index, text, font, out_dir, size, extension, skewing_angle, random_skew, blur, random_blur, background_type, distorsion_type, distorsion_orientation, is_handwritten, name_format, width, alignment, text_color, orientation, space_width):
2525
image = None
2626

2727
##########################
2828
# Create picture of text #
2929
##########################
3030
if is_handwritten:
31+
if orientation == 1:
32+
raise ValueError("Vertical handwritten text is unavailable")
3133
image = HandwrittenTextGenerator.generate(text)
3234
else:
33-
image = ComputerTextGenerator.generate(text, font, text_color, height)
35+
image = ComputerTextGenerator.generate(text, font, text_color, size, orientation, space_width)
3436

3537
random_angle = random.randint(0-skewing_angle, skewing_angle)
3638

@@ -64,23 +66,32 @@ def generate(cls, index, text, font, out_dir, height, extension, skewing_angle,
6466
# Resize image to desired format #
6567
##################################
6668

67-
new_width = int(float(distorted_img.size[0] + 10) * (float(height) / float(distorted_img.size[1] + 10)))
68-
69-
resized_img = distorted_img.resize((new_width, height - 10), Image.ANTIALIAS)
70-
71-
background_width = width if width > 0 else new_width + 10
69+
# Horizontal text
70+
if orientation == 0:
71+
new_width = int(float(distorted_img.size[0] + 10) * (float(size) / float(distorted_img.size[1] + 10)))
72+
resized_img = distorted_img.resize((new_width, size - 10), Image.ANTIALIAS)
73+
background_width = width if width > 0 else new_width + 10
74+
background_height = size
75+
# Vertical text
76+
elif orientation == 1:
77+
new_height = int(float(distorted_img.size[1] + 10) * (float(size) / float(distorted_img.size[0] + 10)))
78+
resized_img = distorted_img.resize((size - 10, new_height), Image.ANTIALIAS)
79+
background_width = size
80+
background_height = new_height + 10
81+
else:
82+
raise ValueError("Invalid orientation")
7283

7384
#############################
7485
# Generate background image #
7586
#############################
7687
if background_type == 0:
77-
background = BackgroundGenerator.gaussian_noise(height, background_width)
88+
background = BackgroundGenerator.gaussian_noise(background_height, background_width)
7889
elif background_type == 1:
79-
background = BackgroundGenerator.plain_white(height, background_width)
90+
background = BackgroundGenerator.plain_white(background_height, background_width)
8091
elif background_type == 2:
81-
background = BackgroundGenerator.quasicrystal(height, background_width)
92+
background = BackgroundGenerator.quasicrystal(background_height, background_width)
8293
else:
83-
background = BackgroundGenerator.picture(height, background_width)
94+
background = BackgroundGenerator.picture(background_height, background_width)
8495

8596
#############################
8697
# Place text with alignment #

TextRecognitionDataGenerator/run.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def parse_arguments():
103103
"--format",
104104
type=int,
105105
nargs="?",
106-
help="Define the height of the produced images",
106+
help="Define the height of the produced images if horizontal, else the width",
107107
default=32,
108108
)
109109
parser.add_argument(
@@ -212,6 +212,14 @@ def parse_arguments():
212212
help="Define the alignment of the text in the image. Only used if the width parameter is set. 0: left, 1: center, 2: right",
213213
default=1
214214
)
215+
parser.add_argument(
216+
"-or",
217+
"--orientation",
218+
type=int,
219+
nargs="?",
220+
help="Define the orientation of the text. 0: Horizontal, 1: Vertical",
221+
default=0
222+
)
215223
parser.add_argument(
216224
"-tc",
217225
"--text_color",
@@ -220,6 +228,14 @@ def parse_arguments():
220228
help="Define the text's color, should be either a single hex color or a range in the ?,? format.",
221229
default='#282828'
222230
)
231+
parser.add_argument(
232+
"-sw",
233+
"--space_width",
234+
type=float,
235+
nargs="?",
236+
help="Define the width of the spaces between words. 2.0 means twice the normal space width",
237+
default=1.0
238+
)
223239

224240
return parser.parse_args()
225241

@@ -304,7 +320,9 @@ def main():
304320
[args.name_format] * string_count,
305321
[args.width] * string_count,
306322
[args.alignment] * string_count,
307-
[args.text_color] * string_count
323+
[args.text_color] * string_count,
324+
[args.orientation] * string_count,
325+
[args.space_width] * string_count
308326
)
309327
), total=args.count):
310328
pass

TextRecognitionDataGenerator/string_generator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def create_strings_from_file(filename, count):
1717
if len(lines) == 0:
1818
raise Exception("No lines could be read in file")
1919
while len(strings) < count:
20-
if len(lines) > count - len(strings):
20+
if len(lines) >= count - len(strings):
2121
strings.extend(lines[0:count - len(strings)])
2222
else:
2323
strings.extend(lines)

0 commit comments

Comments
 (0)