Skip to content

Commit a5ee09d

Browse files
authored
Add --fit and --margins parameters
Fixes: #49
1 parent 0489667 commit a5ee09d

19 files changed

Lines changed: 130 additions & 41 deletions

README.md

Lines changed: 1 addition & 1 deletion
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+
- Add `--fit` and `--margins` for finer layout control
2526
- Change the text orientation using the `-or` parameter
2627
- Change the space width using the `-sw` parameter
2728
- Specify text color range using `-tc '#000000,#FFFFFF'`, please note that the quotes are **necessary**
2829
- Explicit alignement when using `-al` with fixed width (0: Left, 1: Center, 2: Right)
29-
- Fixed width using `-wd`
3030
- Add support for Simplified and Traditional Chinese
3131

3232
## How does it work?

TextRecognitionDataGenerator/computer_text_generator.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@
44

55
class ComputerTextGenerator(object):
66
@classmethod
7-
def generate(cls, text, font, text_color, font_size, orientation, space_width):
7+
def generate(cls, text, font, text_color, font_size, orientation, space_width, fit):
88
if orientation == 0:
9-
return cls.__generate_horizontal_text(text, font, text_color, font_size, space_width)
9+
return cls.__generate_horizontal_text(text, font, text_color, font_size, space_width, fit)
1010
elif orientation == 1:
11-
return cls.__generate_vertical_text(text, font, text_color, font_size, space_width)
11+
return cls.__generate_vertical_text(text, font, text_color, font_size, space_width, fit)
1212
else:
1313
raise ValueError("Unknown orientation " + str(orientation))
1414

1515
@classmethod
16-
def __generate_horizontal_text(cls, text, font, text_color, font_size, space_width):
16+
def __generate_horizontal_text(cls, text, font, text_color, font_size, space_width, fit):
1717
image_font = ImageFont.truetype(font=font, size=font_size)
1818
words = text.split(' ')
1919
space_width = image_font.getsize(' ')[0] * space_width
@@ -38,10 +38,13 @@ def __generate_horizontal_text(cls, text, font, text_color, font_size, space_wid
3838
for i, w in enumerate(words):
3939
txt_draw.text((sum(words_width[0:i]) + i * int(space_width), 0), w, fill=fill, font=image_font)
4040

41-
return txt_img
41+
if fit:
42+
return txt_img.crop(txt_img.getbbox())
43+
else:
44+
return txt_img
4245

4346
@classmethod
44-
def __generate_vertical_text(cls, text, font, text_color, font_size, space_width):
47+
def __generate_vertical_text(cls, text, font, text_color, font_size, space_width, fit):
4548
image_font = ImageFont.truetype(font=font, size=font_size)
4649

4750
space_height = int(image_font.getsize(' ')[1] * space_width)
@@ -66,4 +69,7 @@ def __generate_vertical_text(cls, text, font, text_color, font_size, space_width
6669
for i, c in enumerate(text):
6770
txt_draw.text((0, sum(char_heights[0:i])), c, fill=fill, font=image_font)
6871

69-
return txt_img
72+
if fit:
73+
return txt_img.crop(txt_img.getbbox())
74+
else:
75+
return txt_img

TextRecognitionDataGenerator/data_generator.py

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

2323
@classmethod
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):
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, margins, fit):
2525
image = None
2626

27+
margin_top, margin_left, margin_bottom, margin_right = margins
28+
horizontal_margin = margin_left + margin_right
29+
vertical_margin = margin_top + margin_bottom
30+
2731
##########################
2832
# Create picture of text #
2933
##########################
3034
if is_handwritten:
3135
if orientation == 1:
3236
raise ValueError("Vertical handwritten text is unavailable")
33-
image = HandwrittenTextGenerator.generate(text, text_color)
37+
image = HandwrittenTextGenerator.generate(text, text_color, fit)
3438
else:
35-
image = ComputerTextGenerator.generate(text, font, text_color, size, orientation, space_width)
39+
image = ComputerTextGenerator.generate(text, font, text_color, size, orientation, space_width, fit)
3640

3741
random_angle = random.randint(0-skewing_angle, skewing_angle)
3842

