diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3b6c3ec --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.idea/ +*.pyc +Background/ +*.ttf +*.otf diff --git a/.idea/DocEmul.iml b/.idea/DocEmul.iml deleted file mode 100644 index 7118278..0000000 --- a/.idea/DocEmul.iml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 12f37ed..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 269b3b8..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/branden.xml b/Data/Brandenburg/branden.xml similarity index 95% rename from branden.xml rename to Data/Brandenburg/branden.xml index 2a9cd9a..c1b50f3 100644 --- a/branden.xml +++ b/Data/Brandenburg/branden.xml @@ -169,21 +169,21 @@ - - - - + + + + - + - - - + + + - - + + diff --git a/branden2.xml b/Data/Brandenburg/branden2.xml similarity index 98% rename from branden2.xml rename to Data/Brandenburg/branden2.xml index 45c016d..e2d8c78 100644 --- a/branden2.xml +++ b/Data/Brandenburg/branden2.xml @@ -694,24 +694,24 @@ - - - - - + + + + + - + - + - + - + - + diff --git a/esposalles.xml b/Data/Esposalles/esposalles.xml similarity index 97% rename from esposalles.xml rename to Data/Esposalles/esposalles.xml index 6303e86..0b6d415 100644 --- a/esposalles.xml +++ b/Data/Esposalles/esposalles.xml @@ -387,20 +387,20 @@ - - - + + + - + - - - + + + - - + + diff --git a/esposalles_big.xml b/Data/Esposalles/esposalles_big.xml similarity index 97% rename from esposalles_big.xml rename to Data/Esposalles/esposalles_big.xml index 0101cdf..c7d1c8f 100644 --- a/esposalles_big.xml +++ b/Data/Esposalles/esposalles_big.xml @@ -387,20 +387,20 @@ - - - + + + - + - - - + + + - - + + diff --git a/esposalles_small.xml b/Data/Esposalles/esposalles_small.xml similarity index 97% rename from esposalles_small.xml rename to Data/Esposalles/esposalles_small.xml index b4c7273..81263c0 100644 --- a/esposalles_small.xml +++ b/Data/Esposalles/esposalles_small.xml @@ -387,24 +387,20 @@ - - - + + + - - - - - - - - - - + + + + + + diff --git a/divina.txt b/Dictionaries/divina.txt similarity index 100% rename from divina.txt rename to Dictionaries/divina.txt diff --git a/extra.txt b/Dictionaries/extra.txt similarity index 100% rename from extra.txt rename to Dictionaries/extra.txt diff --git a/extra2.txt b/Dictionaries/extra2.txt similarity index 100% rename from extra2.txt rename to Dictionaries/extra2.txt diff --git a/extra3.txt b/Dictionaries/extra3.txt similarity index 100% rename from extra3.txt rename to Dictionaries/extra3.txt diff --git a/numbers.txt b/Dictionaries/numbers.txt similarity index 100% rename from numbers.txt rename to Dictionaries/numbers.txt diff --git a/README.md b/README.md index 5ac83e0..e815527 100644 --- a/README.md +++ b/README.md @@ -19,13 +19,20 @@ in `/Data` you can find some generated files for two different datasets (E ### Document structure There are several XML files to describe the document structure. This files are used also in the experiments proposed in the research. + ### Text data In the text files there are the data used to write text during the production process. + ### Fonts Before to start the generation process, you need to download from `http://www.dafont.com/` the used fonts for the experiments. -Run the script `python download_font.py' which creates the directory `handwritten`. Here you can find some fonts downloaded from `http://www.dafont.com/` and used to generate the synthetic data for the experiments. +Run the script `python download_font.py` which creates the directory `fonts`. Here you can find some fonts downloaded from `http://www.dafont.com/` and used to generate the synthetic data for the experiments. # Generation process + +## Pre-requisites +- Python 3 +- `pip install -r py-requirements.txt` + ## Esposalles It is possible to emulate the generation of documents for the dataset Esposalles. @@ -46,7 +53,7 @@ Try to modify the script to generate more pages. If you need more instructions to define the document structure, please, contact us and we will glad to help you.. ## Brandenburg -It is possible to emulate the generation of documents for the dataset Brandenburg. Running the script `python test_generate_brandenburg.py` it will be possible to generate documents following the Brandenburg model (`branden2.xml`). It will build the synthetic dataset (only text over a transparent background) into the local directory `GENERATED/Brandenburg/test`. +It is possible to emulate the generation of documents for the dataset Brandenburg. Running the script `python generate_brandenburg.py` it will be possible to generate documents following the Brandenburg model (`branden2.xml`). It will build the synthetic dataset (only text over a transparent background) into the local directory `GENERATED/Brandenburg/test`. # Citing DocEmul diff --git a/branden_test.py b/branden_test.py index 24d7b46..32af7f6 100644 --- a/branden_test.py +++ b/branden_test.py @@ -5,7 +5,7 @@ -def create_bf(dir='/home/scstech/PycharmProjects/synthetic_handwritten/CNN_MODELS/test_set/F2-1'): +def create_bf(dir='/home/scstech/PycharmProjects/synthetic_fonts/CNN_MODELS/test_set/F2-1'): files = [os.path.join(dir,f) for f in os.listdir(dir) if f.split('.')[-1] == 'jpg'] np.random.shuffle(files) print len(files) @@ -16,7 +16,7 @@ def create_bf(dir='/home/scstech/PycharmProjects/synthetic_handwritten/CNN_MODEL -def run_realbackground(dir, path_background,num=9, size=None, greyscale=False,type='TXT',model='branden.xml'): +def run_realbackground(dir, path_background,num=9, size=None, greyscale=False,type='TXT',model='Data/Brandenburg/branden.xml'): RealBackGound.dirname = path_background realSampler = RealBackGound.load_examples() @@ -26,7 +26,7 @@ def run_realbackground(dir, path_background,num=9, size=None, greyscale=False,ty #solidSampler = SolidBackGroundback(colors=[255]) #realSampler = RealBackGound.load_examples() -def run(dir, num=5, size=None, sampler=None, greyscale=False,type='TXT',model='branden2.xml',seed=2): +def run(dir, num=5, size=None, sampler=None, greyscale=False,type='TXT',model='Data/Brandenburg/branden2.xml',seed=2): generate(dir, num=num, size=size,sampler=sampler, greyscale=greyscale,type=type,model=model,seed=seed) diff --git a/docemul/__init__.py b/docemul/__init__.py index de64a1c..0b0b7a6 100644 --- a/docemul/__init__.py +++ b/docemul/__init__.py @@ -1 +1 @@ -from extract_background import create_background_dataset \ No newline at end of file +from .extract_background import create_background_dataset diff --git a/docemul/__init__.pyc b/docemul/__init__.pyc deleted file mode 100644 index 4221ba2..0000000 Binary files a/docemul/__init__.pyc and /dev/null differ diff --git a/docemul/augment.py b/docemul/augment.py index d7ac3d2..914ab9f 100644 --- a/docemul/augment.py +++ b/docemul/augment.py @@ -1,20 +1,22 @@ -import PIL,Image -from skimage.color import rgb2grey +import PIL +from PIL import Image +from skimage.color import rgb2gray import os import csv -from scipy.misc import imread,imsave +from imageio import imread, imsave +from skimage.transform import resize as imresize import numpy as np + def augment_img(img, rotate=3, rotate_time=2, noise=2): imgs = [img] - from scipy.misc import imrotate for _ in range(rotate_time): rotation = np.random.random()*rotate*2 - rotate - print rotation + print(rotation) M = 255 - - im = PIL.Image.fromarray(np.uint8(img)) + img = (img * 255).astype(np.uint8) + im = PIL.Image.fromarray(img) # converted to have an alpha layer im2 = im.convert('RGBA') # rotated image @@ -27,7 +29,8 @@ def augment_img(img, rotate=3, rotate_time=2, noise=2): out = out.convert(im.mode) im = np.asarray(out).copy() - im = rgb2grey(im) + if len(im.shape) != 2: + im = rgb2gray(im) part = tuple(map(int,0.05 * np.array(im.shape[:2]))) top = im[:part[0],:] @@ -64,33 +67,36 @@ def augment_img(img, rotate=3, rotate_time=2, noise=2): def generate_noise(img, rand_no_noise=0.9, max_rand_distr=0.03, step=16): mod = np.zeros_like(img) - for w in range(0, img.shape[0], img.shape[0] / step): + for w in range(0, img.shape[0], img.shape[0] // step): - for h in range(0, img.shape[1], img.shape[1] / step): + for h in range(0, img.shape[1], img.shape[1] // step): if np.random.random() <= rand_no_noise: v = 0 else: v = np.random.random() * max_rand_distr - m = mod[w:w + img.shape[0] / (step / 2), h:h + img.shape[1] / (step / 2)] + m = mod[w:w + img.shape[0] // (step // 2), h:h + img.shape[1] // (step // 2)] noise = (np.random.rand(m.shape[0], m.shape[1]) < v).astype(np.uint8) - mod[w:w + img.shape[0] / (step / 2), h:h + img.shape[1] / (step / 2)] += noise + mod[w:w + img.shape[0] // (step // 2), h:h + img.shape[1] // (step // 2)] += noise return (mod>0).astype(np.uint8) def data_augment(fcsv, dir_target,f_output = 'gt_augment.csv',resize=(450,190),rotate=2, rotate_time=1, noise=1): - os.makedirs(dir_target) + os.makedirs(dir_target, exist_ok=True) img_dir = os.path.join(dir_target, 'imgs') - os.makedirs(img_dir) + os.makedirs(img_dir, exist_ok=True) f_csv_o = os.path.join(dir_target, f_output) with open(fcsv, 'r') as csv_in: with open(f_csv_o, 'w') as csv_out: writer = csv.writer(csv_out, delimiter=' ') - for f, r in csv.reader(csv_in, delimiter=' '): + for row in csv.reader(csv_in, delimiter=' '): + if not row: + continue + f, r = row if os.path.isfile(f): img = imread(f) if resize: @@ -107,8 +113,8 @@ def data_augment(fcsv, dir_target,f_output = 'gt_augment.csv',resize=(450,190),r for j, ii in enumerate(imgs): im_name = os.path.join(img_dir, fname+'_'+str(j)+'.'+ext) imsave(im_name, ii) - print im_name + print(im_name) writer.writerow([im_name, r]) else: - print 'file non valid:', f + print('file non valid:', f) diff --git a/docemul/augment.pyc b/docemul/augment.pyc deleted file mode 100644 index c2491fd..0000000 Binary files a/docemul/augment.pyc and /dev/null differ diff --git a/docemul/backgroundmodel.py b/docemul/backgroundmodel.py index 0faaaf3..034c65b 100644 --- a/docemul/backgroundmodel.py +++ b/docemul/backgroundmodel.py @@ -1,13 +1,11 @@ -from scipy.misc import imread +from imageio import imread, imsave +from skimage.transform import resize as imresize from skimage.filters import threshold_otsu from skimage.color import rgb2gray import numpy as np from sklearn import mixture from sklearn.externals import joblib - - - - +import os class BackGroudModel: def sample_bgimage(self, size): @@ -39,7 +37,7 @@ def __create_distribution__(self,files): y = [] shapes = [] for f in files: - print f + print(f) img = imread(f) gray = rgb2gray(img) @@ -57,7 +55,7 @@ def __create_distribution__(self,files): # print '1', len(filter(lambda v: v == 1, l)) # print '0', len(filter(lambda v: v == 0, l)) - print a.shape, l.shape + print(a.shape, l.shape) X.append(a) y.append(l) @@ -90,12 +88,6 @@ def load(cls, file='sampler.pkl'): return cls(obj.X,obj.y,obj.gmms) - -from scipy.misc import imread, imsave, imresize - -import numpy as np - - def get_background(file): def get_bounds(y,x,r): left = x - r @@ -144,9 +136,9 @@ def ok_bounds(patch): i = 0 for y,x in pixels: i+=1 - print i, len(pixels) + print(i, len(pixels)) if fg[y,x]==1: - print y,x + print(y,x) left, top, right ,bottom = get_bounds(y,x,r) while(ok_bounds(fg[top:bottom,left:right])==False): @@ -178,24 +170,22 @@ def get_files(dir, ext='jpg'): f_name = os.path.join(dir, f) if os.path.isfile(f_name) and f.split('.')[1] == ext: - print f + print(f) yield f_name, f -import os def create_g_dataset(dir, target, ext='jpg'): if not os.path.isdir(target): os.mkdir(target) for src, fname in get_files(dir, ext=ext): - print src + print(src) bg_file = get_background(src) f_bg = os.path.join(target, fname) imsave(f_bg, bg_file) else: - print 'already done!!!' - + print('already done!!!') class RealBackGound(BackGroudModel): @@ -222,7 +212,7 @@ def create_bg(cls, files): for src in files: _, fname = os.path.split(src) - print src + print(src) bg_file = get_background(src) f_bg = os.path.join(local_dir, fname) imsave(f_bg, bg_file) @@ -242,7 +232,6 @@ def sample_bgimage(self, size): return img - class RealBackGoundBack(BackGroudModel): basepath = '.' dirname = 'BG2_MODELS' @@ -279,4 +268,4 @@ def sample_bgimage(self, size): bg = np.ones(size,dtype=np.uint8) np.random.shuffle(self.colors) - return bg*self.colors[0] \ No newline at end of file + return bg*self.colors[0] diff --git a/docemul/backgroundmodel.pyc b/docemul/backgroundmodel.pyc deleted file mode 100644 index f2a79a8..0000000 Binary files a/docemul/backgroundmodel.pyc and /dev/null differ diff --git a/docemul/draw_document.py b/docemul/draw_document.py index 38220cd..835dfc4 100644 --- a/docemul/draw_document.py +++ b/docemul/draw_document.py @@ -1,13 +1,6 @@ -from model import Document, Lines, read_xml -from PIL import Image -from PIL import ImageFont -from PIL import ImageDraw,ImageEnhance - +from .model import Document, Lines, read_xml +from PIL import Image, ImageFont, ImageDraw, ImageEnhance import numpy as np - - - - import os def confirm(prob): @@ -97,7 +90,7 @@ def __init__(self, document, sampler, dicts, fonts): self.records = [] - print 'document.max_append_records', document.max_append_records + print('document.max_append_records', document.max_append_records) check_to_fill = np.random.randint(0, document.max_append_records) if document.max_append_records > 0 else 0 @@ -112,12 +105,12 @@ def __init__(self, document, sampler, dicts, fonts): record, corpus_top = self.__draw_record__(document.record, self.corpus_top) loc_width = corpus_top - self.top - print '--', corpus_top, loc_width, corpus_top - self.corpus_top, '::', self.corpus_min_height, self.corpus_max_height + print('--', corpus_top, loc_width, corpus_top - self.corpus_top, '::', self.corpus_min_height, self.corpus_max_height) if loc_width < self.corpus_max_height: self.records.append(record) - print 'record', num_records + 1, 'append!!!' + print('record', num_records + 1, 'append!!!') self.corpus_top = corpus_top @@ -130,23 +123,23 @@ def __init__(self, document, sampler, dicts, fonts): self.num_records = num_records - print 'final num records', self.num_records + print('final num records', self.num_records) def __draw_record__(self, groups, corpus_top): record = DrawRecord() - print 'num groups', len(groups) + print('num groups', len(groups)) for g, textgroup in enumerate(groups): - print 'group', g+1 + print('group', g+1) if confirm(textgroup.probability): - print 'num lines', len(textgroup.real_lines) + print('num lines', len(textgroup.real_lines)) for l, line in enumerate(textgroup.real_lines): - print 'line', l+1 + print('line', l+1) if line.type == 'TextLine': if confirm(line.probability): @@ -164,7 +157,7 @@ def __draw_record__(self, groups, corpus_top): def __append_text__(self, corpus_top, line, record): record.lines.append((corpus_top, corpus_top + line.height)) - print 'num cells', len(line.cells) + print('num cells', len(line.cells)) text_min_height_prob = line.text_min_height_prob for cell in line.cells: @@ -181,7 +174,7 @@ def __append_text__(self, corpus_top, line, record): cell_x += x_step - print 'cell_x', cell_x, 'cell_width', cell_width + print('cell_x', cell_x, 'cell_width', cell_width) loc_top = corpus_top loc_left = self.corpus_left + cell_x @@ -239,7 +232,7 @@ def create_row(dictonary, number_words, cell, font, max_step=1,min_lenght_first_ if number_words<=0: number_words = np.inf - print 'number words', number_words + print('number words', number_words) np.random.shuffle(dictonary) @@ -253,7 +246,7 @@ def create_row(dictonary, number_words, cell, font, max_step=1,min_lenght_first_ o = iter(dictonary) i = 0 while(True): - word = o.next() + word = next(o) # se siamo alla prima parola rispetto ad aspettarmene almeno 2, allora controllo la lunghezza if i == 0 and len(word)1: @@ -261,7 +254,7 @@ def create_row(dictonary, number_words, cell, font, max_step=1,min_lenght_first_ w, h = draw.textsize(phrase+word, font=font) - print 'text dimension', w, h + print('text dimension', w, h) if i == 0 and w>width: continue @@ -279,8 +272,8 @@ def create_row(dictonary, number_words, cell, font, max_step=1,min_lenght_first_ break if len(phrase)1: - print 'ATTENTION!!!!!!',files[0] - print 'move ttf file', files[0], + print('ATTENTION!!!!!!',files[0]) + print('move ttf file', files[0],) shutil.copy2(files[0], final_path) shutil.rmtree(directory_to_extract_to) + return if not os.path.isdir(final_dir): - os.makedirs(final_dir) + os.makedirs(final_dir, exist_ok=True) loc_file = download(url) final_ttf = os.path.join(final_dir, ttf_name) - print 'final file', + print('final file', final_ttf) unzip_move_delete(loc_file, final_ttf) - print 'remove file', loc_file + print('remove file', loc_file) os.remove(loc_file) + return -# -# -# -# -# -# -# -# -# +# +# +# +# +# +# +# +# +# -directory = 'handwritten' +directory = 'fonts' +# Handwritten fonts download_font('https://dl.dafont.com/dl/?f=a_glitch_in_time',directory, 'A_Glitch_In_Time.ttf') download_font('https://dl.dafont.com/dl/?f=love_letter_tw',directory, 'Lovelt__.ttf') download_font('https://dl.dafont.com/dl/?f=wankstaberg_battles',directory, 'WankstabergBattles.ttf') @@ -75,3 +79,5 @@ def unzip_move_delete(loc_name, final_path, directory_to_extract_to='tmp'): download_font('https://dl.dafont.com/dl/?f=taken_by_vultures',directory, 'Taken_by_Vultures_Demo.otf',ext='otf') download_font('https://dl.dafont.com/dl/?f=lemon_tuesday',directory, 'Lemon_Tuesday.otf',ext='otf') +# Printing fonts +# download_font('https://www.cufonfonts.com/download/font/arial',directory, 'Arial.ttf') diff --git a/test_generate_brandenburg.py b/generate_brandenburg.py similarity index 81% rename from test_generate_brandenburg.py rename to generate_brandenburg.py index cc4ab41..624c508 100644 --- a/test_generate_brandenburg.py +++ b/generate_brandenburg.py @@ -1,10 +1,8 @@ from docemul.generator import generate -def run(dir, num=5, size=None, sampler=None, greyscale=False,type='TXT',model='branden2.xml',seed=2): +def run(dir, num=5, size=None, sampler=None, greyscale=False,type='TXT',model='Data/Brandenburg/branden2.xml',seed=2): generate(dir, num=num, size=size,sampler=sampler, greyscale=greyscale,type=type,model=model,seed=seed) run('GENERATED/Brandenburg/test') - - diff --git a/generate_esposalles_images.py b/generate_esposalles_images.py index 37e9341..f64de8d 100644 --- a/generate_esposalles_images.py +++ b/generate_esposalles_images.py @@ -6,7 +6,7 @@ realSampler = RealBackGound.load_examples() -def run(dir, num=1, size=None, sampler=realSampler, greyscale=True,type='IMG',model='esposalles.xml',seed=1): +def run(dir, num=1, size=None, sampler=realSampler, greyscale=True,type='IMG',model='data/Eesposalles/esposalles.xml',seed=1): generate(dir, num=num, size=size,sampler=sampler, greyscale=greyscale,type=type,model=model,seed=seed) #generate dataset with background @@ -14,7 +14,3 @@ def run(dir, num=1, size=None, sampler=realSampler, greyscale=True,type='IMG',mo #data_augmentation data_augment('GENERATED/Esposalles/test/gt.csv', 'GENERATED/Esposalles/test_augmented',f_output = 'gt_augment.csv',resize=None,rotate=2, rotate_time=1, noise=1) - - - - diff --git a/py-requirements.txt b/py-requirements.txt new file mode 100644 index 0000000..df39e75 --- /dev/null +++ b/py-requirements.txt @@ -0,0 +1,9 @@ +dexml +image +imageio +matplotlib +numpy +pillow +scipy +scikit-learn +scikit-image diff --git a/test_extract_background.py b/test_extract_background.py index bf8f793..d6c1892 100644 --- a/test_extract_background.py +++ b/test_extract_background.py @@ -1,7 +1,5 @@ from docemul import create_background_dataset +create_background_dataset() - -#create_background_dataset() - -print '---' \ No newline at end of file +print('---') diff --git a/test_generate_esposalles.py b/test_generate_esposalles.py deleted file mode 100644 index dbbc107..0000000 --- a/test_generate_esposalles.py +++ /dev/null @@ -1,20 +0,0 @@ -from docemul.generator import generate -from docemul.backgroundmodel import RealBackGound -from docemul.augment import data_augment - -RealBackGound.dirname = 'EXAMPLES/Esposalles/BACKGROUND' - -realSampler = RealBackGound.load_examples() - -def run(dir, num=5, size=None, sampler=realSampler, greyscale=True,type='IMG',model='esposalles.xml',seed=2): - generate(dir, num=num, size=size,sampler=sampler, greyscale=greyscale,type=type,model=model,seed=seed) - -#generate dataset with background -run('GENERATED/Esposalles/test') - -#data_augmentation -data_augment('GENERATED/Esposalles/test/gt.csv', 'GENERATED/Esposalles/test_augmented',f_output = 'gt_augment.csv',resize=None,rotate=2, rotate_time=1, noise=1) - - - -