@@ -68,16 +72,16 @@ def generate(cls, index, text, font, out_dir, size, extension, skewing_angle, ra
6872

6973
# Horizontal text
7074
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
75+
new_width = int(distorted_img.size[0] * (float(size - vertical_margin) / float(distorted_img.size[1])))
76+
resized_img = distorted_img.resize((new_width, size - vertical_margin), Image.ANTIALIAS)
77+
background_width = width if width > 0 else new_width + horizontal_margin
7478
background_height = size
7579
# Vertical text
7680
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)
81+
new_height = int(float(distorted_img.size[1]) * (float(size - horizontal_margin) / float(distorted_img.size[0])))
82+
resized_img = distorted_img.resize((size - horizontal_margin, new_height), Image.ANTIALIAS)
7983
background_width = size
80-
background_height = new_height + 10
84+
background_height = new_height + vertical_margin
8185
else:
8286
raise ValueError("Invalid orientation")
8387

@@ -99,12 +103,12 @@ def generate(cls, index, text, font, out_dir, size, extension, skewing_angle, ra
99103

100104
new_text_width, _ = resized_img.size
101105

102-
if alignment == 0:
103-
background.paste(resized_img, (5, 5), resized_img)
106+
if alignment == 0 or width == -1:
107+
background.paste(resized_img, (margin_left, margin_top), resized_img)
104108
elif alignment == 1:
105-
background.paste(resized_img, (int(background_width / 2 - new_text_width / 2), 5), resized_img)
109+
background.paste(resized_img, (int(background_width / 2 - new_text_width / 2), margin_top), resized_img)
106110
else:
107-
background.paste(resized_img, (background_width - new_text_width - 5, 5), resized_img)
111+
background.paste(resized_img, (background_width - new_text_width - margin_right, margin_top), resized_img)
108112

109113
##################################
110114
# Apply gaussian blur #

TextRecognitionDataGenerator/handwritten_text_generator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ def __join_images(cls, images):
116116
return compound_image
117117

118118
@classmethod
119-
def generate(cls, text, text_color):
119+
def generate(cls, text, text_color, fit):
120120
with open(os.path.join('handwritten_model', 'translation.pkl'), 'rb') as file:
121121
translation = pickle.load(file)
122122

TextRecognitionDataGenerator/run.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@
1313
from data_generator import FakeTextDataGenerator
1414
from multiprocessing import Pool
1515

16-
def valid_range(s):
17-
if len(s.split(',')) > 2:
18-
raise argparse.ArgumentError("The given range is invalid, please use ?,? format.")
19-
return tuple([int(i) for i in s.split(',')])
16+
def margins(margin):
17+
margins = margin.split(',')
18+
if len(margins) == 1:
19+
return [margins[0]] * 4
20+
return [int(m) for m in margins]
2021

2122
def parse_arguments():
2223
"""
@@ -236,6 +237,22 @@ def parse_arguments():
236237
help="Define the width of the spaces between words. 2.0 means twice the normal space width",
237238
default=1.0
238239
)
240+
parser.add_argument(
241+
"-m",
242+
"--margins",
243+
type=margins,
244+
nargs="?",
245+
help="Define the margins around the text when rendered. In pixels",
246+
default=(5, 5, 5, 5)
247+
)
248+
parser.add_argument(
249+
"-fi",
250+
"--fit",
251+
action="store_true",
252+
help="Apply a tight crop around the rendered text",
253+
default=False
254+
)
255+
239256

240257
return parser.parse_args()
241258

@@ -322,7 +339,9 @@ def main():
322339
[args.alignment] * string_count,
323340
[args.text_color] * string_count,
324341
[args.orientation] * string_count,
325-
[args.space_width] * string_count
342+
[args.space_width] * string_count,
343+
[args.margins] * string_count,
344+
[args.fit] * string_count
326345
)
327346
), total=args.count):
328347
pass

tests.py

Lines changed: 74 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,9 @@ def test_generate_data_with_format(self):
8686
0,
8787
'#010101',
8888
0,
89-
1
89+
1,
90+
(5,5,5,5),
91+
0
9092
)
9193

9294
self.assertTrue(
@@ -116,7 +118,9 @@ def test_generate_data_with_extension(self):
116118
0,
117119
'#010101',
118120
0,
119-
1
121+
1,
122+
(5,5,5,5),
123+
0
120124
)
121125

122126
self.assertTrue(
@@ -146,7 +150,9 @@ def test_generate_data_with_skew_angle(self):
146150
0,
147151
'#010101',
148152
0,
149-
1
153+
1,
154+
(5,5,5,5),
155+
0
150156
)
151157

152158
self.assertTrue(
@@ -176,7 +182,9 @@ def test_generate_data_with_blur(self):
176182
0,
177183
'#010101',
178184
0,
179-
1
185+
1,
186+
(5,5,5,5),
187+
0
180188
)
181189

182190
self.assertTrue(
@@ -206,7 +214,9 @@ def test_generate_data_with_sine_distorsion(self):
206214
0,
207215
'#010101',
208216
0,
209-
1
217+
1,
218+
(5,5,5,5),
219+
0
210220
)
211221

212222
self.assertTrue(
@@ -236,7 +246,9 @@ def test_generate_data_with_cosine_distorsion(self):
236246
0,
237247
'#010101',
238248
0,
239-
1
249+
1,
250+
(5,5,5,5),
251+
0
240252
)
241253

242254
self.assertTrue(
@@ -266,7 +278,9 @@ def test_generate_data_with_left_alignment(self):
266278
0,
267279
'#010101',
268280
0,
269-
1
281+
1,
282+
(5,5,5,5),
283+
0
270284
)
271285

272286
self.assertTrue(
@@ -296,7 +310,9 @@ def test_generate_data_with_center_alignment(self):
296310
1,
297311
'#010101',
298312
0,
299-
1
313+
1,
314+
(5,5,5,5),
315+
0
300316
)
301317

302318
self.assertTrue(
@@ -326,7 +342,9 @@ def test_generate_data_with_right_alignment(self):
326342
2,
327343
'#010101',
328344
0,
329-
1
345+
1,
346+
(5,5,5,5),
347+
0
330348
)
331349

332350
self.assertTrue(
@@ -357,7 +375,9 @@ def test_raise_if_handwritten_and_vertical(self):
357375
2,
358376
'#010101',
359377
1,
360-
1
378+
1,
379+
(5,5,5,5),
380+
0
361381
)
362382
raise Exception("Vertical handwritten did not throw")
363383
except ValueError:
@@ -384,7 +404,9 @@ def test_generate_vertical_text(self):
384404
0,
385405
'#010101',
386406
1,
387-
1
407+
1,
408+
(5,5,5,5),
409+
0
388410
)
389411

390412
self.assertTrue(
@@ -414,7 +436,9 @@ def test_generate_horizontal_text_with_variable_space(self):
414436
0,
415437
'#010101',
416438
0,
417-
4
439+
4,
440+
(5,5,5,5),
441+
0
418442
)
419443

420444
self.assertTrue(
@@ -444,7 +468,9 @@ def test_generate_vertical_text_with_variable_space(self):
444468
0,
445469
'#010101',
446470
1,
447-
2
471+
2,
472+
(5,5,5,5),
473+
0
448474
)
449475

450476
self.assertTrue(
@@ -475,12 +501,46 @@ def test_generate_text_with_unknown_orientation(self):
475501
0,
476502
'#010101',
477503
100,
478-
2
504+
2,
505+
(5,5,5,5),
506+
0
479507
)
480508
raise Exception("Unknown orientation did not throw")
481509
except ValueError:
482510
pass
483511

512+
def test_generate_data_with_fit(self):
513+
FakeTextDataGenerator.generate(
514+
13,
515+
'TEST TEST TEST',
516+
'tests/font.ttf',
517+
'tests/out/',
518+
64,
519+
'jpg',
520+
0,
521+
False,
522+
0,
523+
False,
524+
1,
525+
0,
526+
0,
527+
False,
528+
0,
529+
-1,
530+
0,
531+
'#010101',
532+
0,
533+
1,
534+
(0,0,0,0),
535+
1
536+
)
537+
538+
self.assertTrue(
539+
md5('tests/out/TEST TEST TEST_13.jpg') == md5('tests/expected_results/TEST TEST TEST_13.jpg')
540+
)
541+
542+
os.remove('tests/out/TEST TEST TEST_13.jpg')
543+
484544
def test_generate_string_with_letters(self):
485545
s = create_strings_randomly(1, False, 1, True, False, False, 'en')[0]
486546

-160 Bytes
Loading
-1.72 KB
Loading
105 Bytes
Loading
-234 Bytes
Loading

0 commit comments

Comments
 (0)